do not use = {nullptr} initialization. (#11153)
[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     fgCalledCount            = 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         GenTreePtr arg;
334
335 #ifdef FEATURE_READYTORUN_COMPILER
336         if (opts.IsReadyToRun())
337         {
338             mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd);
339
340             CORINFO_RESOLVED_TOKEN resolvedToken;
341             resolvedToken.tokenContext = MAKE_METHODCONTEXT(info.compMethodHnd);
342             resolvedToken.tokenScope   = info.compScopeHnd;
343             resolvedToken.token        = currentMethodToken;
344             resolvedToken.tokenType    = CORINFO_TOKENKIND_Method;
345
346             info.compCompHnd->resolveToken(&resolvedToken);
347
348             arg = impTokenToHandle(&resolvedToken);
349         }
350         else
351 #endif
352         {
353             arg = gtNewIconEmbMethHndNode(info.compMethodHnd);
354         }
355
356         GenTreeArgList* args = gtNewArgList(arg);
357         GenTreePtr      call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, 0, args);
358
359         GenTreePtr handle =
360             gtNewIconEmbHndNode((void*)&bbProfileBufferStart->ExecutionCount, nullptr, GTF_ICON_BBC_PTR);
361         GenTreePtr value = gtNewOperNode(GT_IND, TYP_INT, handle);
362         GenTreePtr relop = gtNewOperNode(GT_NE, TYP_INT, value, gtNewIconNode(0, TYP_INT));
363         relop->gtFlags |= GTF_RELOP_QMARK; // TODO-Cleanup: [Simple]  Move this to gtNewQmarkNode
364         GenTreePtr colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), call);
365         GenTreePtr cond  = gtNewQmarkNode(TYP_VOID, relop, colon);
366         stmt             = gtNewStmt(cond);
367     }
368
369     fgEnsureFirstBBisScratch();
370
371     fgInsertStmtAtEnd(fgFirstBB, stmt);
372 }
373
374 /*****************************************************************************
375  *
376  *  Create a basic block and append it to the current BB list.
377  */
378
379 BasicBlock* Compiler::fgNewBasicBlock(BBjumpKinds jumpKind)
380 {
381     // This method must not be called after the exception table has been
382     // constructed, because it doesn't not provide support for patching
383     // the exception table.
384
385     noway_assert(compHndBBtabCount == 0);
386
387     BasicBlock* block;
388
389     /* Allocate the block descriptor */
390
391     block = bbNewBasicBlock(jumpKind);
392     noway_assert(block->bbJumpKind == jumpKind);
393
394     /* Append the block to the end of the global basic block list */
395
396     if (fgFirstBB)
397     {
398         fgLastBB->setNext(block);
399     }
400     else
401     {
402         fgFirstBB     = block;
403         block->bbPrev = nullptr;
404     }
405
406     fgLastBB = block;
407
408     return block;
409 }
410
411 /*****************************************************************************
412  *
413  *  Ensures that fgFirstBB is a scratch BasicBlock that we have added.
414  *  This can be used to add initialization code (without worrying
415  *  about other blocks jumping to it).
416  *
417  *  Callers have to be careful that they do not mess up the order of things
418  *  added to fgEnsureFirstBBisScratch in a way as to change semantics.
419  */
420
421 void Compiler::fgEnsureFirstBBisScratch()
422 {
423     // This method does not update predecessor lists and so must only be called before they are computed.
424     assert(!fgComputePredsDone);
425
426     // Have we already allocated a scratch block?
427
428     if (fgFirstBBisScratch())
429     {
430         return;
431     }
432
433     assert(fgFirstBBScratch == nullptr);
434
435     BasicBlock* block = bbNewBasicBlock(BBJ_NONE);
436
437     if (fgFirstBB != nullptr)
438     {
439         // If we have profile data the new block will inherit fgFirstBlock's weight
440         if (fgFirstBB->hasProfileWeight())
441         {
442             block->inheritWeight(fgFirstBB);
443         }
444
445         fgInsertBBbefore(fgFirstBB, block);
446     }
447     else
448     {
449         noway_assert(fgLastBB == nullptr);
450         fgFirstBB = block;
451         fgLastBB  = block;
452     }
453
454     noway_assert(fgLastBB != nullptr);
455
456     block->bbFlags |= (BBF_INTERNAL | BBF_IMPORTED);
457
458     fgFirstBBScratch = fgFirstBB;
459
460 #ifdef DEBUG
461     if (verbose)
462     {
463         printf("New scratch BB%02u\n", block->bbNum);
464     }
465 #endif
466 }
467
468 bool Compiler::fgFirstBBisScratch()
469 {
470     if (fgFirstBBScratch != nullptr)
471     {
472         assert(fgFirstBBScratch == fgFirstBB);
473         assert(fgFirstBBScratch->bbFlags & BBF_INTERNAL);
474         assert(fgFirstBBScratch->countOfInEdges() == 1);
475
476         // Normally, the first scratch block is a fall-through block. However, if the block after it was an empty
477         // BBJ_ALWAYS block, it might get removed, and the code that removes it will make the first scratch block
478         // a BBJ_ALWAYS block.
479         assert((fgFirstBBScratch->bbJumpKind == BBJ_NONE) || (fgFirstBBScratch->bbJumpKind == BBJ_ALWAYS));
480
481         return true;
482     }
483     else
484     {
485         return false;
486     }
487 }
488
489 bool Compiler::fgBBisScratch(BasicBlock* block)
490 {
491     return fgFirstBBisScratch() && (block == fgFirstBB);
492 }
493
494 #ifdef DEBUG
495 // Check to see if block contains a statement but don't spend more than a certain
496 // budget doing this per method compiled.
497 // If the budget is exceeded, return 'answerOnBoundExceeded' as the answer.
498 /* static */
499 bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, bool answerOnBoundExceeded /*= true*/)
500 {
501     const __int64 maxLinks = 1000000000;
502
503     assert(stmt->gtOper == GT_STMT);
504
505     __int64* numTraversed = &JitTls::GetCompiler()->compNumStatementLinksTraversed;
506
507     if (*numTraversed > maxLinks)
508     {
509         return answerOnBoundExceeded;
510     }
511
512     GenTree* curr = block->firstStmt();
513     do
514     {
515         (*numTraversed)++;
516         if (curr == stmt)
517         {
518             break;
519         }
520         curr = curr->gtNext;
521     } while (curr);
522     return curr != nullptr;
523 }
524 #endif // DEBUG
525
526 //------------------------------------------------------------------------
527 // fgInsertStmtAtBeg: Insert the given tree or statement at the start of the given basic block.
528 //
529 // Arguments:
530 //    block     - The block into which 'stmt' will be inserted.
531 //    stmt      - The statement to be inserted.
532 //
533 // Return Value:
534 //    Returns the new (potentially) GT_STMT node.
535 //
536 // Notes:
537 //    If 'stmt' is not already a statement, a new statement is created from it.
538 //    We always insert phi statements at the beginning.
539 //    In other cases, if there are any phi assignments and/or an assignment of
540 //    the GT_CATCH_ARG, we insert after those.
541
542 GenTreePtr Compiler::fgInsertStmtAtBeg(BasicBlock* block, GenTreePtr stmt)
543 {
544     if (stmt->gtOper != GT_STMT)
545     {
546         stmt = gtNewStmt(stmt);
547     }
548
549     GenTreePtr list = block->firstStmt();
550
551     if (!stmt->IsPhiDefnStmt())
552     {
553         GenTreePtr insertBeforeStmt = block->FirstNonPhiDefOrCatchArgAsg();
554         if (insertBeforeStmt != nullptr)
555         {
556             return fgInsertStmtBefore(block, insertBeforeStmt, stmt);
557         }
558         else if (list != nullptr)
559         {
560             return fgInsertStmtAtEnd(block, stmt);
561         }
562         // Otherwise, we will simply insert at the beginning, below.
563     }
564
565     /* The new tree will now be the first one of the block */
566
567     block->bbTreeList = stmt;
568     stmt->gtNext      = list;
569
570     /* Are there any statements in the block? */
571
572     if (list)
573     {
574         GenTreePtr last;
575
576         /* There is at least one statement already */
577
578         last = list->gtPrev;
579         noway_assert(last && last->gtNext == nullptr);
580
581         /* Insert the statement in front of the first one */
582
583         list->gtPrev = stmt;
584         stmt->gtPrev = last;
585     }
586     else
587     {
588         /* The block was completely empty */
589
590         stmt->gtPrev = stmt;
591     }
592
593     return stmt;
594 }
595
596 /*****************************************************************************
597  *
598  *  Insert the given tree or statement at the end of the given basic block.
599  *  Returns the (potentially) new GT_STMT node.
600  *  If the block can be a conditional block, use fgInsertStmtNearEnd.
601  */
602
603 GenTreeStmt* Compiler::fgInsertStmtAtEnd(BasicBlock* block, GenTreePtr node)
604 {
605     GenTreePtr   list = block->firstStmt();
606     GenTreeStmt* stmt;
607
608     if (node->gtOper != GT_STMT)
609     {
610         stmt = gtNewStmt(node);
611     }
612     else
613     {
614         stmt = node->AsStmt();
615     }
616
617     assert(stmt->gtNext == nullptr); // We don't set it, and it needs to be this after the insert
618
619     if (list)
620     {
621         GenTreePtr last;
622
623         /* There is at least one statement already */
624
625         last = list->gtPrev;
626         noway_assert(last && last->gtNext == nullptr);
627
628         /* Append the statement after the last one */
629
630         last->gtNext = stmt;
631         stmt->gtPrev = last;
632         list->gtPrev = stmt;
633     }
634     else
635     {
636         /* The block is completely empty */
637
638         block->bbTreeList = stmt;
639         stmt->gtPrev      = stmt;
640     }
641
642     return stmt;
643 }
644
645 /*****************************************************************************
646  *
647  *  Insert the given tree or statement at the end of the given basic block, but before
648  *  the GT_JTRUE, if present.
649  *  Returns the (potentially) new GT_STMT node.
650  */
651
652 GenTreeStmt* Compiler::fgInsertStmtNearEnd(BasicBlock* block, GenTreePtr node)
653 {
654     GenTreeStmt* stmt;
655
656     // This routine can only be used when in tree order.
657     assert(fgOrder == FGOrderTree);
658
659     if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN))
660     {
661         if (node->gtOper != GT_STMT)
662         {
663             stmt = gtNewStmt(node);
664         }
665         else
666         {
667             stmt = node->AsStmt();
668         }
669
670         GenTreeStmt* first = block->firstStmt();
671         noway_assert(first);
672         GenTreeStmt* last = block->lastStmt();
673         noway_assert(last && last->gtNext == nullptr);
674         GenTreePtr after = last->gtPrev;
675
676 #if DEBUG
677         if (block->bbJumpKind == BBJ_COND)
678         {
679             noway_assert(last->gtStmtExpr->gtOper == GT_JTRUE);
680         }
681         else if (block->bbJumpKind == BBJ_RETURN)
682         {
683             noway_assert((last->gtStmtExpr->gtOper == GT_RETURN) || (last->gtStmtExpr->gtOper == GT_JMP) ||
684                          // BBJ_RETURN blocks in functions returning void do not get a GT_RETURN node if they
685                          // have a .tail prefix (even if canTailCall returns false for these calls)
686                          // code:Compiler::impImportBlockCode (search for the RET: label)
687                          // Ditto for real tail calls (all code after them has been removed)
688                          ((last->gtStmtExpr->gtOper == GT_CALL) &&
689                           ((info.compRetType == TYP_VOID) || last->gtStmtExpr->AsCall()->IsTailCall())));
690         }
691         else
692         {
693             noway_assert(block->bbJumpKind == BBJ_SWITCH);
694             noway_assert(last->gtStmtExpr->gtOper == GT_SWITCH);
695         }
696 #endif // DEBUG
697
698         /* Append 'stmt' before 'last' */
699
700         stmt->gtNext = last;
701         last->gtPrev = stmt;
702
703         if (first == last)
704         {
705             /* There is only one stmt in the block */
706
707             block->bbTreeList = stmt;
708             stmt->gtPrev      = last;
709         }
710         else
711         {
712             noway_assert(after && (after->gtNext == last));
713
714             /* Append 'stmt' after 'after' */
715
716             after->gtNext = stmt;
717             stmt->gtPrev  = after;
718         }
719
720         return stmt;
721     }
722     else
723     {
724         return fgInsertStmtAtEnd(block, node);
725     }
726 }
727
728 /*****************************************************************************
729  *
730  *  Insert the given statement "stmt" after GT_STMT node "insertionPoint".
731  *  Returns the newly inserted GT_STMT node.
732  *  Note that the gtPrev list of statement nodes is circular, but the gtNext list is not.
733  */
734
735 GenTreePtr Compiler::fgInsertStmtAfter(BasicBlock* block, GenTreePtr insertionPoint, GenTreePtr stmt)
736 {
737     assert(block->bbTreeList != nullptr);
738     noway_assert(insertionPoint->gtOper == GT_STMT);
739     noway_assert(stmt->gtOper == GT_STMT);
740     assert(fgBlockContainsStatementBounded(block, insertionPoint));
741     assert(!fgBlockContainsStatementBounded(block, stmt, false));
742
743     if (insertionPoint->gtNext == nullptr)
744     {
745         // Ok, we want to insert after the last statement of the block.
746         stmt->gtNext = nullptr;
747         stmt->gtPrev = insertionPoint;
748
749         insertionPoint->gtNext = stmt;
750
751         // Update the backward link of the first statement of the block
752         // to point to the new last statement.
753         assert(block->bbTreeList->gtPrev == insertionPoint);
754         block->bbTreeList->gtPrev = stmt;
755     }
756     else
757     {
758         stmt->gtNext = insertionPoint->gtNext;
759         stmt->gtPrev = insertionPoint;
760
761         insertionPoint->gtNext->gtPrev = stmt;
762         insertionPoint->gtNext         = stmt;
763     }
764
765     return stmt;
766 }
767
768 //  Insert the given tree or statement before GT_STMT node "insertionPoint".
769 //  Returns the newly inserted GT_STMT node.
770
771 GenTreePtr Compiler::fgInsertStmtBefore(BasicBlock* block, GenTreePtr insertionPoint, GenTreePtr stmt)
772 {
773     assert(block->bbTreeList != nullptr);
774     noway_assert(insertionPoint->gtOper == GT_STMT);
775     noway_assert(stmt->gtOper == GT_STMT);
776     assert(fgBlockContainsStatementBounded(block, insertionPoint));
777     assert(!fgBlockContainsStatementBounded(block, stmt, false));
778
779     if (insertionPoint == block->bbTreeList)
780     {
781         // We're inserting before the first statement in the block.
782         GenTreePtr list = block->bbTreeList;
783         GenTreePtr last = list->gtPrev;
784
785         stmt->gtNext = list;
786         stmt->gtPrev = last;
787
788         block->bbTreeList = stmt;
789         list->gtPrev      = stmt;
790     }
791     else
792     {
793         stmt->gtNext = insertionPoint;
794         stmt->gtPrev = insertionPoint->gtPrev;
795
796         insertionPoint->gtPrev->gtNext = stmt;
797         insertionPoint->gtPrev         = stmt;
798     }
799
800     return stmt;
801 }
802
803 /*****************************************************************************
804  *
805  *  Insert the list of statements stmtList after the stmtAfter in block.
806  *  Return the last statement stmtList.
807  */
808
809 GenTreePtr Compiler::fgInsertStmtListAfter(BasicBlock* block,     // the block where stmtAfter is in.
810                                            GenTreePtr  stmtAfter, // the statement where stmtList should be inserted
811                                                                   // after.
812                                            GenTreePtr stmtList)
813 {
814     // Currently we can handle when stmtAfter and stmtList are non-NULL. This makes everything easy.
815     noway_assert(stmtAfter && stmtAfter->gtOper == GT_STMT);
816     noway_assert(stmtList && stmtList->gtOper == GT_STMT);
817
818     GenTreePtr stmtLast = stmtList->gtPrev; // Last statement in a non-empty list, circular in the gtPrev list.
819     noway_assert(stmtLast);
820     noway_assert(stmtLast->gtNext == nullptr);
821
822     GenTreePtr stmtNext = stmtAfter->gtNext;
823
824     if (!stmtNext)
825     {
826         stmtAfter->gtNext         = stmtList;
827         stmtList->gtPrev          = stmtAfter;
828         block->bbTreeList->gtPrev = stmtLast;
829         goto _Done;
830     }
831
832     stmtAfter->gtNext = stmtList;
833     stmtList->gtPrev  = stmtAfter;
834
835     stmtLast->gtNext = stmtNext;
836     stmtNext->gtPrev = stmtLast;
837
838 _Done:
839
840     noway_assert(block->bbTreeList == nullptr || block->bbTreeList->gtPrev->gtNext == nullptr);
841
842     return stmtLast;
843 }
844
845 /*
846     Removes a block from the return block list
847 */
848 void Compiler::fgRemoveReturnBlock(BasicBlock* block)
849 {
850     if (fgReturnBlocks == nullptr)
851     {
852         return;
853     }
854
855     if (fgReturnBlocks->block == block)
856     {
857         // It's the 1st entry, assign new head of list.
858         fgReturnBlocks = fgReturnBlocks->next;
859         return;
860     }
861
862     for (BasicBlockList* retBlocks = fgReturnBlocks; retBlocks->next != nullptr; retBlocks = retBlocks->next)
863     {
864         if (retBlocks->next->block == block)
865         {
866             // Found it; splice it out.
867             retBlocks->next = retBlocks->next->next;
868             return;
869         }
870     }
871 }
872
873 //------------------------------------------------------------------------
874 // fgGetPredForBlock: Find and return the predecessor edge corresponding to a given predecessor block.
875 //
876 // Arguments:
877 //    block -- The block with the predecessor list to operate on.
878 //    blockPred -- The predecessor block to find in the predecessor list.
879 //
880 // Return Value:
881 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
882 //    then returns nullptr.
883 //
884 // Assumptions:
885 //    -- This only works on the full predecessor lists, not the cheap preds lists.
886
887 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred)
888 {
889     noway_assert(block);
890     noway_assert(blockPred);
891     assert(!fgCheapPredsValid);
892
893     flowList* pred;
894
895     for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
896     {
897         if (blockPred == pred->flBlock)
898         {
899             return pred;
900         }
901     }
902
903     return nullptr;
904 }
905
906 //------------------------------------------------------------------------
907 // fgGetPredForBlock: Find and return the predecessor edge corresponding to a given predecessor block.
908 // Also returns the address of the pointer that points to this edge, to make it possible to remove this edge from the
909 // predecessor list without doing another linear search over the edge list.
910 //
911 // Arguments:
912 //    block -- The block with the predecessor list to operate on.
913 //    blockPred -- The predecessor block to find in the predecessor list.
914 //    ptrToPred -- Out parameter: set to the address of the pointer that points to the returned predecessor edge.
915 //
916 // Return Value:
917 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
918 //    then returns nullptr.
919 //
920 // Assumptions:
921 //    -- This only works on the full predecessor lists, not the cheap preds lists.
922
923 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, flowList*** ptrToPred)
924 {
925     assert(block);
926     assert(blockPred);
927     assert(ptrToPred);
928     assert(!fgCheapPredsValid);
929
930     flowList** predPrevAddr;
931     flowList*  pred;
932
933     for (predPrevAddr = &block->bbPreds, pred = *predPrevAddr; pred != nullptr;
934          predPrevAddr = &pred->flNext, pred = *predPrevAddr)
935     {
936         if (blockPred == pred->flBlock)
937         {
938             *ptrToPred = predPrevAddr;
939             return pred;
940         }
941     }
942
943     *ptrToPred = nullptr;
944     return nullptr;
945 }
946
947 //------------------------------------------------------------------------
948 // fgSpliceOutPred: Removes a predecessor edge for a block from the predecessor list.
949 //
950 // Arguments:
951 //    block -- The block with the predecessor list to operate on.
952 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
953 //
954 // Return Value:
955 //    The flowList edge that was removed.
956 //
957 // Assumptions:
958 //    -- "blockPred" must be a predecessor block of "block".
959 //    -- This simply splices out the flowList object. It doesn't update block ref counts, handle duplicate counts, etc.
960 //       For that, use fgRemoveRefPred() or fgRemoveAllRefPred().
961 //    -- This only works on the full predecessor lists, not the cheap preds lists.
962 //
963 // Notes:
964 //    -- This must walk the predecessor list to find the block in question. If the predecessor edge
965 //       is found using fgGetPredForBlock(), consider using the version that hands back the predecessor pointer
966 //       address instead, to avoid this search.
967 //    -- Marks fgModified = true, since the flow graph has changed.
968
969 flowList* Compiler::fgSpliceOutPred(BasicBlock* block, BasicBlock* blockPred)
970 {
971     assert(!fgCheapPredsValid);
972     noway_assert(block->bbPreds);
973
974     flowList* oldEdge = nullptr;
975
976     // Is this the first block in the pred list?
977     if (blockPred == block->bbPreds->flBlock)
978     {
979         oldEdge        = block->bbPreds;
980         block->bbPreds = block->bbPreds->flNext;
981     }
982     else
983     {
984         flowList* pred;
985         for (pred = block->bbPreds; (pred->flNext != nullptr) && (blockPred != pred->flNext->flBlock);
986              pred = pred->flNext)
987         {
988             // empty
989         }
990         oldEdge = pred->flNext;
991         if (oldEdge == nullptr)
992         {
993             noway_assert(!"Should always find the blockPred");
994         }
995         pred->flNext = pred->flNext->flNext;
996     }
997
998     // Any changes to the flow graph invalidate the dominator sets.
999     fgModified = true;
1000
1001     return oldEdge;
1002 }
1003
1004 //------------------------------------------------------------------------
1005 // fgAddRefPred: Increment block->bbRefs by one and add "blockPred" to the predecessor list of "block".
1006 //
1007 // Arguments:
1008 //    block -- A block to operate on.
1009 //    blockPred -- The predecessor block to add to the predecessor list.
1010 //    oldEdge -- Optional (default: nullptr). If non-nullptr, and a new edge is created (and the dup count
1011 //               of an existing edge is not just incremented), the edge weights are copied from this edge.
1012 //    initializingPreds -- Optional (default: false). Only set to "true" when the initial preds computation is
1013 //    happening.
1014 //
1015 // Return Value:
1016 //    The flow edge representing the predecessor.
1017 //
1018 // Assumptions:
1019 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1020 //
1021 // Notes:
1022 //    -- block->bbRefs is incremented by one to account for the reduction in incoming edges.
1023 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
1024 //       the preds themselves aren't touched.
1025 //    -- fgModified is set if a new flow edge is created (but not if an existing flow edge dup count is incremented),
1026 //       indicating that the flow graph shape has changed.
1027
1028 flowList* Compiler::fgAddRefPred(BasicBlock* block,
1029                                  BasicBlock* blockPred,
1030                                  flowList*   oldEdge /* = nullptr */,
1031                                  bool        initializingPreds /* = false */)
1032 {
1033     assert(block != nullptr);
1034     assert(blockPred != nullptr);
1035
1036     block->bbRefs++;
1037
1038     if (!fgComputePredsDone && !initializingPreds)
1039     {
1040         // Why is someone trying to update the preds list when the preds haven't been created?
1041         // Ignore them! This can happen when fgMorph is called before the preds list is created.
1042         return nullptr;
1043     }
1044
1045     assert(!fgCheapPredsValid);
1046
1047     flowList* flow = fgGetPredForBlock(block, blockPred);
1048
1049     if (flow)
1050     {
1051         noway_assert(flow->flDupCount > 0);
1052         flow->flDupCount++;
1053     }
1054     else
1055     {
1056         flow = new (this, CMK_FlowList) flowList();
1057
1058 #if MEASURE_BLOCK_SIZE
1059         genFlowNodeCnt += 1;
1060         genFlowNodeSize += sizeof(flowList);
1061 #endif // MEASURE_BLOCK_SIZE
1062
1063         // Any changes to the flow graph invalidate the dominator sets.
1064         fgModified = true;
1065
1066         // Keep the predecessor list in lowest to highest bbNum order
1067         // This allows us to discover the loops in optFindNaturalLoops
1068         //  from innermost to outermost.
1069
1070         // TODO-Throughput: This search is quadratic if you have many jumps
1071         // to the same target.   We need to either not bother sorting for
1072         // debuggable code, or sort in optFindNaturalLoops, or better, make
1073         // the code in optFindNaturalLoops not depend on order.
1074
1075         flowList** listp = &block->bbPreds;
1076         while (*listp && ((*listp)->flBlock->bbNum < blockPred->bbNum))
1077         {
1078             listp = &(*listp)->flNext;
1079         }
1080
1081         flow->flNext = *listp;
1082         *listp       = flow;
1083
1084         flow->flBlock    = blockPred;
1085         flow->flDupCount = 1;
1086
1087         if (fgHaveValidEdgeWeights)
1088         {
1089             // We are creating an edge from blockPred to block
1090             // and we have already computed the edge weights, so
1091             // we will try to setup this new edge with valid edge weights.
1092             //
1093             if (oldEdge != nullptr)
1094             {
1095                 // If our caller has given us the old edge weights
1096                 // then we will use them.
1097                 //
1098                 flow->flEdgeWeightMin = oldEdge->flEdgeWeightMin;
1099                 flow->flEdgeWeightMax = oldEdge->flEdgeWeightMax;
1100             }
1101             else
1102             {
1103                 // Set the max edge weight to be the minimum of block's or blockPred's weight
1104                 //
1105                 flow->flEdgeWeightMax = min(block->bbWeight, blockPred->bbWeight);
1106
1107                 // If we are inserting a conditional block the minimum weight is zero,
1108                 // otherwise it is the same as the edge's max weight.
1109                 if (blockPred->NumSucc() > 1)
1110                 {
1111                     flow->flEdgeWeightMin = BB_ZERO_WEIGHT;
1112                 }
1113                 else
1114                 {
1115                     flow->flEdgeWeightMin = flow->flEdgeWeightMax;
1116                 }
1117             }
1118         }
1119         else
1120         {
1121             flow->flEdgeWeightMin = BB_ZERO_WEIGHT;
1122             flow->flEdgeWeightMax = BB_MAX_WEIGHT;
1123         }
1124     }
1125     return flow;
1126 }
1127
1128 //------------------------------------------------------------------------
1129 // fgRemoveRefPred: Decrements the reference count of a predecessor edge from "blockPred" to "block",
1130 // removing the edge if it is no longer necessary.
1131 //
1132 // Arguments:
1133 //    block -- A block to operate on.
1134 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
1135 //
1136 // Return Value:
1137 //    If the flow edge was removed (the predecessor has a "dup count" of 1),
1138 //        returns the flow graph edge that was removed. This means "blockPred" is no longer a predecessor of "block".
1139 //    Otherwise, returns nullptr. This means that "blockPred" is still a predecessor of "block" (because "blockPred"
1140 //        is a switch with multiple cases jumping to "block", or a BBJ_COND with both conditional and fall-through
1141 //        paths leading to "block").
1142 //
1143 // Assumptions:
1144 //    -- "blockPred" must be a predecessor block of "block".
1145 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1146 //
1147 // Notes:
1148 //    -- block->bbRefs is decremented by one to account for the reduction in incoming edges.
1149 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
1150 //       the preds themselves aren't touched.
1151 //    -- fgModified is set if a flow edge is removed (but not if an existing flow edge dup count is decremented),
1152 //       indicating that the flow graph shape has changed.
1153
1154 flowList* Compiler::fgRemoveRefPred(BasicBlock* block, BasicBlock* blockPred)
1155 {
1156     noway_assert(block != nullptr);
1157     noway_assert(blockPred != nullptr);
1158
1159     noway_assert(block->countOfInEdges() > 0);
1160     block->bbRefs--;
1161
1162     // Do nothing if we haven't calculated the predecessor list yet.
1163     // Yes, this does happen.
1164     // For example the predecessor lists haven't been created yet when we do fgMorph.
1165     // But fgMorph calls fgFoldConditional, which in turn calls fgRemoveRefPred.
1166     if (!fgComputePredsDone)
1167     {
1168         return nullptr;
1169     }
1170
1171     assert(!fgCheapPredsValid);
1172
1173     flowList** ptrToPred;
1174     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
1175     noway_assert(pred);
1176     noway_assert(pred->flDupCount > 0);
1177
1178     pred->flDupCount--;
1179
1180     if (pred->flDupCount == 0)
1181     {
1182         // Splice out the predecessor edge since it's no longer necessary.
1183         *ptrToPred = pred->flNext;
1184
1185         // Any changes to the flow graph invalidate the dominator sets.
1186         fgModified = true;
1187
1188         return pred;
1189     }
1190     else
1191     {
1192         return nullptr;
1193     }
1194 }
1195
1196 //------------------------------------------------------------------------
1197 // fgRemoveAllRefPreds: Removes a predecessor edge from one block to another, no matter what the "dup count" is.
1198 //
1199 // Arguments:
1200 //    block -- A block to operate on.
1201 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
1202 //
1203 // Return Value:
1204 //    Returns the flow graph edge that was removed. The dup count on the edge is no longer valid.
1205 //
1206 // Assumptions:
1207 //    -- "blockPred" must be a predecessor block of "block".
1208 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1209 //
1210 // Notes:
1211 //    block->bbRefs is decremented to account for the reduction in incoming edges.
1212
1213 flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, BasicBlock* blockPred)
1214 {
1215     assert(block != nullptr);
1216     assert(blockPred != nullptr);
1217     assert(fgComputePredsDone);
1218     assert(!fgCheapPredsValid);
1219     assert(block->countOfInEdges() > 0);
1220
1221     flowList** ptrToPred;
1222     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
1223     assert(pred != nullptr);
1224     assert(pred->flDupCount > 0);
1225
1226     assert(block->bbRefs >= pred->flDupCount);
1227     block->bbRefs -= pred->flDupCount;
1228
1229     // Now splice out the predecessor edge.
1230     *ptrToPred = pred->flNext;
1231
1232     // Any changes to the flow graph invalidate the dominator sets.
1233     fgModified = true;
1234
1235     return pred;
1236 }
1237
1238 //------------------------------------------------------------------------
1239 // fgRemoveAllRefPreds: Remove a predecessor edge, given the address of a pointer to it in the
1240 // predecessor list, no matter what the "dup count" is.
1241 //
1242 // Arguments:
1243 //    block -- A block with the predecessor list to operate on.
1244 //    ptrToPred -- The address of a pointer to the predecessor to remove.
1245 //
1246 // Return Value:
1247 //    The removed predecessor edge. The dup count on the edge is no longer valid.
1248 //
1249 // Assumptions:
1250 //    -- The predecessor edge must be in the predecessor list for "block".
1251 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1252 //
1253 // Notes:
1254 //    block->bbRefs is decremented by the dup count of the predecessor edge, to account for the reduction in incoming
1255 //    edges.
1256
1257 flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, flowList** ptrToPred)
1258 {
1259     assert(block != nullptr);
1260     assert(ptrToPred != nullptr);
1261     assert(fgComputePredsDone);
1262     assert(!fgCheapPredsValid);
1263     assert(block->countOfInEdges() > 0);
1264
1265     flowList* pred = *ptrToPred;
1266     assert(pred != nullptr);
1267     assert(pred->flDupCount > 0);
1268
1269     assert(block->bbRefs >= pred->flDupCount);
1270     block->bbRefs -= pred->flDupCount;
1271
1272     // Now splice out the predecessor edge.
1273     *ptrToPred = pred->flNext;
1274
1275     // Any changes to the flow graph invalidate the dominator sets.
1276     fgModified = true;
1277
1278     return pred;
1279 }
1280
1281 /*
1282     Removes all the appearances of block as predecessor of others
1283 */
1284
1285 void Compiler::fgRemoveBlockAsPred(BasicBlock* block)
1286 {
1287     assert(!fgCheapPredsValid);
1288
1289     PREFIX_ASSUME(block != nullptr);
1290
1291     BasicBlock* bNext;
1292
1293     switch (block->bbJumpKind)
1294     {
1295         case BBJ_CALLFINALLY:
1296             if (!(block->bbFlags & BBF_RETLESS_CALL))
1297             {
1298                 assert(block->isBBCallAlwaysPair());
1299
1300                 /* The block after the BBJ_CALLFINALLY block is not reachable */
1301                 bNext = block->bbNext;
1302
1303                 /* bNext is an unreachable BBJ_ALWAYS block */
1304                 noway_assert(bNext->bbJumpKind == BBJ_ALWAYS);
1305
1306                 while (bNext->countOfInEdges() > 0)
1307                 {
1308                     fgRemoveRefPred(bNext, bNext->bbPreds->flBlock);
1309                 }
1310             }
1311
1312             __fallthrough;
1313
1314         case BBJ_COND:
1315         case BBJ_ALWAYS:
1316         case BBJ_EHCATCHRET:
1317
1318             /* Update the predecessor list for 'block->bbJumpDest' and 'block->bbNext' */
1319             fgRemoveRefPred(block->bbJumpDest, block);
1320
1321             if (block->bbJumpKind != BBJ_COND)
1322             {
1323                 break;
1324             }
1325
1326             /* If BBJ_COND fall through */
1327             __fallthrough;
1328
1329         case BBJ_NONE:
1330
1331             /* Update the predecessor list for 'block->bbNext' */
1332             fgRemoveRefPred(block->bbNext, block);
1333             break;
1334
1335         case BBJ_EHFILTERRET:
1336
1337             block->bbJumpDest->bbRefs++; // To compensate the bbRefs-- inside fgRemoveRefPred
1338             fgRemoveRefPred(block->bbJumpDest, block);
1339             break;
1340
1341         case BBJ_EHFINALLYRET:
1342         {
1343             /* Remove block as the predecessor of the bbNext of all
1344                BBJ_CALLFINALLY blocks calling this finally. No need
1345                to look for BBJ_CALLFINALLY for fault handlers. */
1346
1347             unsigned  hndIndex = block->getHndIndex();
1348             EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
1349
1350             if (ehDsc->HasFinallyHandler())
1351             {
1352                 BasicBlock* begBlk;
1353                 BasicBlock* endBlk;
1354                 ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
1355
1356                 BasicBlock* finBeg = ehDsc->ebdHndBeg;
1357
1358                 for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
1359                 {
1360                     if ((bcall->bbFlags & BBF_REMOVED) || bcall->bbJumpKind != BBJ_CALLFINALLY ||
1361                         bcall->bbJumpDest != finBeg)
1362                     {
1363                         continue;
1364                     }
1365
1366                     assert(bcall->isBBCallAlwaysPair());
1367                     fgRemoveRefPred(bcall->bbNext, block);
1368                 }
1369             }
1370         }
1371         break;
1372
1373         case BBJ_THROW:
1374         case BBJ_RETURN:
1375             break;
1376
1377         case BBJ_SWITCH:
1378         {
1379             unsigned     jumpCnt = block->bbJumpSwt->bbsCount;
1380             BasicBlock** jumpTab = block->bbJumpSwt->bbsDstTab;
1381
1382             do
1383             {
1384                 fgRemoveRefPred(*jumpTab, block);
1385             } while (++jumpTab, --jumpCnt);
1386
1387             break;
1388         }
1389
1390         default:
1391             noway_assert(!"Block doesn't have a valid bbJumpKind!!!!");
1392             break;
1393     }
1394 }
1395
1396 /*****************************************************************************
1397  * fgChangeSwitchBlock:
1398  *
1399  * We have a BBJ_SWITCH jump at 'oldSwitchBlock' and we want to move this
1400  * switch jump over to 'newSwitchBlock'.  All of the blocks that are jumped
1401  * to from jumpTab[] need to have their predecessor lists updated by removing
1402  * the 'oldSwitchBlock' and adding 'newSwitchBlock'.
1403  */
1404
1405 void Compiler::fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSwitchBlock)
1406 {
1407     noway_assert(oldSwitchBlock != nullptr);
1408     noway_assert(newSwitchBlock != nullptr);
1409     noway_assert(oldSwitchBlock->bbJumpKind == BBJ_SWITCH);
1410
1411     unsigned     jumpCnt = oldSwitchBlock->bbJumpSwt->bbsCount;
1412     BasicBlock** jumpTab = oldSwitchBlock->bbJumpSwt->bbsDstTab;
1413
1414     unsigned i;
1415
1416     // Walk the switch's jump table, updating the predecessor for each branch.
1417     for (i = 0; i < jumpCnt; i++)
1418     {
1419         BasicBlock* bJump = jumpTab[i];
1420         noway_assert(bJump != nullptr);
1421
1422         // Note that if there are duplicate branch targets in the switch jump table,
1423         // fgRemoveRefPred()/fgAddRefPred() will do the right thing: the second and
1424         // subsequent duplicates will simply subtract from and add to the duplicate
1425         // count (respectively).
1426
1427         //
1428         // Remove the old edge [oldSwitchBlock => bJump]
1429         //
1430         fgRemoveRefPred(bJump, oldSwitchBlock);
1431
1432         //
1433         // Create the new edge [newSwitchBlock => bJump]
1434         //
1435         fgAddRefPred(bJump, newSwitchBlock);
1436     }
1437
1438     if (m_switchDescMap != nullptr)
1439     {
1440         SwitchUniqueSuccSet uniqueSuccSet;
1441
1442         // If already computed and cached the unique descriptors for the old block, let's
1443         // update those for the new block.
1444         if (m_switchDescMap->Lookup(oldSwitchBlock, &uniqueSuccSet))
1445         {
1446             m_switchDescMap->Set(newSwitchBlock, uniqueSuccSet);
1447         }
1448         else
1449         {
1450             fgInvalidateSwitchDescMapEntry(newSwitchBlock);
1451         }
1452         fgInvalidateSwitchDescMapEntry(oldSwitchBlock);
1453     }
1454 }
1455
1456 /*****************************************************************************
1457  * fgReplaceSwitchJumpTarget:
1458  *
1459  * We have a BBJ_SWITCH at 'blockSwitch' and we want to replace all entries
1460  * in the jumpTab[] such that so that jumps that previously went to
1461  * 'oldTarget' now go to 'newTarget'.
1462  * We also must update the predecessor lists for 'oldTarget' and 'newPred'.
1463  */
1464
1465 void Compiler::fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* newTarget, BasicBlock* oldTarget)
1466 {
1467     noway_assert(blockSwitch != nullptr);
1468     noway_assert(newTarget != nullptr);
1469     noway_assert(oldTarget != nullptr);
1470     noway_assert(blockSwitch->bbJumpKind == BBJ_SWITCH);
1471
1472     // For the jump targets values that match oldTarget of our BBJ_SWITCH
1473     // replace predecessor 'blockSwitch' with 'newTarget'
1474     //
1475
1476     unsigned     jumpCnt = blockSwitch->bbJumpSwt->bbsCount;
1477     BasicBlock** jumpTab = blockSwitch->bbJumpSwt->bbsDstTab;
1478
1479     unsigned i = 0;
1480
1481     // Walk the switch's jump table looking for blocks to update the preds for
1482     while (i < jumpCnt)
1483     {
1484         if (jumpTab[i] == oldTarget) // We will update when jumpTab[i] matches
1485         {
1486             // Remove the old edge [oldTarget from blockSwitch]
1487             //
1488             fgRemoveAllRefPreds(oldTarget, blockSwitch);
1489
1490             //
1491             // Change the jumpTab entry to branch to the new location
1492             //
1493             jumpTab[i] = newTarget;
1494
1495             //
1496             // Create the new edge [newTarget from blockSwitch]
1497             //
1498             flowList* newEdge = fgAddRefPred(newTarget, blockSwitch);
1499
1500             // Now set the correct value of newEdge->flDupCount
1501             // and replace any other jumps in jumpTab[] that go to oldTarget.
1502             //
1503             i++;
1504             while (i < jumpCnt)
1505             {
1506                 if (jumpTab[i] == oldTarget)
1507                 {
1508                     //
1509                     // We also must update this entry in the jumpTab
1510                     //
1511                     jumpTab[i] = newTarget;
1512                     newTarget->bbRefs++;
1513
1514                     //
1515                     // Increment the flDupCount
1516                     //
1517                     newEdge->flDupCount++;
1518                 }
1519                 i++; // Check the next entry in jumpTab[]
1520             }
1521
1522             // Maintain, if necessary, the set of unique targets of "block."
1523             UpdateSwitchTableTarget(blockSwitch, oldTarget, newTarget);
1524
1525             // Make sure the new target has the proper bits set for being a branch target.
1526             newTarget->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
1527
1528             return; // We have replaced the jumps to oldTarget with newTarget
1529         }
1530         i++; // Check the next entry in jumpTab[] for a match
1531     }
1532     noway_assert(!"Did not find oldTarget in jumpTab[]");
1533 }
1534
1535 //------------------------------------------------------------------------
1536 // Compiler::fgReplaceJumpTarget: For a given block, replace the target 'oldTarget' with 'newTarget'.
1537 //
1538 // Arguments:
1539 //    block     - the block in which a jump target will be replaced.
1540 //    newTarget - the new branch target of the block.
1541 //    oldTarget - the old branch target of the block.
1542 //
1543 // Notes:
1544 // 1. Only branches are changed: BBJ_ALWAYS, the non-fallthrough path of BBJ_COND, BBJ_SWITCH, etc.
1545 //    We ignore other block types.
1546 // 2. Only the first target found is updated. If there are multiple ways for a block
1547 //    to reach 'oldTarget' (e.g., multiple arms of a switch), only the first one found is changed.
1548 // 3. The predecessor lists are not changed.
1549 // 4. The switch table "unique successor" cache is invalidated.
1550 //
1551 // This function is most useful early, before the full predecessor lists have been computed.
1552 //
1553 void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget)
1554 {
1555     assert(block != nullptr);
1556
1557     switch (block->bbJumpKind)
1558     {
1559         case BBJ_CALLFINALLY:
1560         case BBJ_COND:
1561         case BBJ_ALWAYS:
1562         case BBJ_EHCATCHRET:
1563         case BBJ_EHFILTERRET:
1564         case BBJ_LEAVE: // This function will be called before import, so we still have BBJ_LEAVE
1565
1566             if (block->bbJumpDest == oldTarget)
1567             {
1568                 block->bbJumpDest = newTarget;
1569             }
1570             break;
1571
1572         case BBJ_NONE:
1573         case BBJ_EHFINALLYRET:
1574         case BBJ_THROW:
1575         case BBJ_RETURN:
1576             break;
1577
1578         case BBJ_SWITCH:
1579             unsigned jumpCnt;
1580             jumpCnt = block->bbJumpSwt->bbsCount;
1581             BasicBlock** jumpTab;
1582             jumpTab = block->bbJumpSwt->bbsDstTab;
1583
1584             for (unsigned i = 0; i < jumpCnt; i++)
1585             {
1586                 if (jumpTab[i] == oldTarget)
1587                 {
1588                     jumpTab[i] = newTarget;
1589                     break;
1590                 }
1591             }
1592             break;
1593
1594         default:
1595             assert(!"Block doesn't have a valid bbJumpKind!!!!");
1596             unreached();
1597             break;
1598     }
1599 }
1600
1601 /*****************************************************************************
1602  * Updates the predecessor list for 'block' by replacing 'oldPred' with 'newPred'.
1603  * Note that a block can only appear once in the preds list (for normal preds, not
1604  * cheap preds): if a predecessor has multiple ways to get to this block, then
1605  * flDupCount will be >1, but the block will still appear exactly once. Thus, this
1606  * function assumes that all branches from the predecessor (practically, that all
1607  * switch cases that target this block) are changed to branch from the new predecessor,
1608  * with the same dup count.
1609  *
1610  * Note that the block bbRefs is not changed, since 'block' has the same number of
1611  * references as before, just from a different predecessor block.
1612  */
1613
1614 void Compiler::fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* newPred)
1615 {
1616     noway_assert(block != nullptr);
1617     noway_assert(oldPred != nullptr);
1618     noway_assert(newPred != nullptr);
1619     assert(!fgCheapPredsValid);
1620
1621     flowList* pred;
1622
1623     for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
1624     {
1625         if (oldPred == pred->flBlock)
1626         {
1627             pred->flBlock = newPred;
1628             break;
1629         }
1630     }
1631 }
1632
1633 /*****************************************************************************
1634  *
1635  *  Returns true if block b1 dominates block b2.
1636  */
1637
1638 bool Compiler::fgDominate(BasicBlock* b1, BasicBlock* b2)
1639 {
1640     noway_assert(fgDomsComputed);
1641     assert(!fgCheapPredsValid);
1642
1643     //
1644     // If the fgModified flag is false then we made some modifications to
1645     // the flow graph, like adding a new block or changing a conditional branch
1646     // into an unconditional branch.
1647     //
1648     // We can continue to use the dominator and reachable information to
1649     // unmark loops as long as we haven't renumbered the blocks or we aren't
1650     // asking for information about a new block
1651     //
1652
1653     if (b2->bbNum > fgDomBBcount)
1654     {
1655         if (b1 == b2)
1656         {
1657             return true;
1658         }
1659
1660         for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext)
1661         {
1662             if (!fgDominate(b1, pred->flBlock))
1663             {
1664                 return false;
1665             }
1666         }
1667
1668         return b2->bbPreds != nullptr;
1669     }
1670
1671     if (b1->bbNum > fgDomBBcount)
1672     {
1673         // if b1 is a loop preheader and Succ is its only successor, then all predecessors of
1674         // Succ either are b1 itself or are dominated by Succ. Under these conditions, b1
1675         // dominates b2 if and only if Succ dominates b2 (or if b2 == b1, but we already tested
1676         // for this case)
1677         if (b1->bbFlags & BBF_LOOP_PREHEADER)
1678         {
1679             noway_assert(b1->bbFlags & BBF_INTERNAL);
1680             noway_assert(b1->bbJumpKind == BBJ_NONE);
1681             return fgDominate(b1->bbNext, b2);
1682         }
1683
1684         // unknown dominators; err on the safe side and return false
1685         return false;
1686     }
1687
1688     /* Check if b1 dominates b2 */
1689     unsigned numA = b1->bbNum;
1690     noway_assert(numA <= fgDomBBcount);
1691     unsigned numB = b2->bbNum;
1692     noway_assert(numB <= fgDomBBcount);
1693
1694     // 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)
1695     // in the dominator tree. Turns out that can be translated as:
1696     //
1697     //   A dom B <-> preorder(A) <= preorder(B) && postorder(A) >= postorder(B)
1698     //
1699     // where the equality holds when you ask if A dominates itself.
1700     bool treeDom =
1701         fgDomTreePreOrder[numA] <= fgDomTreePreOrder[numB] && fgDomTreePostOrder[numA] >= fgDomTreePostOrder[numB];
1702
1703     return treeDom;
1704 }
1705
1706 /*****************************************************************************
1707  *
1708  *  Returns true if block b1 can reach block b2.
1709  */
1710
1711 bool Compiler::fgReachable(BasicBlock* b1, BasicBlock* b2)
1712 {
1713     noway_assert(fgDomsComputed);
1714     assert(!fgCheapPredsValid);
1715
1716     //
1717     // If the fgModified flag is false then we made some modifications to
1718     // the flow graph, like adding a new block or changing a conditional branch
1719     // into an unconditional branch.
1720     //
1721     // We can continue to use the dominator and reachable information to
1722     // unmark loops as long as we haven't renumbered the blocks or we aren't
1723     // asking for information about a new block
1724     //
1725
1726     if (b2->bbNum > fgDomBBcount)
1727     {
1728         if (b1 == b2)
1729         {
1730             return true;
1731         }
1732
1733         for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext)
1734         {
1735             if (fgReachable(b1, pred->flBlock))
1736             {
1737                 return true;
1738             }
1739         }
1740
1741         return false;
1742     }
1743
1744     if (b1->bbNum > fgDomBBcount)
1745     {
1746         noway_assert(b1->bbJumpKind == BBJ_NONE || b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND);
1747
1748         if (b1->bbFallsThrough() && fgReachable(b1->bbNext, b2))
1749         {
1750             return true;
1751         }
1752
1753         if (b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND)
1754         {
1755             return fgReachable(b1->bbJumpDest, b2);
1756         }
1757
1758         return false;
1759     }
1760
1761     /* Check if b1 can reach b2 */
1762     assert(fgReachabilitySetsValid);
1763     assert(BasicBlockBitSetTraits::GetSize(this) == fgDomBBcount + 1);
1764     return BlockSetOps::IsMember(this, b2->bbReach, b1->bbNum);
1765 }
1766
1767 /*****************************************************************************
1768  *  Update changed flow graph information.
1769  *
1770  *  If the flow graph has changed, we need to recompute various information if we want to use
1771  *  it again.
1772  */
1773
1774 void Compiler::fgUpdateChangedFlowGraph()
1775 {
1776     // We need to clear this so we don't hit an assert calling fgRenumberBlocks().
1777     fgDomsComputed = false;
1778
1779     JITDUMP("\nRenumbering the basic blocks for fgUpdateChangeFlowGraph\n");
1780     fgRenumberBlocks();
1781
1782     fgComputePreds();
1783     fgComputeEnterBlocksSet();
1784     fgComputeReachabilitySets();
1785     fgComputeDoms();
1786 }
1787
1788 /*****************************************************************************
1789  *  Compute the bbReach sets.
1790  *
1791  *  This can be called to recompute the bbReach sets after the flow graph changes, such as when the
1792  *  number of BasicBlocks change (and thus, the BlockSet epoch changes).
1793  *
1794  *  Finally, this also sets the BBF_GC_SAFE_POINT flag on blocks.
1795  *
1796  *  Assumes the predecessor lists are correct.
1797  *
1798  *  TODO-Throughput: This algorithm consumes O(n^2) because we're using dense bitsets to
1799  *  represent reachability. While this yields O(1) time queries, it bloats the memory usage
1800  *  for large code.  We can do better if we try to approach reachability by
1801  *  computing the strongly connected components of the flow graph.  That way we only need
1802  *  linear memory to label every block with its SCC.
1803  */
1804
1805 void Compiler::fgComputeReachabilitySets()
1806 {
1807     assert(fgComputePredsDone);
1808     assert(!fgCheapPredsValid);
1809
1810 #ifdef DEBUG
1811     fgReachabilitySetsValid = false;
1812 #endif // DEBUG
1813
1814     BasicBlock* block;
1815
1816     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1817     {
1818         // Initialize the per-block bbReach sets. (Note that we can't just call BlockSetOps::ClearD()
1819         // when re-running this computation, because if the epoch changes, the size and representation of the
1820         // sets might change).
1821         block->bbReach = BlockSetOps::MakeEmpty(this);
1822
1823         /* Mark block as reaching itself */
1824         BlockSetOps::AddElemD(this, block->bbReach, block->bbNum);
1825     }
1826
1827     /* Find the reachable blocks */
1828     // Also, set BBF_GC_SAFE_POINT.
1829
1830     bool     change;
1831     BlockSet BLOCKSET_INIT_NOCOPY(newReach, BlockSetOps::MakeEmpty(this));
1832     do
1833     {
1834         change = false;
1835
1836         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1837         {
1838             BlockSetOps::Assign(this, newReach, block->bbReach);
1839
1840             bool predGcSafe = (block->bbPreds != nullptr); // Do all of our predecessor blocks have a GC safe bit?
1841
1842             for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
1843             {
1844                 BasicBlock* predBlock = pred->flBlock;
1845
1846                 /* Union the predecessor's reachability set into newReach */
1847                 BlockSetOps::UnionD(this, newReach, predBlock->bbReach);
1848
1849                 if (!(predBlock->bbFlags & BBF_GC_SAFE_POINT))
1850                 {
1851                     predGcSafe = false;
1852                 }
1853             }
1854
1855             if (predGcSafe)
1856             {
1857                 block->bbFlags |= BBF_GC_SAFE_POINT;
1858             }
1859
1860             if (!BlockSetOps::Equal(this, newReach, block->bbReach))
1861             {
1862                 BlockSetOps::Assign(this, block->bbReach, newReach);
1863                 change = true;
1864             }
1865         }
1866     } while (change);
1867
1868 #ifdef DEBUG
1869     if (verbose)
1870     {
1871         printf("\nAfter computing reachability sets:\n");
1872         fgDispReach();
1873     }
1874
1875     fgReachabilitySetsValid = true;
1876 #endif // DEBUG
1877 }
1878
1879 /*****************************************************************************
1880  *  Compute the entry blocks set.
1881  *
1882  *  Initialize fgEnterBlks to the set of blocks for which we don't have explicit control
1883  *  flow edges. These are the entry basic block and each of the EH handler blocks.
1884  *  For ARM, also include the BBJ_ALWAYS block of a BBJ_CALLFINALLY/BBJ_ALWAYS pair,
1885  *  to avoid creating "retless" calls, since we need the BBJ_ALWAYS for the purpose
1886  *  of unwinding, even if the call doesn't return (due to an explicit throw, for example).
1887  */
1888
1889 void Compiler::fgComputeEnterBlocksSet()
1890 {
1891 #ifdef DEBUG
1892     fgEnterBlksSetValid = false;
1893 #endif // DEBUG
1894
1895     fgEnterBlks = BlockSetOps::MakeEmpty(this);
1896
1897     /* Now set the entry basic block */
1898     BlockSetOps::AddElemD(this, fgEnterBlks, fgFirstBB->bbNum);
1899     assert(fgFirstBB->bbNum == 1);
1900
1901     if (compHndBBtabCount > 0)
1902     {
1903         /* Also 'or' in the handler basic blocks */
1904         EHblkDsc* HBtab;
1905         EHblkDsc* HBtabEnd;
1906         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
1907         {
1908             if (HBtab->HasFilter())
1909             {
1910                 BlockSetOps::AddElemD(this, fgEnterBlks, HBtab->ebdFilter->bbNum);
1911             }
1912             BlockSetOps::AddElemD(this, fgEnterBlks, HBtab->ebdHndBeg->bbNum);
1913         }
1914     }
1915
1916 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1917     // TODO-ARM-Cleanup: The ARM code here to prevent creating retless calls by adding the BBJ_ALWAYS
1918     // to the enter blocks is a bit of a compromise, because sometimes the blocks are already reachable,
1919     // and it messes up DFS ordering to have them marked as enter block. We should prevent the
1920     // creation of retless calls some other way.
1921     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
1922     {
1923         if (block->bbJumpKind == BBJ_CALLFINALLY)
1924         {
1925             assert(block->isBBCallAlwaysPair());
1926
1927             // Don't remove the BBJ_ALWAYS block that is only here for the unwinder. It might be dead
1928             // if the finally is no-return, so mark it as an entry point.
1929             BlockSetOps::AddElemD(this, fgEnterBlks, block->bbNext->bbNum);
1930         }
1931     }
1932 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1933
1934 #ifdef DEBUG
1935     if (verbose)
1936     {
1937         printf("Enter blocks: ");
1938         BLOCKSET_ITER_INIT(this, iter, fgEnterBlks, bbNum);
1939         while (iter.NextElem(this, &bbNum))
1940         {
1941             printf("BB%02u ", bbNum);
1942         }
1943         printf("\n");
1944     }
1945 #endif // DEBUG
1946
1947 #ifdef DEBUG
1948     fgEnterBlksSetValid = true;
1949 #endif // DEBUG
1950 }
1951
1952 /*****************************************************************************
1953  *  Remove unreachable blocks.
1954  *
1955  *  Return true if any unreachable blocks were removed.
1956  */
1957
1958 bool Compiler::fgRemoveUnreachableBlocks()
1959 {
1960     assert(!fgCheapPredsValid);
1961     assert(fgReachabilitySetsValid);
1962
1963     bool        hasLoops             = false;
1964     bool        hasUnreachableBlocks = false;
1965     BasicBlock* block;
1966
1967     /* Record unreachable blocks */
1968     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1969     {
1970         /* Internal throw blocks are also reachable */
1971         if (fgIsThrowHlpBlk(block))
1972         {
1973             goto SKIP_BLOCK;
1974         }
1975         else if (block == genReturnBB)
1976         {
1977             // Don't remove statements for the genReturnBB block, as we might have special hookups there.
1978             // For example, <BUGNUM> in VSW 364383, </BUGNUM>
1979             // the profiler hookup needs to have the "void GT_RETURN" statement
1980             // to properly set the info.compProfilerCallback flag.
1981             goto SKIP_BLOCK;
1982         }
1983         else
1984         {
1985             // If any of the entry blocks can reach this block, then we skip it.
1986             if (!BlockSetOps::IsEmptyIntersection(this, fgEnterBlks, block->bbReach))
1987             {
1988                 goto SKIP_BLOCK;
1989             }
1990         }
1991
1992         // Remove all the code for the block
1993         fgUnreachableBlock(block);
1994
1995         // Make sure that the block was marked as removed */
1996         noway_assert(block->bbFlags & BBF_REMOVED);
1997
1998         // Some blocks mark the end of trys and catches
1999         // and can't be removed. We convert these into
2000         // empty blocks of type BBJ_THROW
2001
2002         if (block->bbFlags & BBF_DONT_REMOVE)
2003         {
2004             bool bIsBBCallAlwaysPair = block->isBBCallAlwaysPair();
2005
2006             /* Unmark the block as removed, */
2007             /* clear BBF_INTERNAL as well and set BBJ_IMPORTED */
2008
2009             block->bbFlags &= ~(BBF_REMOVED | BBF_INTERNAL | BBF_NEEDS_GCPOLL);
2010             block->bbFlags |= BBF_IMPORTED;
2011             block->bbJumpKind = BBJ_THROW;
2012             block->bbSetRunRarely();
2013
2014 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2015             // If this is a <BBJ_CALLFINALLY, BBJ_ALWAYS> pair, we have to clear BBF_FINALLY_TARGET flag on
2016             // the target node (of BBJ_ALWAYS) since BBJ_CALLFINALLY node is getting converted to a BBJ_THROW.
2017             if (bIsBBCallAlwaysPair)
2018             {
2019                 noway_assert(block->bbNext->bbJumpKind == BBJ_ALWAYS);
2020                 fgClearFinallyTargetBit(block->bbNext->bbJumpDest);
2021             }
2022 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2023         }
2024         else
2025         {
2026             /* We have to call fgRemoveBlock next */
2027             hasUnreachableBlocks = true;
2028         }
2029         continue;
2030
2031     SKIP_BLOCK:;
2032
2033         // if (block->isRunRarely())
2034         //    continue;
2035         if (block->bbJumpKind == BBJ_RETURN)
2036         {
2037             continue;
2038         }
2039
2040         /* Set BBF_LOOP_HEAD if we have backwards branches to this block */
2041
2042         unsigned blockNum = block->bbNum;
2043         for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
2044         {
2045             BasicBlock* predBlock = pred->flBlock;
2046             if (blockNum <= predBlock->bbNum)
2047             {
2048                 if (predBlock->bbJumpKind == BBJ_CALLFINALLY)
2049                 {
2050                     continue;
2051                 }
2052
2053                 /* If block can reach predBlock then we have a loop head */
2054                 if (BlockSetOps::IsMember(this, predBlock->bbReach, blockNum))
2055                 {
2056                     hasLoops = true;
2057
2058                     /* Set the BBF_LOOP_HEAD flag */
2059                     block->bbFlags |= BBF_LOOP_HEAD;
2060                     break;
2061                 }
2062             }
2063         }
2064     }
2065
2066     fgHasLoops = hasLoops;
2067
2068     if (hasUnreachableBlocks)
2069     {
2070         // Now remove the unreachable blocks
2071         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2072         {
2073             //  If we mark the block with BBF_REMOVED then
2074             //  we need to call fgRemovedBlock() on it
2075
2076             if (block->bbFlags & BBF_REMOVED)
2077             {
2078                 fgRemoveBlock(block, true);
2079
2080                 // When we have a BBJ_CALLFINALLY, BBJ_ALWAYS pair; fgRemoveBlock will remove
2081                 // both blocks, so we must advance 1 extra place in the block list
2082                 //
2083                 if (block->isBBCallAlwaysPair())
2084                 {
2085                     block = block->bbNext;
2086                 }
2087             }
2088         }
2089     }
2090
2091     return hasUnreachableBlocks;
2092 }
2093
2094 /*****************************************************************************
2095  *
2096  *  Function called to compute the dominator and reachable sets.
2097  *
2098  *  Assumes the predecessor lists are computed and correct.
2099  */
2100
2101 void Compiler::fgComputeReachability()
2102 {
2103 #ifdef DEBUG
2104     if (verbose)
2105     {
2106         printf("*************** In fgComputeReachability\n");
2107     }
2108
2109     fgVerifyHandlerTab();
2110
2111     // Make sure that the predecessor lists are accurate
2112     assert(fgComputePredsDone);
2113     fgDebugCheckBBlist();
2114 #endif // DEBUG
2115
2116     /* Create a list of all BBJ_RETURN blocks. The head of the list is 'fgReturnBlocks'. */
2117     fgReturnBlocks = nullptr;
2118
2119     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2120     {
2121         // If this is a BBJ_RETURN block, add it to our list of all BBJ_RETURN blocks. This list is only
2122         // used to find return blocks.
2123         if (block->bbJumpKind == BBJ_RETURN)
2124         {
2125             fgReturnBlocks = new (this, CMK_Reachability) BasicBlockList(block, fgReturnBlocks);
2126         }
2127     }
2128
2129     // Compute reachability and then delete blocks determined to be unreachable. If we delete blocks, we
2130     // need to loop, as that might have caused more blocks to become unreachable. This can happen in the
2131     // case where a call to a finally is unreachable and deleted (maybe the call to the finally is
2132     // preceded by a throw or an infinite loop), making the blocks following the finally unreachable.
2133     // However, all EH entry blocks are considered global entry blocks, causing the blocks following the
2134     // call to the finally to stay rooted, until a second round of reachability is done.
2135     // The dominator algorithm expects that all blocks can be reached from the fgEnterBlks set.
2136     unsigned passNum = 1;
2137     bool     changed;
2138     do
2139     {
2140         // Just to be paranoid, avoid infinite loops; fall back to minopts.
2141         if (passNum > 10)
2142         {
2143             noway_assert(!"Too many unreachable block removal loops");
2144         }
2145
2146         /* Walk the flow graph, reassign block numbers to keep them in ascending order */
2147         JITDUMP("\nRenumbering the basic blocks for fgComputeReachability pass #%u\n", passNum);
2148         passNum++;
2149         fgRenumberBlocks();
2150
2151         //
2152         // Compute fgEnterBlks
2153         //
2154
2155         fgComputeEnterBlocksSet();
2156
2157         //
2158         // Compute bbReach
2159         //
2160
2161         fgComputeReachabilitySets();
2162
2163         //
2164         // Use reachability information to delete unreachable blocks.
2165         // Also, determine if the flow graph has loops and set 'fgHasLoops' accordingly.
2166         // Set the BBF_LOOP_HEAD flag on the block target of backwards branches.
2167         //
2168
2169         changed = fgRemoveUnreachableBlocks();
2170
2171     } while (changed);
2172
2173 #ifdef DEBUG
2174     if (verbose)
2175     {
2176         printf("\nAfter computing reachability:\n");
2177         fgDispBasicBlocks(verboseTrees);
2178         printf("\n");
2179     }
2180
2181     fgVerifyHandlerTab();
2182     fgDebugCheckBBlist(true);
2183 #endif // DEBUG
2184
2185     //
2186     // Now, compute the dominators
2187     //
2188
2189     fgComputeDoms();
2190 }
2191
2192 /** In order to be able to compute dominance, we need to first get a DFS reverse post order sort on the basic flow graph
2193   * for the dominance algorithm to operate correctly.  The reason why we need the DFS sort is because
2194   * we will build the dominance sets using the partial order induced by the DFS sorting.  With this
2195   * precondition not holding true, the algorithm doesn't work properly.
2196   */
2197 void Compiler::fgDfsInvPostOrder()
2198 {
2199     // NOTE: This algorithm only pays attention to the actual blocks. It ignores the imaginary entry block.
2200
2201     // visited   :  Once we run the DFS post order sort recursive algorithm, we mark the nodes we visited to avoid
2202     //              backtracking.
2203     BlockSet BLOCKSET_INIT_NOCOPY(visited, BlockSetOps::MakeEmpty(this));
2204
2205     // We begin by figuring out which basic blocks don't have incoming edges and mark them as
2206     // start nodes.  Later on we run the recursive algorithm for each node that we
2207     // mark in this step.
2208     BlockSet_ValRet_T startNodes = fgDomFindStartNodes();
2209
2210     // Make sure fgEnterBlks are still there in startNodes, even if they participate in a loop (i.e., there is
2211     // an incoming edge into the block).
2212     assert(fgEnterBlksSetValid);
2213
2214 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2215     //
2216     //    BlockSetOps::UnionD(this, startNodes, fgEnterBlks);
2217     //
2218     // This causes problems on ARM, because we for BBJ_CALLFINALLY/BBJ_ALWAYS pairs, we add the BBJ_ALWAYS
2219     // to the enter blocks set to prevent flow graph optimizations from removing it and creating retless call finallies
2220     // (BBF_RETLESS_CALL). This leads to an incorrect DFS ordering in some cases, because we start the recursive walk
2221     // from the BBJ_ALWAYS, which is reachable from other blocks. A better solution would be to change ARM to avoid
2222     // creating retless calls in a different way, not by adding BBJ_ALWAYS to fgEnterBlks.
2223     //
2224     // So, let us make sure at least fgFirstBB is still there, even if it participates in a loop.
2225     BlockSetOps::AddElemD(this, startNodes, 1);
2226     assert(fgFirstBB->bbNum == 1);
2227 #else
2228     BlockSetOps::UnionD(this, startNodes, fgEnterBlks);
2229 #endif
2230
2231     assert(BlockSetOps::IsMember(this, startNodes, fgFirstBB->bbNum));
2232
2233     // Call the flowgraph DFS traversal helper.
2234     unsigned postIndex = 1;
2235     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2236     {
2237         // If the block has no predecessors, and we haven't already visited it (because it's in fgEnterBlks but also
2238         // reachable from the first block), go ahead and traverse starting from this block.
2239         if (BlockSetOps::IsMember(this, startNodes, block->bbNum) &&
2240             !BlockSetOps::IsMember(this, visited, block->bbNum))
2241         {
2242             fgDfsInvPostOrderHelper(block, visited, &postIndex);
2243         }
2244     }
2245
2246     // After the DFS reverse postorder is completed, we must have visited all the basic blocks.
2247     noway_assert(postIndex == fgBBcount + 1);
2248     noway_assert(fgBBNumMax == fgBBcount);
2249
2250 #ifdef DEBUG
2251     if (0 && verbose)
2252     {
2253         printf("\nAfter doing a post order traversal of the BB graph, this is the ordering:\n");
2254         for (unsigned i = 1; i <= fgBBNumMax; ++i)
2255         {
2256             printf("%02u -> BB%02u\n", i, fgBBInvPostOrder[i]->bbNum);
2257         }
2258         printf("\n");
2259     }
2260 #endif // DEBUG
2261 }
2262
2263 BlockSet_ValRet_T Compiler::fgDomFindStartNodes()
2264 {
2265     unsigned    j;
2266     BasicBlock* block;
2267
2268     // startNodes ::  A set that represents which basic blocks in the flow graph don't have incoming edges.
2269     // We begin assuming everything is a start block and remove any block that is being referenced by another in its
2270     // successor list.
2271
2272     BlockSet BLOCKSET_INIT_NOCOPY(startNodes, BlockSetOps::MakeFull(this));
2273
2274     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2275     {
2276         unsigned cSucc = block->NumSucc(this);
2277         for (j = 0; j < cSucc; ++j)
2278         {
2279             BasicBlock* succ = block->GetSucc(j, this);
2280             BlockSetOps::RemoveElemD(this, startNodes, succ->bbNum);
2281         }
2282     }
2283
2284 #ifdef DEBUG
2285     if (verbose)
2286     {
2287         printf("\nDominator computation start blocks (those blocks with no incoming edges):\n");
2288         BLOCKSET_ITER_INIT(this, iter, startNodes, bbNum);
2289         while (iter.NextElem(this, &bbNum))
2290         {
2291             printf("BB%02u ", bbNum);
2292         }
2293         printf("\n");
2294     }
2295 #endif // DEBUG
2296
2297     return startNodes;
2298 }
2299
2300 //------------------------------------------------------------------------
2301 // fgDfsInvPostOrderHelper: Helper to assign post-order numbers to blocks.
2302 //
2303 // Arguments:
2304 //    block   - The starting entry block
2305 //    visited - The set of visited blocks
2306 //    count   - Pointer to the Dfs counter
2307 //
2308 // Notes:
2309 //    Compute a non-recursive DFS traversal of the flow graph using an
2310 //    evaluation stack to assign post-order numbers.
2311
2312 void Compiler::fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, unsigned* count)
2313 {
2314     // Assume we haven't visited this node yet (callers ensure this).
2315     assert(!BlockSetOps::IsMember(this, visited, block->bbNum));
2316
2317     // Allocate a local stack to hold the DFS traversal actions necessary
2318     // to compute pre/post-ordering of the control flowgraph.
2319     ArrayStack<DfsBlockEntry> stack(this);
2320
2321     // Push the first block on the stack to seed the traversal.
2322     stack.Push(DfsBlockEntry(DSS_Pre, block));
2323     // Flag the node we just visited to avoid backtracking.
2324     BlockSetOps::AddElemD(this, visited, block->bbNum);
2325
2326     // The search is terminated once all the actions have been processed.
2327     while (stack.Height() != 0)
2328     {
2329         DfsBlockEntry current      = stack.Pop();
2330         BasicBlock*   currentBlock = current.dfsBlock;
2331
2332         if (current.dfsStackState == DSS_Pre)
2333         {
2334             // This is a pre-visit that corresponds to the first time the
2335             // node is encountered in the spanning tree and receives pre-order
2336             // numberings. By pushing the post-action on the stack here we
2337             // are guaranteed to only process it after all of its successors
2338             // pre and post actions are processed.
2339             stack.Push(DfsBlockEntry(DSS_Post, currentBlock));
2340
2341             unsigned cSucc = currentBlock->NumSucc(this);
2342             for (unsigned j = 0; j < cSucc; ++j)
2343             {
2344                 BasicBlock* succ = currentBlock->GetSucc(j, this);
2345
2346                 // If this is a node we haven't seen before, go ahead and process
2347                 if (!BlockSetOps::IsMember(this, visited, succ->bbNum))
2348                 {
2349                     // Push a pre-visit action for this successor onto the stack and
2350                     // mark it as visited in case this block has multiple successors
2351                     // to the same node (multi-graph).
2352                     stack.Push(DfsBlockEntry(DSS_Pre, succ));
2353                     BlockSetOps::AddElemD(this, visited, succ->bbNum);
2354                 }
2355             }
2356         }
2357         else
2358         {
2359             // This is a post-visit that corresponds to the last time the
2360             // node is visited in the spanning tree and only happens after
2361             // all descendents in the spanning tree have had pre and post
2362             // actions applied.
2363
2364             assert(current.dfsStackState == DSS_Post);
2365
2366             unsigned invCount = fgBBcount - *count + 1;
2367             assert(1 <= invCount && invCount <= fgBBNumMax);
2368             fgBBInvPostOrder[invCount] = currentBlock;
2369             currentBlock->bbDfsNum     = invCount;
2370             ++(*count);
2371         }
2372     }
2373 }
2374
2375 void Compiler::fgComputeDoms()
2376 {
2377     assert(!fgCheapPredsValid);
2378
2379 #ifdef DEBUG
2380     if (verbose)
2381     {
2382         printf("*************** In fgComputeDoms\n");
2383     }
2384
2385     fgVerifyHandlerTab();
2386
2387     // Make sure that the predecessor lists are accurate.
2388     // Also check that the blocks are properly, densely numbered (so calling fgRenumberBlocks is not necessary).
2389     fgDebugCheckBBlist(true);
2390
2391     // Assert things related to the BlockSet epoch.
2392     assert(fgBBcount == fgBBNumMax);
2393     assert(BasicBlockBitSetTraits::GetSize(this) == fgBBNumMax + 1);
2394 #endif // DEBUG
2395
2396     BlockSet BLOCKSET_INIT_NOCOPY(processedBlks, BlockSetOps::MakeEmpty(this));
2397
2398     fgBBInvPostOrder = new (this, CMK_DominatorMemory) BasicBlock*[fgBBNumMax + 1];
2399     memset(fgBBInvPostOrder, 0, sizeof(BasicBlock*) * (fgBBNumMax + 1));
2400
2401     fgDfsInvPostOrder();
2402     noway_assert(fgBBInvPostOrder[0] == nullptr);
2403
2404     // flRoot and bbRoot represent an imaginary unique entry point in the flow graph.
2405     // All the orphaned EH blocks and fgFirstBB will temporarily have its predecessors list
2406     // (with bbRoot as the only basic block in it) set as flRoot.
2407     // Later on, we clear their predecessors and let them to be nullptr again.
2408     // Since we number basic blocks starting at one, the imaginary entry block is conveniently numbered as zero.
2409     flowList   flRoot;
2410     BasicBlock bbRoot;
2411
2412     bbRoot.bbPreds  = nullptr;
2413     bbRoot.bbNum    = 0;
2414     bbRoot.bbIDom   = &bbRoot;
2415     bbRoot.bbDfsNum = 0;
2416     bbRoot.bbFlags  = 0;
2417     flRoot.flNext   = nullptr;
2418     flRoot.flBlock  = &bbRoot;
2419
2420     fgBBInvPostOrder[0] = &bbRoot;
2421
2422     // Mark both bbRoot and fgFirstBB processed
2423     BlockSetOps::AddElemD(this, processedBlks, 0); // bbRoot    == block #0
2424     BlockSetOps::AddElemD(this, processedBlks, 1); // fgFirstBB == block #1
2425     assert(fgFirstBB->bbNum == 1);
2426
2427     // Special case fgFirstBB to say its IDom is bbRoot.
2428     fgFirstBB->bbIDom = &bbRoot;
2429
2430     BasicBlock* block = nullptr;
2431
2432     for (block = fgFirstBB->bbNext; block != nullptr; block = block->bbNext)
2433     {
2434         // If any basic block has no predecessors then we flag it as processed and temporarily
2435         // mark its precedessor list to be flRoot.  This makes the flowgraph connected,
2436         // a precondition that is needed by the dominance algorithm to operate properly.
2437         if (block->bbPreds == nullptr)
2438         {
2439             block->bbPreds = &flRoot;
2440             block->bbIDom  = &bbRoot;
2441             BlockSetOps::AddElemD(this, processedBlks, block->bbNum);
2442         }
2443         else
2444         {
2445             block->bbIDom = nullptr;
2446         }
2447     }
2448
2449     // Mark the EH blocks as entry blocks and also flag them as processed.
2450     if (compHndBBtabCount > 0)
2451     {
2452         EHblkDsc* HBtab;
2453         EHblkDsc* HBtabEnd;
2454         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
2455         {
2456             if (HBtab->HasFilter())
2457             {
2458                 HBtab->ebdFilter->bbIDom = &bbRoot;
2459                 BlockSetOps::AddElemD(this, processedBlks, HBtab->ebdFilter->bbNum);
2460             }
2461             HBtab->ebdHndBeg->bbIDom = &bbRoot;
2462             BlockSetOps::AddElemD(this, processedBlks, HBtab->ebdHndBeg->bbNum);
2463         }
2464     }
2465
2466     // Now proceed to compute the immediate dominators for each basic block.
2467     bool changed = true;
2468     while (changed)
2469     {
2470         changed = false;
2471         for (unsigned i = 1; i <= fgBBNumMax;
2472              ++i) // Process each actual block; don't process the imaginary predecessor block.
2473         {
2474             flowList*   first   = nullptr;
2475             BasicBlock* newidom = nullptr;
2476             block               = fgBBInvPostOrder[i];
2477
2478             // If we have a block that has bbRoot as its bbIDom
2479             // it means we flag it as processed and as an entry block so
2480             // in this case we're all set.
2481             if (block->bbIDom == &bbRoot)
2482             {
2483                 continue;
2484             }
2485
2486             // Pick up the first processed predecesor of the current block.
2487             for (first = block->bbPreds; first != nullptr; first = first->flNext)
2488             {
2489                 if (BlockSetOps::IsMember(this, processedBlks, first->flBlock->bbNum))
2490                 {
2491                     break;
2492                 }
2493             }
2494             noway_assert(first != nullptr);
2495
2496             // We assume the first processed predecessor will be the
2497             // immediate dominator and then compute the forward flow analysis.
2498             newidom = first->flBlock;
2499             for (flowList* p = block->bbPreds; p != nullptr; p = p->flNext)
2500             {
2501                 if (p->flBlock == first->flBlock)
2502                 {
2503                     continue;
2504                 }
2505                 if (p->flBlock->bbIDom != nullptr)
2506                 {
2507                     // fgIntersectDom is basically the set intersection between
2508                     // the dominance sets of the new IDom and the current predecessor
2509                     // Since the nodes are ordered in DFS inverse post order and
2510                     // IDom induces a tree, fgIntersectDom actually computes
2511                     // the lowest common ancestor in the dominator tree.
2512                     newidom = fgIntersectDom(p->flBlock, newidom);
2513                 }
2514             }
2515
2516             // If the Immediate dominator changed, assign the new one
2517             // to the current working basic block.
2518             if (block->bbIDom != newidom)
2519             {
2520                 noway_assert(newidom != nullptr);
2521                 block->bbIDom = newidom;
2522                 changed       = true;
2523             }
2524             BlockSetOps::AddElemD(this, processedBlks, block->bbNum);
2525         }
2526     }
2527
2528     // As stated before, once we have computed immediate dominance we need to clear
2529     // all the basic blocks whose predecessor list was set to flRoot.  This
2530     // reverts that and leaves the blocks the same as before.
2531     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2532     {
2533         if (block->bbPreds == &flRoot)
2534         {
2535             block->bbPreds = nullptr;
2536         }
2537     }
2538
2539     fgCompDominatedByExceptionalEntryBlocks();
2540
2541 #ifdef DEBUG
2542     if (verbose)
2543     {
2544         fgDispDoms();
2545     }
2546 #endif
2547
2548     fgBuildDomTree();
2549
2550     fgModified   = false;
2551     fgDomBBcount = fgBBcount;
2552     assert(fgBBcount == fgBBNumMax);
2553     assert(BasicBlockBitSetTraits::GetSize(this) == fgDomBBcount + 1);
2554
2555     fgDomsComputed = true;
2556 }
2557
2558 void Compiler::fgBuildDomTree()
2559 {
2560     unsigned    i;
2561     BasicBlock* block;
2562
2563 #ifdef DEBUG
2564     if (verbose)
2565     {
2566         printf("\nInside fgBuildDomTree\n");
2567     }
2568 #endif // DEBUG
2569
2570     // domTree :: The dominance tree represented using adjacency lists. We use BasicBlockList to represent edges.
2571     // Indexed by basic block number.
2572     unsigned         bbArraySize = fgBBNumMax + 1;
2573     BasicBlockList** domTree     = new (this, CMK_DominatorMemory) BasicBlockList*[bbArraySize];
2574
2575     fgDomTreePreOrder  = new (this, CMK_DominatorMemory) unsigned[bbArraySize];
2576     fgDomTreePostOrder = new (this, CMK_DominatorMemory) unsigned[bbArraySize];
2577
2578     // Initialize all the data structures.
2579     for (i = 0; i < bbArraySize; ++i)
2580     {
2581         domTree[i]           = nullptr;
2582         fgDomTreePreOrder[i] = fgDomTreePostOrder[i] = 0;
2583     }
2584
2585     // Build the dominance tree.
2586     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2587     {
2588         // If the immediate dominator is not the imaginary root (bbRoot)
2589         // we proceed to append this block to the children of the dominator node.
2590         if (block->bbIDom->bbNum != 0)
2591         {
2592             int bbNum      = block->bbIDom->bbNum;
2593             domTree[bbNum] = new (this, CMK_DominatorMemory) BasicBlockList(block, domTree[bbNum]);
2594         }
2595         else
2596         {
2597             // This means this block had bbRoot set as its IDom.  We clear it out
2598             // and convert the tree back to a forest.
2599             block->bbIDom = nullptr;
2600         }
2601     }
2602
2603 #ifdef DEBUG
2604     if (verbose)
2605     {
2606         printf("\nAfter computing the Dominance Tree:\n");
2607         fgDispDomTree(domTree);
2608     }
2609 #endif // DEBUG
2610
2611     // Get the bitset that represents the roots of the dominance tree.
2612     // Something to note here is that the dominance tree has been converted from a forest to a tree
2613     // by using the bbRoot trick on fgComputeDoms. The reason we have a forest instead of a real tree
2614     // is because we treat the EH blocks as entry nodes so the real dominance tree is not necessarily connected.
2615     BlockSet_ValRet_T domTreeEntryNodes = fgDomTreeEntryNodes(domTree);
2616
2617     // The preorder and postorder numbers.
2618     // We start from 1 to match the bbNum ordering.
2619     unsigned preNum  = 1;
2620     unsigned postNum = 1;
2621
2622     // There will be nodes in the dominance tree that will not be reachable:
2623     // the catch blocks that return since they don't have any predecessor.
2624     // For that matter we'll keep track of how many nodes we can
2625     // reach and assert at the end that we visited all of them.
2626     unsigned domTreeReachable = fgBBcount;
2627
2628     // Once we have the dominance tree computed, we need to traverse it
2629     // to get the preorder and postorder numbers for each node.  The purpose of
2630     // this is to achieve O(1) queries for of the form A dominates B.
2631     for (i = 1; i <= fgBBNumMax; ++i)
2632     {
2633         if (BlockSetOps::IsMember(this, domTreeEntryNodes, i))
2634         {
2635             if (domTree[i] == nullptr)
2636             {
2637                 // If this is an entry node but there's no children on this
2638                 // node, it means it's unreachable so we decrement the reachable
2639                 // counter.
2640                 --domTreeReachable;
2641             }
2642             else
2643             {
2644                 // Otherwise, we do a DFS traversal of the dominator tree.
2645                 fgTraverseDomTree(i, domTree, &preNum, &postNum);
2646             }
2647         }
2648     }
2649
2650     noway_assert(preNum == domTreeReachable + 1);
2651     noway_assert(postNum == domTreeReachable + 1);
2652
2653     // Once we have all the reachable nodes numbered, we proceed to
2654     // assign numbers to the non-reachable ones, just assign incrementing
2655     // values.  We must reach fgBBcount at the end.
2656
2657     for (i = 1; i <= fgBBNumMax; ++i)
2658     {
2659         if (BlockSetOps::IsMember(this, domTreeEntryNodes, i))
2660         {
2661             if (domTree[i] == nullptr)
2662             {
2663                 fgDomTreePreOrder[i]  = preNum++;
2664                 fgDomTreePostOrder[i] = postNum++;
2665             }
2666         }
2667     }
2668
2669     noway_assert(preNum == fgBBNumMax + 1);
2670     noway_assert(postNum == fgBBNumMax + 1);
2671     noway_assert(fgDomTreePreOrder[0] == 0);  // Unused first element
2672     noway_assert(fgDomTreePostOrder[0] == 0); // Unused first element
2673
2674 #ifdef DEBUG
2675     if (0 && verbose)
2676     {
2677         printf("\nAfter traversing the dominance tree:\n");
2678         printf("PreOrder:\n");
2679         for (i = 1; i <= fgBBNumMax; ++i)
2680         {
2681             printf("BB%02u : %02u\n", i, fgDomTreePreOrder[i]);
2682         }
2683         printf("PostOrder:\n");
2684         for (i = 1; i <= fgBBNumMax; ++i)
2685         {
2686             printf("BB%02u : %02u\n", i, fgDomTreePostOrder[i]);
2687         }
2688     }
2689 #endif // DEBUG
2690 }
2691
2692 BlockSet_ValRet_T Compiler::fgDomTreeEntryNodes(BasicBlockList** domTree)
2693 {
2694     // domTreeEntryNodes ::  Set that represents which basic blocks are roots of the dominator forest.
2695
2696     BlockSet BLOCKSET_INIT_NOCOPY(domTreeEntryNodes, BlockSetOps::MakeFull(this));
2697
2698     // First of all we need to find all the roots of the dominance forest.
2699
2700     for (unsigned i = 1; i <= fgBBNumMax; ++i)
2701     {
2702         for (BasicBlockList* current = domTree[i]; current != nullptr; current = current->next)
2703         {
2704             BlockSetOps::RemoveElemD(this, domTreeEntryNodes, current->block->bbNum);
2705         }
2706     }
2707
2708     return domTreeEntryNodes;
2709 }
2710
2711 #ifdef DEBUG
2712 void Compiler::fgDispDomTree(BasicBlockList** domTree)
2713 {
2714     for (unsigned i = 1; i <= fgBBNumMax; ++i)
2715     {
2716         if (domTree[i] != nullptr)
2717         {
2718             printf("BB%02u : ", i);
2719             for (BasicBlockList* current = domTree[i]; current != nullptr; current = current->next)
2720             {
2721                 assert(current->block);
2722                 printf("BB%02u ", current->block->bbNum);
2723             }
2724             printf("\n");
2725         }
2726     }
2727     printf("\n");
2728 }
2729 #endif // DEBUG
2730
2731 //------------------------------------------------------------------------
2732 // fgTraverseDomTree: Assign pre/post-order numbers to the dominator tree.
2733 //
2734 // Arguments:
2735 //    bbNum   - The basic block number of the starting block
2736 //    domTree - The dominator tree (as child block lists)
2737 //    preNum  - Pointer to the pre-number counter
2738 //    postNum - Pointer to the post-number counter
2739 //
2740 // Notes:
2741 //    Runs a non-recursive DFS traversal of the dominator tree using an
2742 //    evaluation stack to assign pre-order and post-order numbers.
2743 //    These numberings are used to provide constant time lookup for
2744 //    ancestor/descendent tests between pairs of nodes in the tree.
2745
2746 void Compiler::fgTraverseDomTree(unsigned bbNum, BasicBlockList** domTree, unsigned* preNum, unsigned* postNum)
2747 {
2748     noway_assert(bbNum <= fgBBNumMax);
2749
2750     // If the block preorder number is not zero it means we already visited
2751     // that node, so we skip it.
2752     if (fgDomTreePreOrder[bbNum] == 0)
2753     {
2754         // If this is the first time we visit this node, both preorder and postnumber
2755         // values must be zero.
2756         noway_assert(fgDomTreePostOrder[bbNum] == 0);
2757
2758         // Allocate a local stack to hold the Dfs traversal actions necessary
2759         // to compute pre/post-ordering of the dominator tree.
2760         ArrayStack<DfsNumEntry> stack(this);
2761
2762         // Push the first entry number on the stack to seed the traversal.
2763         stack.Push(DfsNumEntry(DSS_Pre, bbNum));
2764
2765         // The search is terminated once all the actions have been processed.
2766         while (stack.Height() != 0)
2767         {
2768             DfsNumEntry current    = stack.Pop();
2769             unsigned    currentNum = current.dfsNum;
2770
2771             if (current.dfsStackState == DSS_Pre)
2772             {
2773                 // This pre-visit action corresponds to the first time the
2774                 // node is encountered during the spanning traversal.
2775                 noway_assert(fgDomTreePreOrder[currentNum] == 0);
2776                 noway_assert(fgDomTreePostOrder[currentNum] == 0);
2777
2778                 // Assign the preorder number on the first visit.
2779                 fgDomTreePreOrder[currentNum] = (*preNum)++;
2780
2781                 // Push this nodes post-action on the stack such that all successors
2782                 // pre-order visits occur before this nodes post-action. We will assign
2783                 // its post-order numbers when we pop off the stack.
2784                 stack.Push(DfsNumEntry(DSS_Post, currentNum));
2785
2786                 // For each child in the dominator tree process its pre-actions.
2787                 for (BasicBlockList* child = domTree[currentNum]; child != nullptr; child = child->next)
2788                 {
2789                     unsigned childNum = child->block->bbNum;
2790
2791                     // This is a tree so never could have been visited
2792                     assert(fgDomTreePreOrder[childNum] == 0);
2793
2794                     // Push the successor in the dominator tree for pre-actions.
2795                     stack.Push(DfsNumEntry(DSS_Pre, childNum));
2796                 }
2797             }
2798             else
2799             {
2800                 // This post-visit action corresponds to the last time the node
2801                 // is encountered and only after all descendents in the spanning
2802                 // tree have had pre and post-order numbers assigned.
2803
2804                 assert(current.dfsStackState == DSS_Post);
2805                 assert(fgDomTreePreOrder[currentNum] != 0);
2806                 assert(fgDomTreePostOrder[currentNum] == 0);
2807
2808                 // Now assign this nodes post-order number.
2809                 fgDomTreePostOrder[currentNum] = (*postNum)++;
2810             }
2811         }
2812     }
2813 }
2814
2815 // This code finds the lowest common ancestor in the
2816 // dominator tree between two basic blocks. The LCA in the Dominance tree
2817 // represents the closest dominator between the two basic blocks. Used to
2818 // adjust the IDom value in fgComputDoms.
2819 BasicBlock* Compiler::fgIntersectDom(BasicBlock* a, BasicBlock* b)
2820 {
2821     BasicBlock* finger1 = a;
2822     BasicBlock* finger2 = b;
2823     while (finger1 != finger2)
2824     {
2825         while (finger1->bbDfsNum > finger2->bbDfsNum)
2826         {
2827             finger1 = finger1->bbIDom;
2828         }
2829         while (finger2->bbDfsNum > finger1->bbDfsNum)
2830         {
2831             finger2 = finger2->bbIDom;
2832         }
2833     }
2834     return finger1;
2835 }
2836
2837 // Return a BlockSet containing all the blocks that dominate 'block'.
2838 BlockSet_ValRet_T Compiler::fgGetDominatorSet(BasicBlock* block)
2839 {
2840     assert(block != nullptr);
2841
2842     BlockSet BLOCKSET_INIT_NOCOPY(domSet, BlockSetOps::MakeEmpty(this));
2843
2844     do
2845     {
2846         BlockSetOps::AddElemD(this, domSet, block->bbNum);
2847         if (block == block->bbIDom)
2848         {
2849             break; // We found a cycle in the IDom list, so we're done.
2850         }
2851         block = block->bbIDom;
2852     } while (block != nullptr);
2853
2854     return domSet;
2855 }
2856
2857 /*****************************************************************************
2858  *
2859  *  fgComputeCheapPreds: Function called to compute the BasicBlock::bbCheapPreds lists.
2860  *
2861  *  No other block data is changed (e.g., bbRefs, bbFlags).
2862  *
2863  *  The cheap preds lists are similar to the normal (bbPreds) predecessor lists, but are cheaper to
2864  *  compute and store, as follows:
2865  *  1. A flow edge is typed BasicBlockList, which only has a block pointer and 'next' pointer. It doesn't
2866  *     have weights or a dup count.
2867  *  2. The preds list for a block is not sorted by block number.
2868  *  3. The predecessors of the block following a BBJ_CALLFINALLY (the corresponding BBJ_ALWAYS,
2869  *     for normal, non-retless calls to the finally) are not computed.
2870  *  4. The cheap preds lists will contain duplicates if a single switch table has multiple branches
2871  *     to the same block. Thus, we don't spend the time looking for duplicates for every edge we insert.
2872  */
2873 void Compiler::fgComputeCheapPreds()
2874 {
2875     noway_assert(!fgComputePredsDone); // We can't do this if we've got the full preds.
2876     noway_assert(fgFirstBB != nullptr);
2877
2878     BasicBlock* block;
2879
2880 #ifdef DEBUG
2881     if (verbose)
2882     {
2883         printf("\n*************** In fgComputeCheapPreds()\n");
2884         fgDispBasicBlocks();
2885         printf("\n");
2886     }
2887 #endif // DEBUG
2888
2889     // Clear out the cheap preds lists.
2890     fgRemovePreds();
2891
2892     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2893     {
2894         switch (block->bbJumpKind)
2895         {
2896             case BBJ_COND:
2897                 fgAddCheapPred(block->bbJumpDest, block);
2898                 fgAddCheapPred(block->bbNext, block);
2899                 break;
2900
2901             case BBJ_CALLFINALLY:
2902             case BBJ_LEAVE: // If fgComputeCheapPreds is called before all blocks are imported, BBJ_LEAVE blocks are
2903                             // still in the BB list.
2904             case BBJ_ALWAYS:
2905             case BBJ_EHCATCHRET:
2906                 fgAddCheapPred(block->bbJumpDest, block);
2907                 break;
2908
2909             case BBJ_NONE:
2910                 fgAddCheapPred(block->bbNext, block);
2911                 break;
2912
2913             case BBJ_EHFILTERRET:
2914                 // Connect end of filter to catch handler.
2915                 // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
2916                 // fgComputeCheapPreds before fgImport on an ill-formed program; the problem will be detected in
2917                 // fgImport.
2918                 if (block->bbJumpDest != nullptr)
2919                 {
2920                     fgAddCheapPred(block->bbJumpDest, block);
2921                 }
2922                 break;
2923
2924             case BBJ_SWITCH:
2925                 unsigned jumpCnt;
2926                 jumpCnt = block->bbJumpSwt->bbsCount;
2927                 BasicBlock** jumpTab;
2928                 jumpTab = block->bbJumpSwt->bbsDstTab;
2929
2930                 do
2931                 {
2932                     fgAddCheapPred(*jumpTab, block);
2933                 } while (++jumpTab, --jumpCnt);
2934
2935                 break;
2936
2937             case BBJ_EHFINALLYRET: // It's expensive to compute the preds for this case, so we don't for the cheap
2938                                    // preds.
2939             case BBJ_THROW:
2940             case BBJ_RETURN:
2941                 break;
2942
2943             default:
2944                 noway_assert(!"Unexpected bbJumpKind");
2945                 break;
2946         }
2947     }
2948
2949     fgCheapPredsValid = true;
2950
2951 #ifdef DEBUG
2952     if (verbose)
2953     {
2954         printf("\n*************** After fgComputeCheapPreds()\n");
2955         fgDispBasicBlocks();
2956         printf("\n");
2957     }
2958 #endif
2959 }
2960
2961 /*****************************************************************************
2962  * Add 'blockPred' to the cheap predecessor list of 'block'.
2963  */
2964
2965 void Compiler::fgAddCheapPred(BasicBlock* block, BasicBlock* blockPred)
2966 {
2967     assert(!fgComputePredsDone);
2968     assert(block != nullptr);
2969     assert(blockPred != nullptr);
2970
2971     block->bbCheapPreds = new (this, CMK_FlowList) BasicBlockList(blockPred, block->bbCheapPreds);
2972
2973 #if MEASURE_BLOCK_SIZE
2974     genFlowNodeCnt += 1;
2975     genFlowNodeSize += sizeof(BasicBlockList);
2976 #endif // MEASURE_BLOCK_SIZE
2977 }
2978
2979 /*****************************************************************************
2980  * Remove 'blockPred' from the cheap predecessor list of 'block'.
2981  * If there are duplicate edges, only remove one of them.
2982  */
2983 void Compiler::fgRemoveCheapPred(BasicBlock* block, BasicBlock* blockPred)
2984 {
2985     assert(!fgComputePredsDone);
2986     assert(fgCheapPredsValid);
2987
2988     flowList* oldEdge = nullptr;
2989
2990     assert(block != nullptr);
2991     assert(blockPred != nullptr);
2992     assert(block->bbCheapPreds != nullptr);
2993
2994     /* Is this the first block in the pred list? */
2995     if (blockPred == block->bbCheapPreds->block)
2996     {
2997         block->bbCheapPreds = block->bbCheapPreds->next;
2998     }
2999     else
3000     {
3001         BasicBlockList* pred;
3002         for (pred = block->bbCheapPreds; pred->next != nullptr; pred = pred->next)
3003         {
3004             if (blockPred == pred->next->block)
3005             {
3006                 break;
3007             }
3008         }
3009         noway_assert(pred->next != nullptr); // we better have found it!
3010         pred->next = pred->next->next;       // splice it out
3011     }
3012 }
3013
3014 void Compiler::fgRemovePreds()
3015 {
3016     C_ASSERT(offsetof(BasicBlock, bbPreds) ==
3017              offsetof(BasicBlock, bbCheapPreds)); // bbPreds and bbCheapPreds are at the same place in a union,
3018     C_ASSERT(sizeof(((BasicBlock*)nullptr)->bbPreds) ==
3019              sizeof(((BasicBlock*)nullptr)->bbCheapPreds)); // and are the same size. So, this function removes both.
3020
3021     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
3022     {
3023         block->bbPreds = nullptr;
3024     }
3025     fgComputePredsDone = false;
3026     fgCheapPredsValid  = false;
3027 }
3028
3029 /*****************************************************************************
3030  *
3031  *  Function called to compute the bbPreds lists.
3032  */
3033 void Compiler::fgComputePreds()
3034 {
3035     noway_assert(fgFirstBB);
3036
3037     BasicBlock* block;
3038
3039 #ifdef DEBUG
3040     if (verbose)
3041     {
3042         printf("\n*************** In fgComputePreds()\n");
3043         fgDispBasicBlocks();
3044         printf("\n");
3045     }
3046 #endif // DEBUG
3047
3048     // reset the refs count for each basic block
3049
3050     for (block = fgFirstBB; block; block = block->bbNext)
3051     {
3052         block->bbRefs = 0;
3053     }
3054
3055     /* the first block is always reachable! */
3056     fgFirstBB->bbRefs = 1;
3057
3058     /* Treat the initial block as a jump target */
3059     fgFirstBB->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3060
3061     fgRemovePreds();
3062
3063     for (block = fgFirstBB; block; block = block->bbNext)
3064     {
3065         switch (block->bbJumpKind)
3066         {
3067             case BBJ_CALLFINALLY:
3068                 if (!(block->bbFlags & BBF_RETLESS_CALL))
3069                 {
3070                     assert(block->isBBCallAlwaysPair());
3071
3072                     /* Mark the next block as being a jump target,
3073                        since the call target will return there */
3074                     PREFIX_ASSUME(block->bbNext != nullptr);
3075                     block->bbNext->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
3076                 }
3077
3078                 __fallthrough;
3079
3080             case BBJ_LEAVE: // Sometimes fgComputePreds is called before all blocks are imported, so BBJ_LEAVE
3081                             // blocks are still in the BB list.
3082             case BBJ_COND:
3083             case BBJ_ALWAYS:
3084             case BBJ_EHCATCHRET:
3085
3086                 /* Mark the jump dest block as being a jump target */
3087                 block->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3088
3089                 fgAddRefPred(block->bbJumpDest, block, nullptr, true);
3090
3091                 /* Is the next block reachable? */
3092
3093                 if (block->bbJumpKind != BBJ_COND)
3094                 {
3095                     break;
3096                 }
3097
3098                 noway_assert(block->bbNext);
3099
3100                 /* Fall through, the next block is also reachable */
3101                 __fallthrough;
3102
3103             case BBJ_NONE:
3104
3105                 fgAddRefPred(block->bbNext, block, nullptr, true);
3106                 break;
3107
3108             case BBJ_EHFILTERRET:
3109
3110                 // Connect end of filter to catch handler.
3111                 // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
3112                 // fgComputePreds before fgImport on an ill-formed program; the problem will be detected in fgImport.
3113                 if (block->bbJumpDest != nullptr)
3114                 {
3115                     fgAddRefPred(block->bbJumpDest, block, nullptr, true);
3116                 }
3117                 break;
3118
3119             case BBJ_EHFINALLYRET:
3120             {
3121                 /* Connect the end of the finally to the successor of
3122                   the call to this finally */
3123
3124                 if (!block->hasHndIndex())
3125                 {
3126                     NO_WAY("endfinally outside a finally/fault block.");
3127                 }
3128
3129                 unsigned  hndIndex = block->getHndIndex();
3130                 EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
3131
3132                 if (!ehDsc->HasFinallyOrFaultHandler())
3133                 {
3134                     NO_WAY("endfinally outside a finally/fault block.");
3135                 }
3136
3137                 if (ehDsc->HasFinallyHandler())
3138                 {
3139                     // Find all BBJ_CALLFINALLY that branched to this finally handler.
3140                     BasicBlock* begBlk;
3141                     BasicBlock* endBlk;
3142                     ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
3143
3144                     BasicBlock* finBeg = ehDsc->ebdHndBeg;
3145                     for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
3146                     {
3147                         if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
3148                         {
3149                             continue;
3150                         }
3151
3152                         noway_assert(bcall->isBBCallAlwaysPair());
3153                         fgAddRefPred(bcall->bbNext, block, nullptr, true);
3154                     }
3155                 }
3156             }
3157             break;
3158
3159             case BBJ_THROW:
3160             case BBJ_RETURN:
3161                 break;
3162
3163             case BBJ_SWITCH:
3164                 unsigned jumpCnt;
3165                 jumpCnt = block->bbJumpSwt->bbsCount;
3166                 BasicBlock** jumpTab;
3167                 jumpTab = block->bbJumpSwt->bbsDstTab;
3168
3169                 do
3170                 {
3171                     /* Mark the target block as being a jump target */
3172                     (*jumpTab)->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3173
3174                     fgAddRefPred(*jumpTab, block, nullptr, true);
3175                 } while (++jumpTab, --jumpCnt);
3176
3177                 break;
3178
3179             default:
3180                 noway_assert(!"Unexpected bbJumpKind");
3181                 break;
3182         }
3183     }
3184
3185     for (unsigned EHnum = 0; EHnum < compHndBBtabCount; EHnum++)
3186     {
3187         EHblkDsc* ehDsc = ehGetDsc(EHnum);
3188
3189         if (ehDsc->HasFilter())
3190         {
3191             ehDsc->ebdFilter->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3192         }
3193
3194         ehDsc->ebdHndBeg->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3195     }
3196
3197     fgModified         = false;
3198     fgComputePredsDone = true;
3199
3200 #ifdef DEBUG
3201     if (verbose)
3202     {
3203         printf("\n*************** After fgComputePreds()\n");
3204         fgDispBasicBlocks();
3205         printf("\n");
3206     }
3207 #endif
3208 }
3209
3210 unsigned Compiler::fgNSuccsOfFinallyRet(BasicBlock* block)
3211 {
3212     BasicBlock* bb;
3213     unsigned    res;
3214     fgSuccOfFinallyRetWork(block, ~0, &bb, &res);
3215     return res;
3216 }
3217
3218 BasicBlock* Compiler::fgSuccOfFinallyRet(BasicBlock* block, unsigned i)
3219 {
3220     BasicBlock* bb;
3221     unsigned    res;
3222     fgSuccOfFinallyRetWork(block, i, &bb, &res);
3223     return bb;
3224 }
3225
3226 void Compiler::fgSuccOfFinallyRetWork(BasicBlock* block, unsigned i, BasicBlock** bres, unsigned* nres)
3227 {
3228     assert(block->hasHndIndex()); // Otherwise, endfinally outside a finally/fault block?
3229
3230     unsigned  hndIndex = block->getHndIndex();
3231     EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
3232
3233     assert(ehDsc->HasFinallyOrFaultHandler()); // Otherwise, endfinally outside a finally/fault block.
3234
3235     *bres            = nullptr;
3236     unsigned succNum = 0;
3237
3238     if (ehDsc->HasFinallyHandler())
3239     {
3240         BasicBlock* begBlk;
3241         BasicBlock* endBlk;
3242         ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
3243
3244         BasicBlock* finBeg = ehDsc->ebdHndBeg;
3245
3246         for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
3247         {
3248             if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
3249             {
3250                 continue;
3251             }
3252
3253             assert(bcall->isBBCallAlwaysPair());
3254
3255             if (succNum == i)
3256             {
3257                 *bres = bcall->bbNext;
3258                 return;
3259             }
3260             succNum++;
3261         }
3262     }
3263     assert(i == ~0u || ehDsc->HasFaultHandler()); // Should reach here only for fault blocks.
3264     if (i == ~0u)
3265     {
3266         *nres = succNum;
3267     }
3268 }
3269
3270 Compiler::SwitchUniqueSuccSet Compiler::GetDescriptorForSwitch(BasicBlock* switchBlk)
3271 {
3272     assert(switchBlk->bbJumpKind == BBJ_SWITCH);
3273     BlockToSwitchDescMap* switchMap = GetSwitchDescMap();
3274     SwitchUniqueSuccSet   res;
3275     if (switchMap->Lookup(switchBlk, &res))
3276     {
3277         return res;
3278     }
3279     else
3280     {
3281         // We must compute the descriptor. Find which are dups, by creating a bit set with the unique successors.
3282         // We create a temporary bitset of blocks to compute the unique set of successor blocks,
3283         // since adding a block's number twice leaves just one "copy" in the bitset. Note that
3284         // we specifically don't use the BlockSet type, because doing so would require making a
3285         // call to EnsureBasicBlockEpoch() to make sure the epoch is up-to-date. However, that
3286         // can create a new epoch, thus invalidating all existing BlockSet objects, such as
3287         // reachability information stored in the blocks. To avoid that, we just use a local BitVec.
3288
3289         BitVecTraits blockVecTraits(fgBBNumMax + 1, this);
3290         BitVec       BITVEC_INIT_NOCOPY(uniqueSuccBlocks, BitVecOps::MakeEmpty(&blockVecTraits));
3291         BasicBlock** jumpTable = switchBlk->bbJumpSwt->bbsDstTab;
3292         unsigned     jumpCount = switchBlk->bbJumpSwt->bbsCount;
3293         for (unsigned i = 0; i < jumpCount; i++)
3294         {
3295             BasicBlock* targ = jumpTable[i];
3296             BitVecOps::AddElemD(&blockVecTraits, uniqueSuccBlocks, targ->bbNum);
3297         }
3298         // Now we have a set of unique successors.
3299         unsigned numNonDups = BitVecOps::Count(&blockVecTraits, uniqueSuccBlocks);
3300
3301         typedef BasicBlock* BasicBlockPtr;
3302         BasicBlockPtr*      nonDups = new (getAllocator()) BasicBlockPtr[numNonDups];
3303
3304         unsigned nonDupInd = 0;
3305         // At this point, all unique targets are in "uniqueSuccBlocks".  As we encounter each,
3306         // add to nonDups, remove from "uniqueSuccBlocks".
3307         for (unsigned i = 0; i < jumpCount; i++)
3308         {
3309             BasicBlock* targ = jumpTable[i];
3310             if (BitVecOps::IsMember(&blockVecTraits, uniqueSuccBlocks, targ->bbNum))
3311             {
3312                 nonDups[nonDupInd] = targ;
3313                 nonDupInd++;
3314                 BitVecOps::RemoveElemD(&blockVecTraits, uniqueSuccBlocks, targ->bbNum);
3315             }
3316         }
3317
3318         assert(nonDupInd == numNonDups);
3319         assert(BitVecOps::Count(&blockVecTraits, uniqueSuccBlocks) == 0);
3320         res.numDistinctSuccs = numNonDups;
3321         res.nonDuplicates    = nonDups;
3322         switchMap->Set(switchBlk, res);
3323         return res;
3324     }
3325 }
3326
3327 void Compiler::SwitchUniqueSuccSet::UpdateTarget(IAllocator* alloc,
3328                                                  BasicBlock* switchBlk,
3329                                                  BasicBlock* from,
3330                                                  BasicBlock* to)
3331 {
3332     assert(switchBlk->bbJumpKind == BBJ_SWITCH); // Precondition.
3333     unsigned     jmpTabCnt = switchBlk->bbJumpSwt->bbsCount;
3334     BasicBlock** jmpTab    = switchBlk->bbJumpSwt->bbsDstTab;
3335
3336     // Is "from" still in the switch table (because it had more than one entry before?)
3337     bool fromStillPresent = false;
3338     for (unsigned i = 0; i < jmpTabCnt; i++)
3339     {
3340         if (jmpTab[i] == from)
3341         {
3342             fromStillPresent = true;
3343             break;
3344         }
3345     }
3346
3347     // Is "to" already in "this"?
3348     bool toAlreadyPresent = false;
3349     for (unsigned i = 0; i < numDistinctSuccs; i++)
3350     {
3351         if (nonDuplicates[i] == to)
3352         {
3353             toAlreadyPresent = true;
3354             break;
3355         }
3356     }
3357
3358     // Four cases:
3359     //   If "from" is still present, and "to" is already present, do nothing
3360     //   If "from" is still present, and "to" is not, must reallocate to add an entry.
3361     //   If "from" is not still present, and "to" is not present, write "to" where "from" was.
3362     //   If "from" is not still present, but "to" is present, remove "from".
3363     if (fromStillPresent && toAlreadyPresent)
3364     {
3365         return;
3366     }
3367     else if (fromStillPresent && !toAlreadyPresent)
3368     {
3369         // reallocate to add an entry
3370         typedef BasicBlock* BasicBlockPtr;
3371         BasicBlockPtr*      newNonDups = new (alloc) BasicBlockPtr[numDistinctSuccs + 1];
3372         memcpy(newNonDups, nonDuplicates, numDistinctSuccs * sizeof(BasicBlock*));
3373         newNonDups[numDistinctSuccs] = to;
3374         numDistinctSuccs++;
3375         nonDuplicates = newNonDups;
3376     }
3377     else if (!fromStillPresent && !toAlreadyPresent)
3378     {
3379 #ifdef DEBUG
3380         // write "to" where "from" was
3381         bool foundFrom = false;
3382 #endif // DEBUG
3383         for (unsigned i = 0; i < numDistinctSuccs; i++)
3384         {
3385             if (nonDuplicates[i] == from)
3386             {
3387                 nonDuplicates[i] = to;
3388 #ifdef DEBUG
3389                 foundFrom = true;
3390 #endif // DEBUG
3391                 break;
3392             }
3393         }
3394         assert(foundFrom);
3395     }
3396     else
3397     {
3398         assert(!fromStillPresent && toAlreadyPresent);
3399 #ifdef DEBUG
3400         // remove "from".
3401         bool foundFrom = false;
3402 #endif // DEBUG
3403         for (unsigned i = 0; i < numDistinctSuccs; i++)
3404         {
3405             if (nonDuplicates[i] == from)
3406             {
3407                 nonDuplicates[i] = nonDuplicates[numDistinctSuccs - 1];
3408                 numDistinctSuccs--;
3409 #ifdef DEBUG
3410                 foundFrom = true;
3411 #endif // DEBUG
3412                 break;
3413             }
3414         }
3415         assert(foundFrom);
3416     }
3417 }
3418
3419 /*****************************************************************************
3420  *
3421  *  Simple utility function to remove an entry for a block in the switch desc
3422  *  map. So it can be called from other phases.
3423  *
3424  */
3425 void Compiler::fgInvalidateSwitchDescMapEntry(BasicBlock* block)
3426 {
3427     // Check if map has no entries yet.
3428     if (m_switchDescMap != nullptr)
3429     {
3430         m_switchDescMap->Remove(block);
3431     }
3432 }
3433
3434 void Compiler::UpdateSwitchTableTarget(BasicBlock* switchBlk, BasicBlock* from, BasicBlock* to)
3435 {
3436     if (m_switchDescMap == nullptr)
3437     {
3438         return; // No mappings, nothing to do.
3439     }
3440
3441     // Otherwise...
3442     BlockToSwitchDescMap* switchMap = GetSwitchDescMap();
3443     SwitchUniqueSuccSet*  res       = switchMap->LookupPointer(switchBlk);
3444     if (res != nullptr)
3445     {
3446         // If no result, nothing to do. Otherwise, update it.
3447         res->UpdateTarget(getAllocator(), switchBlk, from, to);
3448     }
3449 }
3450
3451 /*****************************************************************************
3452  *  For a block that is in a handler region, find the first block of the most-nested
3453  *  handler containing the block.
3454  */
3455 BasicBlock* Compiler::fgFirstBlockOfHandler(BasicBlock* block)
3456 {
3457     assert(block->hasHndIndex());
3458     return ehGetDsc(block->getHndIndex())->ebdHndBeg;
3459 }
3460
3461 /*****************************************************************************
3462  *
3463  *  Function called to find back edges and return blocks and mark them as needing GC Polls.  This marks all
3464  *  blocks.
3465  */
3466 void Compiler::fgMarkGCPollBlocks()
3467 {
3468     if (GCPOLL_NONE == opts.compGCPollType)
3469     {
3470         return;
3471     }
3472
3473 #ifdef DEBUG
3474     /* Check that the flowgraph data (bbNum, bbRefs, bbPreds) is up-to-date */
3475     fgDebugCheckBBlist();
3476 #endif
3477
3478     BasicBlock* block;
3479
3480     // Return blocks always need GC polls.  In addition, all back edges (including those from switch
3481     // statements) need GC polls.  The poll is on the block with the outgoing back edge (or ret), rather than
3482     // on the destination or on the edge itself.
3483     for (block = fgFirstBB; block; block = block->bbNext)
3484     {
3485         bool blockNeedsPoll = false;
3486         switch (block->bbJumpKind)
3487         {
3488             case BBJ_COND:
3489             case BBJ_ALWAYS:
3490                 blockNeedsPoll = (block->bbJumpDest->bbNum <= block->bbNum);
3491                 break;
3492
3493             case BBJ_RETURN:
3494                 blockNeedsPoll = true;
3495                 break;
3496
3497             case BBJ_SWITCH:
3498                 unsigned jumpCnt;
3499                 jumpCnt = block->bbJumpSwt->bbsCount;
3500                 BasicBlock** jumpTab;
3501                 jumpTab = block->bbJumpSwt->bbsDstTab;
3502
3503                 do
3504                 {
3505                     if ((*jumpTab)->bbNum <= block->bbNum)
3506                     {
3507                         blockNeedsPoll = true;
3508                         break;
3509                     }
3510                 } while (++jumpTab, --jumpCnt);
3511                 break;
3512
3513             default:
3514                 break;
3515         }
3516
3517         if (blockNeedsPoll)
3518         {
3519             block->bbFlags |= BBF_NEEDS_GCPOLL;
3520         }
3521     }
3522 }
3523
3524 void Compiler::fgInitBlockVarSets()
3525 {
3526     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
3527     {
3528         block->InitVarSets(this);
3529     }
3530
3531     // QMarks are much like blocks, and need their VarSets initialized.
3532     assert(!compIsForInlining());
3533     for (unsigned i = 0; i < compQMarks->Size(); i++)
3534     {
3535         GenTreePtr qmark = compQMarks->Get(i);
3536         // Perhaps the gtOper of a QMark node was changed to something else since it was created and put on this list.
3537         // So can't hurt to check.
3538         if (qmark->OperGet() == GT_QMARK)
3539         {
3540             VarSetOps::AssignAllowUninitRhs(this, qmark->gtQmark.gtThenLiveSet, VarSetOps::UninitVal());
3541             VarSetOps::AssignAllowUninitRhs(this, qmark->gtQmark.gtElseLiveSet, VarSetOps::UninitVal());
3542         }
3543     }
3544     fgBBVarSetsInited = true;
3545 }
3546
3547 /*****************************************************************************
3548  *
3549  *  The following does the final pass on BBF_NEEDS_GCPOLL and then actually creates the GC Polls.
3550  */
3551 void Compiler::fgCreateGCPolls()
3552 {
3553     if (GCPOLL_NONE == opts.compGCPollType)
3554     {
3555         return;
3556     }
3557
3558     bool createdPollBlocks = false;
3559
3560 #ifdef DEBUG
3561     if (verbose)
3562     {
3563         printf("*************** In fgCreateGCPolls() for %s\n", info.compFullName);
3564     }
3565 #endif // DEBUG
3566
3567     if (!(opts.MinOpts() || opts.compDbgCode))
3568     {
3569         // Remove polls from well formed loops with a constant upper bound.
3570         for (unsigned lnum = 0; lnum < optLoopCount; ++lnum)
3571         {
3572             // Look for constant counted loops that run for a short duration.  This logic is very similar to
3573             // what's in code:Compiler::optUnrollLoops, since they have similar constraints.  However, this
3574             // logic is much more permissive since we're not doing a complex transformation.
3575
3576             /* TODO-Cleanup:
3577              * I feel bad cloning so much logic from optUnrollLoops
3578              */
3579
3580             // Filter out loops not meeting the obvious preconditions.
3581             //
3582             if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED)
3583             {
3584                 continue;
3585             }
3586
3587             if (!(optLoopTable[lnum].lpFlags & LPFLG_CONST))
3588             {
3589                 continue;
3590             }
3591
3592             BasicBlock* head   = optLoopTable[lnum].lpHead;
3593             BasicBlock* bottom = optLoopTable[lnum].lpBottom;
3594
3595             // Loops dominated by GC_SAFE_POINT won't have this set.
3596             if (!(bottom->bbFlags & BBF_NEEDS_GCPOLL))
3597             {
3598                 continue;
3599             }
3600
3601             /* Get the loop data:
3602                 - initial constant
3603                 - limit constant
3604                 - iterator
3605                 - iterator increment
3606                 - increment operation type (i.e. ASG_ADD, ASG_SUB, etc...)
3607                 - loop test type (i.e. GT_GE, GT_LT, etc...)
3608              */
3609
3610             int        lbeg     = optLoopTable[lnum].lpConstInit;
3611             int        llim     = optLoopTable[lnum].lpConstLimit();
3612             genTreeOps testOper = optLoopTable[lnum].lpTestOper();
3613
3614             int        lvar     = optLoopTable[lnum].lpIterVar();
3615             int        iterInc  = optLoopTable[lnum].lpIterConst();
3616             genTreeOps iterOper = optLoopTable[lnum].lpIterOper();
3617
3618             var_types iterOperType = optLoopTable[lnum].lpIterOperType();
3619             bool      unsTest      = (optLoopTable[lnum].lpTestTree->gtFlags & GTF_UNSIGNED) != 0;
3620             if (lvaTable[lvar].lvAddrExposed)
3621             { // Can't reason about the value of the iteration variable.
3622                 continue;
3623             }
3624
3625             unsigned totalIter;
3626
3627             /* Find the number of iterations - the function returns false if not a constant number */
3628
3629             if (!optComputeLoopRep(lbeg, llim, iterInc, iterOper, iterOperType, testOper, unsTest,
3630                                    // The value here doesn't matter for this variation of the optimization
3631                                    true, &totalIter))
3632             {
3633 #ifdef DEBUG
3634                 if (verbose)
3635                 {
3636                     printf("Could not compute loop iterations for loop from BB%02u to BB%02u", head->bbNum,
3637                            bottom->bbNum);
3638                 }
3639 #endif                      // DEBUG
3640                 (void)head; // suppress gcc error.
3641
3642                 continue;
3643             }
3644
3645             /* Forget it if there are too many repetitions or not a constant loop */
3646
3647             static const unsigned ITER_LIMIT = 256;
3648             if (totalIter > ITER_LIMIT)
3649             {
3650                 continue;
3651             }
3652
3653             // It is safe to elminate the poll from this loop.
3654             bottom->bbFlags &= ~BBF_NEEDS_GCPOLL;
3655
3656 #ifdef DEBUG
3657             if (verbose)
3658             {
3659                 printf("Removing poll in block BB%02u because it forms a bounded counted loop\n", bottom->bbNum);
3660             }
3661 #endif // DEBUG
3662         }
3663     }
3664
3665     // Final chance to optimize the polls.  Move all polls in loops from the bottom of the loop up to the
3666     // loop head.  Also eliminate all epilog polls in non-leaf methods.  This only works if we have dominator
3667     // information.
3668     if (fgDomsComputed)
3669     {
3670         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
3671         {
3672             if (!(block->bbFlags & BBF_NEEDS_GCPOLL))
3673             {
3674                 continue;
3675             }
3676
3677             if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
3678             {
3679                 // make sure that this is loop-like
3680                 if (!fgReachable(block->bbJumpDest, block))
3681                 {
3682                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3683 #ifdef DEBUG
3684                     if (verbose)
3685                     {
3686                         printf("Removing poll in block BB%02u because it is not loop\n", block->bbNum);
3687                     }
3688 #endif // DEBUG
3689                     continue;
3690                 }
3691             }
3692             else if (!(block->bbJumpKind == BBJ_RETURN || block->bbJumpKind == BBJ_SWITCH))
3693             {
3694                 noway_assert(!"GC Poll on a block that has no control transfer.");
3695 #ifdef DEBUG
3696                 if (verbose)
3697                 {
3698                     printf("Removing poll in block BB%02u because it is not a jump\n", block->bbNum);
3699                 }
3700 #endif // DEBUG
3701                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3702                 continue;
3703             }
3704
3705             // Because of block compaction, it's possible to end up with a block that is both poll and safe.
3706             // Clean those up now.
3707
3708             if (block->bbFlags & BBF_GC_SAFE_POINT)
3709             {
3710 #ifdef DEBUG
3711                 if (verbose)
3712                 {
3713                     printf("Removing poll in return block BB%02u because it is GC Safe\n", block->bbNum);
3714                 }
3715 #endif // DEBUG
3716                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3717                 continue;
3718             }
3719
3720             if (block->bbJumpKind == BBJ_RETURN)
3721             {
3722                 if (!optReachWithoutCall(fgFirstBB, block))
3723                 {
3724                     // check to see if there is a call along the path between the first block and the return
3725                     // block.
3726                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3727 #ifdef DEBUG
3728                     if (verbose)
3729                     {
3730                         printf("Removing poll in return block BB%02u because it dominated by a call\n", block->bbNum);
3731                     }
3732 #endif // DEBUG
3733                     continue;
3734                 }
3735             }
3736         }
3737     }
3738
3739     noway_assert(!fgGCPollsCreated);
3740     BasicBlock* block;
3741     fgGCPollsCreated = true;
3742
3743     // Walk through the blocks and hunt for a block that has BBF_NEEDS_GCPOLL
3744     for (block = fgFirstBB; block; block = block->bbNext)
3745     {
3746         // Because of block compaction, it's possible to end up with a block that is both poll and safe.
3747         // And if !fgDomsComputed, we won't have cleared them, so skip them now
3748         if (!(block->bbFlags & BBF_NEEDS_GCPOLL) || (block->bbFlags & BBF_GC_SAFE_POINT))
3749         {
3750             continue;
3751         }
3752
3753         // This block needs a poll.  We either just insert a callout or we split the block and inline part of
3754         // the test.  This depends on the value of opts.compGCPollType.
3755
3756         // If we're doing GCPOLL_CALL, just insert a GT_CALL node before the last node in the block.
3757         CLANG_FORMAT_COMMENT_ANCHOR;
3758
3759 #ifdef DEBUG
3760         switch (block->bbJumpKind)
3761         {
3762             case BBJ_RETURN:
3763             case BBJ_ALWAYS:
3764             case BBJ_COND:
3765             case BBJ_SWITCH:
3766                 break;
3767             default:
3768                 noway_assert(!"Unknown block type for BBF_NEEDS_GCPOLL");
3769         }
3770 #endif // DEBUG
3771
3772         noway_assert(opts.compGCPollType);
3773
3774         GCPollType pollType = opts.compGCPollType;
3775         // pollType is set to either CALL or INLINE at this point.  Below is the list of places where we
3776         // can't or don't want to emit an inline check.  Check all of those.  If after all of that we still
3777         // have INLINE, then emit an inline check.
3778
3779         if (opts.MinOpts() || opts.compDbgCode)
3780         {
3781 #ifdef DEBUG
3782             if (verbose)
3783             {
3784                 printf("Selecting CALL poll in block BB%02u because of debug/minopts\n", block->bbNum);
3785             }
3786 #endif // DEBUG
3787
3788             // Don't split blocks and create inlined polls unless we're optimizing.
3789             pollType = GCPOLL_CALL;
3790         }
3791         else if (genReturnBB == block)
3792         {
3793 #ifdef DEBUG
3794             if (verbose)
3795             {
3796                 printf("Selecting CALL poll in block BB%02u because it is the single return block\n", block->bbNum);
3797             }
3798 #endif // DEBUG
3799
3800             // we don't want to split the single return block
3801             pollType = GCPOLL_CALL;
3802         }
3803         else if (BBJ_SWITCH == block->bbJumpKind)
3804         {
3805 #ifdef DEBUG
3806             if (verbose)
3807             {
3808                 printf("Selecting CALL poll in block BB%02u because it is a loop formed by a SWITCH\n", block->bbNum);
3809             }
3810 #endif // DEBUG
3811
3812             // I don't want to deal with all the outgoing edges of a switch block.
3813             pollType = GCPOLL_CALL;
3814         }
3815
3816         // TODO-Cleanup: potentially don't split if we're in an EH region.
3817
3818         createdPollBlocks |= fgCreateGCPoll(pollType, block);
3819     }
3820
3821     // If we split a block to create a GC Poll, then rerun fgReorderBlocks to push the rarely run blocks out
3822     // past the epilog.  We should never split blocks unless we're optimizing.
3823     if (createdPollBlocks)
3824     {
3825         noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3826         fgReorderBlocks();
3827     }
3828 }
3829
3830 /*****************************************************************************
3831  *
3832  *  Actually create a GCPoll in the given block. Returns true if it created
3833  *  a basic block.
3834  */
3835
3836 bool Compiler::fgCreateGCPoll(GCPollType pollType, BasicBlock* block)
3837 {
3838     assert(!(block->bbFlags & BBF_GC_SAFE_POINT));
3839     bool createdPollBlocks;
3840
3841     void* addrTrap;
3842     void* pAddrOfCaptureThreadGlobal;
3843
3844     addrTrap = info.compCompHnd->getAddrOfCaptureThreadGlobal(&pAddrOfCaptureThreadGlobal);
3845
3846 #ifdef ENABLE_FAST_GCPOLL_HELPER
3847     // I never want to split blocks if we've got two indirections here.
3848     // This is a size trade-off assuming the VM has ENABLE_FAST_GCPOLL_HELPER.
3849     // So don't do it when that is off
3850     if (pAddrOfCaptureThreadGlobal != NULL)
3851     {
3852         pollType = GCPOLL_CALL;
3853     }
3854 #endif // ENABLE_FAST_GCPOLL_HELPER
3855
3856     if (GCPOLL_CALL == pollType)
3857     {
3858         createdPollBlocks = false;
3859         GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_POLL_GC, TYP_VOID);
3860 #if GTF_CALL_REG_SAVE
3861         call->gtCallMoreFlags |= GTF_CALL_REG_SAVE;
3862 #endif // GTF_CALL_REG_SAVE
3863
3864         // for BBJ_ALWAYS I don't need to insert it before the condition.  Just append it.
3865         if (block->bbJumpKind == BBJ_ALWAYS)
3866         {
3867             fgInsertStmtAtEnd(block, call);
3868         }
3869         else
3870         {
3871             GenTreeStmt* newStmt = fgInsertStmtNearEnd(block, call);
3872             // For DDB156656, we need to associate the GC Poll with the IL offset (and therefore sequence
3873             // point) of the tree before which we inserted the poll.  One example of when this is a
3874             // problem:
3875             //  if (...) {  //1
3876             //      ...
3877             //  } //2
3878             //  else { //3
3879             //      ...
3880             //  }
3881             //  (gcpoll) //4
3882             //  return. //5
3883             //
3884             //  If we take the if statement at 1, we encounter a jump at 2.  This jumps over the else
3885             //  and lands at 4.  4 is where we inserted the gcpoll.  However, that is associated with
3886             //  the sequence point a 3.  Therefore, the debugger displays the wrong source line at the
3887             //  gc poll location.
3888             //
3889             //  More formally, if control flow targets an instruction, that instruction must be the
3890             //  start of a new sequence point.
3891             if (newStmt->gtNext)
3892             {
3893                 // Is it possible for gtNext to be NULL?
3894                 noway_assert(newStmt->gtNext->gtOper == GT_STMT);
3895                 newStmt->gtStmtILoffsx = newStmt->gtNextStmt->gtStmtILoffsx;
3896             }
3897         }
3898
3899         block->bbFlags |= BBF_GC_SAFE_POINT;
3900 #ifdef DEBUG
3901         if (verbose)
3902         {
3903             printf("*** creating GC Poll in block BB%02u\n", block->bbNum);
3904             gtDispTreeList(block->bbTreeList);
3905         }
3906 #endif // DEBUG
3907     }
3908     else
3909     {
3910         createdPollBlocks = true;
3911         // if we're doing GCPOLL_INLINE, then:
3912         //  1) Create two new blocks: Poll and Bottom.  The original block is called Top.
3913
3914         // I want to create:
3915         // top -> poll -> bottom (lexically)
3916         // so that we jump over poll to get to bottom.
3917         BasicBlock* top         = block;
3918         BasicBlock* poll        = fgNewBBafter(BBJ_NONE, top, true);
3919         BasicBlock* bottom      = fgNewBBafter(top->bbJumpKind, poll, true);
3920         BBjumpKinds oldJumpKind = top->bbJumpKind;
3921
3922         // Update block flags
3923         const unsigned __int64 originalFlags = top->bbFlags | BBF_GC_SAFE_POINT;
3924
3925         // Unlike Fei's inliner from puclr, I'm allowed to split loops.
3926         // And we keep a few other flags...
3927         noway_assert((originalFlags & (BBF_SPLIT_NONEXIST & ~(BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1))) == 0);
3928         top->bbFlags = originalFlags & (~BBF_SPLIT_LOST | BBF_GC_SAFE_POINT);
3929         bottom->bbFlags |= originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT);
3930         bottom->inheritWeight(top);
3931         poll->bbFlags |= originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT);
3932
3933         //  9) Mark Poll as rarely run.
3934         poll->bbSetRunRarely();
3935
3936         //  5) Bottom gets all the outgoing edges and inherited flags of Original.
3937         bottom->bbJumpDest = top->bbJumpDest;
3938
3939         //  2) Add a GC_CALL node to Poll.
3940         GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_POLL_GC, TYP_VOID);
3941 #if GTF_CALL_REG_SAVE
3942         call->gtCallMoreFlags |= GTF_CALL_REG_SAVE;
3943 #endif // GTF_CALL_REG_SAVE
3944         fgInsertStmtAtEnd(poll, call);
3945
3946         //  3) Remove the last statement from Top and add it to Bottom.
3947         if (oldJumpKind != BBJ_ALWAYS)
3948         {
3949             // if I'm always jumping to the target, then this is not a condition that needs moving.
3950             GenTreeStmt* stmt = top->firstStmt();
3951             while (stmt->gtNext)
3952             {
3953                 stmt = stmt->gtNextStmt;
3954             }
3955             fgRemoveStmt(top, stmt);
3956             fgInsertStmtAtEnd(bottom, stmt);
3957         }
3958
3959         // for BBJ_ALWAYS blocks, bottom is an empty block.
3960
3961         //  4) Create a GT_EQ node that checks against g_TrapReturningThreads.  True jumps to Bottom,
3962         //  false falls through to poll.  Add this to the end of Top.  Top is now BBJ_COND.  Bottom is
3963         //  now a jump target
3964         CLANG_FORMAT_COMMENT_ANCHOR;
3965
3966 #ifdef ENABLE_FAST_GCPOLL_HELPER
3967         // Prefer the fast gc poll helepr over the double indirection
3968         noway_assert(pAddrOfCaptureThreadGlobal == nullptr);
3969 #endif
3970
3971         GenTreePtr trap;
3972         if (pAddrOfCaptureThreadGlobal != nullptr)
3973         {
3974             trap = gtNewOperNode(GT_IND, TYP_I_IMPL,
3975                                  gtNewIconHandleNode((size_t)pAddrOfCaptureThreadGlobal, GTF_ICON_PTR_HDL));
3976         }
3977         else
3978         {
3979             trap = gtNewIconHandleNode((size_t)addrTrap, GTF_ICON_PTR_HDL);
3980         }
3981
3982         GenTreePtr trapRelop = gtNewOperNode(GT_EQ, TYP_INT,
3983                                              // lhs [g_TrapReturningThreads]
3984                                              gtNewOperNode(GT_IND, TYP_INT, trap),
3985                                              // rhs 0
3986                                              gtNewIconNode(0, TYP_INT));
3987         trapRelop->gtFlags |= GTF_RELOP_JMP_USED | GTF_DONT_CSE; // Treat reading g_TrapReturningThreads as volatile.
3988         GenTreePtr trapCheck = gtNewOperNode(GT_JTRUE, TYP_VOID, trapRelop);
3989         fgInsertStmtAtEnd(top, trapCheck);
3990         top->bbJumpDest = bottom;
3991         top->bbJumpKind = BBJ_COND;
3992         bottom->bbFlags |= BBF_JMP_TARGET;
3993
3994         //  7) Bottom has Top and Poll as its predecessors.  Poll has just Top as a predecessor.
3995         fgAddRefPred(bottom, poll);
3996         fgAddRefPred(bottom, top);
3997         fgAddRefPred(poll, top);
3998
3999         //  8) Replace Top with Bottom in the predecessor list of all outgoing edges from Bottom (1 for
4000         //      jumps, 2 for conditional branches, N for switches).
4001         switch (oldJumpKind)
4002         {
4003             case BBJ_RETURN:
4004                 // no successors
4005                 break;
4006             case BBJ_COND:
4007                 // replace predecessor in the fall through block.
4008                 noway_assert(bottom->bbNext);
4009                 fgReplacePred(bottom->bbNext, top, bottom);
4010
4011                 // fall through for the jump target
4012                 __fallthrough;
4013
4014             case BBJ_ALWAYS:
4015                 fgReplacePred(bottom->bbJumpDest, top, bottom);
4016                 break;
4017             case BBJ_SWITCH:
4018                 NO_WAY("SWITCH should be a call rather than an inlined poll.");
4019                 break;
4020             default:
4021                 NO_WAY("Unknown block type for updating predecessor lists.");
4022         }
4023
4024         top->bbFlags &= ~BBF_NEEDS_GCPOLL;
4025         noway_assert(!(poll->bbFlags & BBF_NEEDS_GCPOLL));
4026         noway_assert(!(bottom->bbFlags & BBF_NEEDS_GCPOLL));
4027
4028         if (compCurBB == top)
4029         {
4030             compCurBB = bottom;
4031         }
4032
4033 #ifdef DEBUG
4034         if (verbose)
4035         {
4036             printf("*** creating inlined GC Poll in top block BB%02u\n", top->bbNum);
4037             gtDispTreeList(top->bbTreeList);
4038             printf(" poll block is BB%02u\n", poll->bbNum);
4039             gtDispTreeList(poll->bbTreeList);
4040             printf(" bottom block is BB%02u\n", bottom->bbNum);
4041             gtDispTreeList(bottom->bbTreeList);
4042         }
4043 #endif // DEBUG
4044     }
4045
4046     return createdPollBlocks;
4047 }
4048
4049 /*****************************************************************************
4050  *
4051  *  The following helps find a basic block given its PC offset.
4052  */
4053
4054 void Compiler::fgInitBBLookup()
4055 {
4056     BasicBlock** dscBBptr;
4057     BasicBlock*  tmpBBdesc;
4058
4059     /* Allocate the basic block table */
4060
4061     dscBBptr = fgBBs = new (this, CMK_BasicBlock) BasicBlock*[fgBBcount];
4062
4063     /* Walk all the basic blocks, filling in the table */
4064
4065     for (tmpBBdesc = fgFirstBB; tmpBBdesc; tmpBBdesc = tmpBBdesc->bbNext)
4066     {
4067         *dscBBptr++ = tmpBBdesc;
4068     }
4069
4070     noway_assert(dscBBptr == fgBBs + fgBBcount);
4071 }
4072
4073 BasicBlock* Compiler::fgLookupBB(unsigned addr)
4074 {
4075     unsigned lo;
4076     unsigned hi;
4077
4078     /* Do a binary search */
4079
4080     for (lo = 0, hi = fgBBcount - 1;;)
4081     {
4082
4083     AGAIN:;
4084
4085         if (lo > hi)
4086         {
4087             break;
4088         }
4089
4090         unsigned    mid = (lo + hi) / 2;
4091         BasicBlock* dsc = fgBBs[mid];
4092
4093         // We introduce internal blocks for BBJ_CALLFINALLY. Skip over these.
4094
4095         while (dsc->bbFlags & BBF_INTERNAL)
4096         {
4097             dsc = dsc->bbNext;
4098             mid++;
4099
4100             // We skipped over too many, Set hi back to the original mid - 1
4101
4102             if (mid > hi)
4103             {
4104                 mid = (lo + hi) / 2;
4105                 hi  = mid - 1;
4106                 goto AGAIN;
4107             }
4108         }
4109
4110         unsigned pos = dsc->bbCodeOffs;
4111
4112         if (pos < addr)
4113         {
4114             if ((lo == hi) && (lo == (fgBBcount - 1)))
4115             {
4116                 noway_assert(addr == dsc->bbCodeOffsEnd);
4117                 return nullptr; // NULL means the end of method
4118             }
4119             lo = mid + 1;
4120             continue;
4121         }
4122
4123         if (pos > addr)
4124         {
4125             hi = mid - 1;
4126             continue;
4127         }
4128
4129         return dsc;
4130     }
4131 #ifdef DEBUG
4132     printf("ERROR: Couldn't find basic block at offset %04X\n", addr);
4133 #endif // DEBUG
4134     NO_WAY("fgLookupBB failed.");
4135 }
4136
4137 /*****************************************************************************
4138  *
4139  *  The 'jump target' array uses the following flags to indicate what kind
4140  *  of label is present.
4141  */
4142
4143 #define JT_NONE 0x00  // This IL offset is never used
4144 #define JT_ADDR 0x01  // merely make sure this is an OK address
4145 #define JT_JUMP 0x02  // 'normal' jump target
4146 #define JT_MULTI 0x04 // target of multiple jumps
4147
4148 inline void Compiler::fgMarkJumpTarget(BYTE* jumpTarget, unsigned offs)
4149 {
4150     /* Make sure we set JT_MULTI if target of multiple jumps */
4151
4152     noway_assert(JT_MULTI == JT_JUMP << 1);
4153
4154     jumpTarget[offs] |= (jumpTarget[offs] & JT_JUMP) << 1 | JT_JUMP;
4155 }
4156
4157 //------------------------------------------------------------------------
4158 // FgStack: simple stack model for the inlinee's evaluation stack.
4159 //
4160 // Model the inputs available to various operations in the inline body.
4161 // Tracks constants, arguments, array lengths.
4162
4163 class FgStack
4164 {
4165 public:
4166     FgStack() : slot0(SLOT_INVALID), slot1(SLOT_INVALID), depth(0)
4167     {
4168         // Empty
4169     }
4170
4171     void Clear()
4172     {
4173         depth = 0;
4174     }
4175     void PushUnknown()
4176     {
4177         Push(SLOT_UNKNOWN);
4178     }
4179     void PushConstant()
4180     {
4181         Push(SLOT_CONSTANT);
4182     }
4183     void PushArrayLen()
4184     {
4185         Push(SLOT_ARRAYLEN);
4186     }
4187     void PushArgument(unsigned arg)
4188     {
4189         Push(SLOT_ARGUMENT + arg);
4190     }
4191     unsigned GetSlot0() const
4192     {
4193         assert(depth >= 1);
4194         return slot0;
4195     }
4196     unsigned GetSlot1() const
4197     {
4198         assert(depth >= 2);
4199         return slot1;
4200     }
4201     static bool IsConstant(unsigned value)
4202     {
4203         return value == SLOT_CONSTANT;
4204     }
4205     static bool IsArrayLen(unsigned value)
4206     {
4207         return value == SLOT_ARRAYLEN;
4208     }
4209     static bool IsArgument(unsigned value)
4210     {
4211         return value >= SLOT_ARGUMENT;
4212     }
4213     static unsigned SlotTypeToArgNum(unsigned value)
4214     {
4215         assert(IsArgument(value));
4216         return value - SLOT_ARGUMENT;
4217     }
4218     bool IsStackTwoDeep() const
4219     {
4220         return depth == 2;
4221     }
4222     bool IsStackOneDeep() const
4223     {
4224         return depth == 1;
4225     }
4226     bool IsStackAtLeastOneDeep() const
4227     {
4228         return depth >= 1;
4229     }
4230
4231 private:
4232     enum
4233     {
4234         SLOT_INVALID  = UINT_MAX,
4235         SLOT_UNKNOWN  = 0,
4236         SLOT_CONSTANT = 1,
4237         SLOT_ARRAYLEN = 2,
4238         SLOT_ARGUMENT = 3
4239     };
4240
4241     void Push(int type)
4242     {
4243         switch (depth)
4244         {
4245             case 0:
4246                 ++depth;
4247                 slot0 = type;
4248                 break;
4249             case 1:
4250                 ++depth;
4251                 __fallthrough;
4252             case 2:
4253                 slot1 = slot0;
4254                 slot0 = type;
4255         }
4256     }
4257
4258     unsigned slot0;
4259     unsigned slot1;
4260     unsigned depth;
4261 };
4262
4263 //------------------------------------------------------------------------
4264 // fgFindJumpTargets: walk the IL stream, determining jump target offsets
4265 //
4266 // Arguments:
4267 //    codeAddr   - base address of the IL code buffer
4268 //    codeSize   - number of bytes in the IL code buffer
4269 //    jumpTarget - [OUT] byte array for flagging jump targets
4270 //
4271 // Notes:
4272 //    If inlining or prejitting the root, this method also makes
4273 //    various observations about the method that factor into inline
4274 //    decisions.
4275 //
4276 //    May throw an exception if the IL is malformed.
4277 //
4278 //    jumpTarget[N] is set to a JT_* value if IL offset N is a
4279 //    jump target in the method.
4280 //
4281 //    Also sets lvAddrExposed and lvHasILStoreOp, ilHasMultipleILStoreOp in lvaTable[].
4282
4283 #ifdef _PREFAST_
4284 #pragma warning(push)
4285 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
4286 #endif
4287
4288 void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget)
4289 {
4290     const BYTE* codeBegp = codeAddr;
4291     const BYTE* codeEndp = codeAddr + codeSize;
4292     unsigned    varNum;
4293     bool        seenJump = false;
4294     var_types   varType  = DUMMY_INIT(TYP_UNDEF); // TYP_ type
4295     typeInfo    ti;                               // Verifier type.
4296     bool        typeIsNormed = false;
4297     FgStack     pushedStack;
4298     const bool  isForceInline          = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0;
4299     const bool  makeInlineObservations = (compInlineResult != nullptr);
4300     const bool  isInlining             = compIsForInlining();
4301     unsigned    retBlocks              = 0;
4302
4303     if (makeInlineObservations)
4304     {
4305         // Observe force inline state and code size.
4306         compInlineResult->NoteBool(InlineObservation::CALLEE_IS_FORCE_INLINE, isForceInline);
4307         compInlineResult->NoteInt(InlineObservation::CALLEE_IL_CODE_SIZE, codeSize);
4308
4309 #ifdef DEBUG
4310
4311         // If inlining, this method should still be a candidate.
4312         if (isInlining)
4313         {
4314             assert(compInlineResult->IsCandidate());
4315         }
4316
4317 #endif // DEBUG
4318
4319         // note that we're starting to look at the opcodes.
4320         compInlineResult->Note(InlineObservation::CALLEE_BEGIN_OPCODE_SCAN);
4321     }
4322
4323     while (codeAddr < codeEndp)
4324     {
4325         OPCODE opcode = (OPCODE)getU1LittleEndian(codeAddr);
4326         codeAddr += sizeof(__int8);
4327         opts.instrCount++;
4328         typeIsNormed = false;
4329
4330     DECODE_OPCODE:
4331
4332         if (opcode >= CEE_COUNT)
4333         {
4334             BADCODE3("Illegal opcode", ": %02X", (int)opcode);
4335         }
4336
4337         if ((opcode >= CEE_LDARG_0 && opcode <= CEE_STLOC_S) || (opcode >= CEE_LDARG && opcode <= CEE_STLOC))
4338         {
4339             opts.lvRefCount++;
4340         }
4341
4342         if (makeInlineObservations && (opcode >= CEE_LDNULL) && (opcode <= CEE_LDC_R8))
4343         {
4344             pushedStack.PushConstant();
4345         }
4346
4347         unsigned sz = opcodeSizes[opcode];
4348
4349         switch (opcode)
4350         {
4351             case CEE_PREFIX1:
4352             {
4353                 if (codeAddr >= codeEndp)
4354                 {
4355                     goto TOO_FAR;
4356                 }
4357                 opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr));
4358                 codeAddr += sizeof(__int8);
4359                 goto DECODE_OPCODE;
4360             }
4361
4362             case CEE_PREFIX2:
4363             case CEE_PREFIX3:
4364             case CEE_PREFIX4:
4365             case CEE_PREFIX5:
4366             case CEE_PREFIX6:
4367             case CEE_PREFIX7:
4368             case CEE_PREFIXREF:
4369             {
4370                 BADCODE3("Illegal opcode", ": %02X", (int)opcode);
4371             }
4372
4373             case CEE_CALL:
4374             case CEE_CALLVIRT:
4375             {
4376                 // There has to be code after the call, otherwise the inlinee is unverifiable.
4377                 if (isInlining)
4378                 {
4379
4380                     noway_assert(codeAddr < codeEndp - sz);
4381                 }
4382
4383                 // If the method has a call followed by a ret, assume that
4384                 // it is a wrapper method.
4385                 if (makeInlineObservations)
4386                 {
4387                     if ((OPCODE)getU1LittleEndian(codeAddr + sz) == CEE_RET)
4388                     {
4389                         compInlineResult->Note(InlineObservation::CALLEE_LOOKS_LIKE_WRAPPER);
4390                     }
4391                 }
4392             }
4393             break;
4394
4395             case CEE_LEAVE:
4396             case CEE_LEAVE_S:
4397             case CEE_BR:
4398             case CEE_BR_S:
4399             case CEE_BRFALSE:
4400             case CEE_BRFALSE_S:
4401             case CEE_BRTRUE:
4402             case CEE_BRTRUE_S:
4403             case CEE_BEQ:
4404             case CEE_BEQ_S:
4405             case CEE_BGE:
4406             case CEE_BGE_S:
4407             case CEE_BGE_UN:
4408             case CEE_BGE_UN_S:
4409             case CEE_BGT:
4410             case CEE_BGT_S:
4411             case CEE_BGT_UN:
4412             case CEE_BGT_UN_S:
4413             case CEE_BLE:
4414             case CEE_BLE_S:
4415             case CEE_BLE_UN:
4416             case CEE_BLE_UN_S:
4417             case CEE_BLT:
4418             case CEE_BLT_S:
4419             case CEE_BLT_UN:
4420             case CEE_BLT_UN_S:
4421             case CEE_BNE_UN:
4422             case CEE_BNE_UN_S:
4423             {
4424                 seenJump = true;
4425
4426                 if (codeAddr > codeEndp - sz)
4427                 {
4428                     goto TOO_FAR;
4429                 }
4430
4431                 // Compute jump target address
4432                 signed jmpDist = (sz == 1) ? getI1LittleEndian(codeAddr) : getI4LittleEndian(codeAddr);
4433
4434                 if (compIsForInlining() && jmpDist == 0 &&
4435                     (opcode == CEE_LEAVE || opcode == CEE_LEAVE_S || opcode == CEE_BR || opcode == CEE_BR_S))
4436                 {
4437                     break; /* NOP */
4438                 }
4439
4440                 unsigned jmpAddr = (IL_OFFSET)(codeAddr - codeBegp) + sz + jmpDist;
4441
4442                 // Make sure target is reasonable
4443                 if (jmpAddr >= codeSize)
4444                 {
4445                     BADCODE3("code jumps to outer space", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4446                 }
4447
4448                 // Mark the jump target
4449                 fgMarkJumpTarget(jumpTarget, jmpAddr);
4450
4451                 // See if jump might be sensitive to inlining
4452                 if (makeInlineObservations && (opcode != CEE_BR_S) && (opcode != CEE_BR))
4453                 {
4454                     fgObserveInlineConstants(opcode, pushedStack, isInlining);
4455                 }
4456             }
4457             break;
4458
4459             case CEE_SWITCH:
4460             {
4461                 seenJump = true;
4462
4463                 if (makeInlineObservations)
4464                 {
4465                     compInlineResult->Note(InlineObservation::CALLEE_HAS_SWITCH);
4466
4467                     // Fail fast, if we're inlining and can't handle this.
4468                     if (isInlining && compInlineResult->IsFailure())
4469                     {
4470                         return;
4471                     }
4472                 }
4473
4474                 // Make sure we don't go past the end reading the number of cases
4475                 if (codeAddr > codeEndp - sizeof(DWORD))
4476                 {
4477                     goto TOO_FAR;
4478                 }
4479
4480                 // Read the number of cases
4481                 unsigned jmpCnt = getU4LittleEndian(codeAddr);
4482                 codeAddr += sizeof(DWORD);
4483
4484                 if (jmpCnt > codeSize / sizeof(DWORD))
4485                 {
4486                     goto TOO_FAR;
4487                 }
4488
4489                 // Find the end of the switch table
4490                 unsigned jmpBase = (unsigned)((codeAddr - codeBegp) + jmpCnt * sizeof(DWORD));
4491
4492                 // Make sure there is more code after the switch
4493                 if (jmpBase >= codeSize)
4494                 {
4495                     goto TOO_FAR;
4496                 }
4497
4498                 // jmpBase is also the target of the default case, so mark it
4499                 fgMarkJumpTarget(jumpTarget, jmpBase);
4500
4501                 // Process table entries
4502                 while (jmpCnt > 0)
4503                 {
4504                     unsigned jmpAddr = jmpBase + getI4LittleEndian(codeAddr);
4505                     codeAddr += 4;
4506
4507                     if (jmpAddr >= codeSize)
4508                     {
4509                         BADCODE3("jump target out of range", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4510                     }
4511
4512                     fgMarkJumpTarget(jumpTarget, jmpAddr);
4513                     jmpCnt--;
4514                 }
4515
4516                 // We've advanced past all the bytes in this instruction
4517                 sz = 0;
4518             }
4519             break;
4520
4521             case CEE_UNALIGNED:
4522             case CEE_CONSTRAINED:
4523             case CEE_READONLY:
4524             case CEE_VOLATILE:
4525             case CEE_TAILCALL:
4526             {
4527                 if (codeAddr >= codeEndp)
4528                 {
4529                     goto TOO_FAR;
4530                 }
4531             }
4532             break;
4533
4534             case CEE_STARG:
4535             case CEE_STARG_S:
4536             {
4537                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4538
4539                 if (codeAddr > codeEndp - sz)
4540                 {
4541                     goto TOO_FAR;
4542                 }
4543
4544                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4545
4546                 if (isInlining)
4547                 {
4548                     if (varNum < impInlineInfo->argCnt)
4549                     {
4550                         impInlineInfo->inlArgInfo[varNum].argHasStargOp = true;
4551                     }
4552                 }
4553                 else
4554                 {
4555                     // account for possible hidden param
4556                     varNum = compMapILargNum(varNum);
4557
4558                     // This check is only intended to prevent an AV.  Bad varNum values will later
4559                     // be handled properly by the verifier.
4560                     if (varNum < lvaTableCnt)
4561                     {
4562                         // In non-inline cases, note written-to arguments.
4563                         lvaTable[varNum].lvHasILStoreOp = 1;
4564                     }
4565                 }
4566             }
4567             break;
4568
4569             case CEE_STLOC_0:
4570             case CEE_STLOC_1:
4571             case CEE_STLOC_2:
4572             case CEE_STLOC_3:
4573                 varNum = (opcode - CEE_STLOC_0);
4574                 goto STLOC;
4575
4576             case CEE_STLOC:
4577             case CEE_STLOC_S:
4578             {
4579                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4580
4581                 if (codeAddr > codeEndp - sz)
4582                 {
4583                     goto TOO_FAR;
4584                 }
4585
4586                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4587
4588             STLOC:
4589                 if (isInlining)
4590                 {
4591                     InlLclVarInfo& lclInfo = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt];
4592
4593                     if (lclInfo.lclHasStlocOp)
4594                     {
4595                         lclInfo.lclHasMultipleStlocOp = 1;
4596                     }
4597                     else
4598                     {
4599                         lclInfo.lclHasStlocOp = 1;
4600                     }
4601                 }
4602                 else
4603                 {
4604                     varNum += info.compArgsCount;
4605
4606                     // This check is only intended to prevent an AV.  Bad varNum values will later
4607                     // be handled properly by the verifier.
4608                     if (varNum < lvaTableCnt)
4609                     {
4610                         // In non-inline cases, note written-to locals.
4611                         if (lvaTable[varNum].lvHasILStoreOp)
4612                         {
4613                             lvaTable[varNum].lvHasMultipleILStoreOp = 1;
4614                         }
4615                         else
4616                         {
4617                             lvaTable[varNum].lvHasILStoreOp = 1;
4618                         }
4619                     }
4620                 }
4621             }
4622             break;
4623
4624             case CEE_LDARGA:
4625             case CEE_LDARGA_S:
4626             case CEE_LDLOCA:
4627             case CEE_LDLOCA_S:
4628             {
4629                 // Handle address-taken args or locals
4630                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4631
4632                 if (codeAddr > codeEndp - sz)
4633                 {
4634                     goto TOO_FAR;
4635                 }
4636
4637                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4638
4639                 if (isInlining)
4640                 {
4641                     if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
4642                     {
4643                         varType = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclTypeInfo;
4644                         ti      = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclVerTypeInfo;
4645
4646                         impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclHasLdlocaOp = true;
4647                     }
4648                     else
4649                     {
4650                         noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
4651
4652                         varType = impInlineInfo->lclVarInfo[varNum].lclTypeInfo;
4653                         ti      = impInlineInfo->lclVarInfo[varNum].lclVerTypeInfo;
4654
4655                         impInlineInfo->inlArgInfo[varNum].argHasLdargaOp = true;
4656
4657                         pushedStack.PushArgument(varNum);
4658                     }
4659                 }
4660                 else
4661                 {
4662                     if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
4663                     {
4664                         if (varNum >= info.compMethodInfo->locals.numArgs)
4665                         {
4666                             BADCODE("bad local number");
4667                         }
4668
4669                         varNum += info.compArgsCount;
4670                     }
4671                     else
4672                     {
4673                         noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
4674
4675                         if (varNum >= info.compILargsCount)
4676                         {
4677                             BADCODE("bad argument number");
4678                         }
4679
4680                         varNum = compMapILargNum(varNum); // account for possible hidden param
4681                     }
4682
4683                     varType = (var_types)lvaTable[varNum].lvType;
4684                     ti      = lvaTable[varNum].lvVerTypeInfo;
4685
4686                     // Determine if the next instruction will consume
4687                     // the address. If so we won't mark this var as
4688                     // address taken.
4689                     //
4690                     // We will put structs on the stack and changing
4691                     // the addrTaken of a local requires an extra pass
4692                     // in the morpher so we won't apply this
4693                     // optimization to structs.
4694                     //
4695                     // Debug code spills for every IL instruction, and
4696                     // therefore it will split statements, so we will
4697                     // need the address.  Note that this optimization
4698                     // is based in that we know what trees we will
4699                     // generate for this ldfld, and we require that we
4700                     // won't need the address of this local at all
4701                     noway_assert(varNum < lvaTableCnt);
4702
4703                     const bool notStruct    = !varTypeIsStruct(&lvaTable[varNum]);
4704                     const bool notLastInstr = (codeAddr < codeEndp - sz);
4705                     const bool notDebugCode = !opts.compDbgCode;
4706
4707                     if (notStruct && notLastInstr && notDebugCode &&
4708                         impILConsumesAddr(codeAddr + sz, impTokenLookupContextHandle, info.compScopeHnd))
4709                     {
4710                         // We can skip the addrtaken, as next IL instruction consumes
4711                         // the address.
4712                     }
4713                     else
4714                     {
4715                         lvaTable[varNum].lvHasLdAddrOp = 1;
4716                         if (!info.compIsStatic && (varNum == 0))
4717                         {
4718                             // Addr taken on "this" pointer is significant,
4719                             // go ahead to mark it as permanently addr-exposed here.
4720                             lvaSetVarAddrExposed(0);
4721                             // This may be conservative, but probably not very.
4722                         }
4723                     }
4724                 } // isInlining
4725
4726                 typeIsNormed = ti.IsValueClass() && !varTypeIsStruct(varType);
4727             }
4728             break;
4729
4730             case CEE_JMP:
4731                 retBlocks++;
4732
4733 #if !defined(_TARGET_X86_) && !defined(_TARGET_ARM_)
4734                 if (!isInlining)
4735                 {
4736                     // We transform this into a set of ldarg's + tail call and
4737                     // thus may push more onto the stack than originally thought.
4738                     // This doesn't interfere with verification because CEE_JMP
4739                     // is never verifiable, and there's nothing unsafe you can
4740                     // do with a an IL stack overflow if the JIT is expecting it.
4741                     info.compMaxStack = max(info.compMaxStack, info.compILargsCount);
4742                     break;
4743                 }
4744 #endif // !_TARGET_X86_ && !_TARGET_ARM_
4745
4746                 // If we are inlining, we need to fail for a CEE_JMP opcode, just like
4747                 // the list of other opcodes (for all platforms).
4748
4749                 __fallthrough;
4750
4751             case CEE_CALLI:
4752             case CEE_LOCALLOC:
4753             case CEE_MKREFANY:
4754             case CEE_RETHROW:
4755                 // CEE_CALLI should not be inlined because the JIT cannot generate an inlined call frame. If the call
4756                 // target
4757                 // is a no-marshal CALLI P/Invoke we end up calling the IL stub. We don't NGEN these stubs, so we'll
4758                 // have to
4759                 // JIT an IL stub for a trivial func. It's almost certainly a better choice to leave out the inline
4760                 // candidate so we can generate an inlined call frame. It might be nice to call getCallInfo to figure
4761                 // out
4762                 // what kind of call we have here.
4763
4764                 // Consider making this only for not force inline.
4765                 if (makeInlineObservations)
4766                 {
4767                     // Arguably this should be NoteFatal, but the legacy behavior is
4768                     // to ignore this for the prejit root.
4769                     compInlineResult->Note(InlineObservation::CALLEE_UNSUPPORTED_OPCODE);
4770
4771                     // Fail fast if we're inlining...
4772                     if (isInlining)
4773                     {
4774                         assert(compInlineResult->IsFailure());
4775                         return;
4776                     }
4777                 }
4778                 break;
4779
4780             case CEE_LDARG_0:
4781             case CEE_LDARG_1:
4782             case CEE_LDARG_2:
4783             case CEE_LDARG_3:
4784                 if (makeInlineObservations)
4785                 {
4786                     pushedStack.PushArgument(opcode - CEE_LDARG_0);
4787                 }
4788                 break;
4789
4790             case CEE_LDARG_S:
4791             case CEE_LDARG:
4792             {
4793                 if (codeAddr > codeEndp - sz)
4794                 {
4795                     goto TOO_FAR;
4796                 }
4797
4798                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4799
4800                 if (makeInlineObservations)
4801                 {
4802                     pushedStack.PushArgument(varNum);
4803                 }
4804             }
4805             break;
4806
4807             case CEE_LDLEN:
4808                 if (makeInlineObservations)
4809                 {
4810                     pushedStack.PushArrayLen();
4811                 }
4812                 break;
4813
4814             case CEE_CEQ:
4815             case CEE_CGT:
4816             case CEE_CGT_UN:
4817             case CEE_CLT:
4818             case CEE_CLT_UN:
4819                 if (makeInlineObservations)
4820                 {
4821                     fgObserveInlineConstants(opcode, pushedStack, isInlining);
4822                 }
4823                 break;
4824             case CEE_RET:
4825                 retBlocks++;
4826
4827             default:
4828                 break;
4829         }
4830
4831         // Skip any remaining operands this opcode may have
4832         codeAddr += sz;
4833
4834         // Note the opcode we just saw
4835         if (makeInlineObservations)
4836         {
4837             InlineObservation obs =
4838                 typeIsNormed ? InlineObservation::CALLEE_OPCODE_NORMED : InlineObservation::CALLEE_OPCODE;
4839             compInlineResult->NoteInt(obs, opcode);
4840         }
4841     }
4842
4843     if (codeAddr != codeEndp)
4844     {
4845     TOO_FAR:
4846         BADCODE3("Code ends in the middle of an opcode, or there is a branch past the end of the method",
4847                  " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4848     }
4849
4850     if (makeInlineObservations)
4851     {
4852         compInlineResult->Note(InlineObservation::CALLEE_END_OPCODE_SCAN);
4853
4854         if (!compInlineResult->UsesLegacyPolicy())
4855         {
4856             // If there are no return blocks we know it does not return, however if there
4857             // return blocks we don't know it returns as it may be counting unreachable code.
4858             // However we will still make the CALLEE_DOES_NOT_RETURN observation.
4859
4860             compInlineResult->NoteBool(InlineObservation::CALLEE_DOES_NOT_RETURN, retBlocks == 0);
4861
4862             if (retBlocks == 0 && isInlining)
4863             {
4864                 // Mark the call node as "no return" as it can impact caller's code quality.
4865                 impInlineInfo->iciCall->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN;
4866             }
4867         }
4868
4869         // Determine if call site is within a try.
4870         if (isInlining && impInlineInfo->iciBlock->hasTryIndex())
4871         {
4872             compInlineResult->Note(InlineObservation::CALLSITE_IN_TRY_REGION);
4873         }
4874
4875         // If the inline is viable and discretionary, do the
4876         // profitability screening.
4877         if (compInlineResult->IsDiscretionaryCandidate())
4878         {
4879             // Make some callsite specific observations that will feed
4880             // into the profitability model.
4881             impMakeDiscretionaryInlineObservations(impInlineInfo, compInlineResult);
4882
4883             // None of those observations should have changed the
4884             // inline's viability.
4885             assert(compInlineResult->IsCandidate());
4886
4887             if (isInlining)
4888             {
4889                 // Assess profitability...
4890                 CORINFO_METHOD_INFO* methodInfo = &impInlineInfo->inlineCandidateInfo->methInfo;
4891                 compInlineResult->DetermineProfitability(methodInfo);
4892
4893                 if (compInlineResult->IsFailure())
4894                 {
4895                     impInlineRoot()->m_inlineStrategy->NoteUnprofitable();
4896                     JITDUMP("\n\nInline expansion aborted, inline not profitable\n");
4897                     return;
4898                 }
4899                 else
4900                 {
4901                     // The inline is still viable.
4902                     assert(compInlineResult->IsCandidate());
4903                 }
4904             }
4905             else
4906             {
4907                 // Prejit root case. Profitability assessment for this
4908                 // is done over in compCompileHelper.
4909             }
4910         }
4911     }
4912
4913     // None of the local vars in the inlinee should have address taken or been written to.
4914     // Therefore we should NOT need to enter this "if" statement.
4915     if (!isInlining && !info.compIsStatic)
4916     {
4917         fgAdjustForAddressExposedOrWrittenThis();
4918     }
4919 }
4920
4921 #ifdef _PREFAST_
4922 #pragma warning(pop)
4923 #endif
4924
4925 //------------------------------------------------------------------------
4926 // fgAdjustForAddressExposedOrWrittenThis: update var table for cases
4927 //   where the this pointer value can change.
4928 //
4929 // Notes:
4930 //    Modifies lvaArg0Var to refer to a temp if the value of 'this' can
4931 //    change. The original this (info.compThisArg) then remains
4932 //    unmodified in the method.  fgAddInternal is reponsible for
4933 //    adding the code to copy the initial this into the temp.
4934
4935 void Compiler::fgAdjustForAddressExposedOrWrittenThis()
4936 {
4937     // Optionally enable adjustment during stress.
4938     if (!tiVerificationNeeded && compStressCompile(STRESS_GENERIC_VARN, 15))
4939     {
4940         lvaTable[info.compThisArg].lvHasILStoreOp = true;
4941     }
4942
4943     // If this is exposed or written to, create a temp for the modifiable this
4944     if (lvaTable[info.compThisArg].lvAddrExposed || lvaTable[info.compThisArg].lvHasILStoreOp)
4945     {
4946         // If there is a "ldarga 0" or "starg 0", grab and use the temp.
4947         lvaArg0Var = lvaGrabTemp(false DEBUGARG("Address-exposed, or written this pointer"));
4948         noway_assert(lvaArg0Var > (unsigned)info.compThisArg);
4949         lvaTable[lvaArg0Var].lvType            = lvaTable[info.compThisArg].TypeGet();
4950         lvaTable[lvaArg0Var].lvAddrExposed     = lvaTable[info.compThisArg].lvAddrExposed;
4951         lvaTable[lvaArg0Var].lvDoNotEnregister = lvaTable[info.compThisArg].lvDoNotEnregister;
4952 #ifdef DEBUG
4953         lvaTable[lvaArg0Var].lvVMNeedsStackAddr = lvaTable[info.compThisArg].lvVMNeedsStackAddr;
4954         lvaTable[lvaArg0Var].lvLiveInOutOfHndlr = lvaTable[info.compThisArg].lvLiveInOutOfHndlr;
4955         lvaTable[lvaArg0Var].lvLclFieldExpr     = lvaTable[info.compThisArg].lvLclFieldExpr;
4956         lvaTable[lvaArg0Var].lvLiveAcrossUCall  = lvaTable[info.compThisArg].lvLiveAcrossUCall;
4957 #endif
4958         lvaTable[lvaArg0Var].lvHasILStoreOp = lvaTable[info.compThisArg].lvHasILStoreOp;
4959         lvaTable[lvaArg0Var].lvVerTypeInfo  = lvaTable[info.compThisArg].lvVerTypeInfo;
4960
4961         // Clear the TI_FLAG_THIS_PTR in the original 'this' pointer.
4962         noway_assert(lvaTable[lvaArg0Var].lvVerTypeInfo.IsThisPtr());
4963         lvaTable[info.compThisArg].lvVerTypeInfo.ClearThisPtr();
4964         lvaTable[info.compThisArg].lvAddrExposed  = false;
4965         lvaTable[info.compThisArg].lvHasILStoreOp = false;
4966     }
4967 }
4968
4969 //------------------------------------------------------------------------
4970 // fgObserveInlineConstants: look for operations that might get optimized
4971 //   if this method were to be inlined, and report these to the inliner.
4972 //
4973 // Arguments:
4974 //    opcode     -- MSIL opcode under consideration
4975 //    stack      -- abstract stack model at this point in the IL
4976 //    isInlining -- true if we're inlining (vs compiling a prejit root)
4977 //
4978 // Notes:
4979 //    Currently only invoked on compare and branch opcodes.
4980 //
4981 //    If we're inlining we also look at the argument values supplied by
4982 //    the caller at this call site.
4983 //
4984 //    The crude stack model may overestimate stack depth.
4985
4986 void Compiler::fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, bool isInlining)
4987 {
4988     // We should be able to record inline observations.
4989     assert(compInlineResult != nullptr);
4990
4991     // The stack only has to be 1 deep for BRTRUE/FALSE
4992     bool lookForBranchCases = stack.IsStackAtLeastOneDeep();
4993
4994     if (compInlineResult->UsesLegacyPolicy())
4995     {
4996         // LegacyPolicy misses cases where the stack is really one
4997         // deep but the model says it's two deep. We need to do
4998         // likewise to preseve old behavior.
4999         lookForBranchCases &= !stack.IsStackTwoDeep();
5000     }
5001
5002     if (lookForBranchCases)
5003     {
5004         if (opcode == CEE_BRFALSE || opcode == CEE_BRFALSE_S || opcode == CEE_BRTRUE || opcode == CEE_BRTRUE_S)
5005         {
5006             unsigned slot0 = stack.GetSlot0();
5007             if (FgStack::IsArgument(slot0))
5008             {
5009                 compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST);
5010
5011                 if (isInlining)
5012                 {
5013                     // Check for the double whammy of an incoming constant argument
5014                     // feeding a constant test.
5015                     unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
5016                     if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5017                     {
5018                         compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5019                     }
5020                 }
5021             }
5022
5023             return;
5024         }
5025     }
5026
5027     // Remaining cases require at least two things on the stack.
5028     if (!stack.IsStackTwoDeep())
5029     {
5030         return;
5031     }
5032
5033     unsigned slot0 = stack.GetSlot0();
5034     unsigned slot1 = stack.GetSlot1();
5035
5036     // Arg feeds constant test
5037     if ((FgStack::IsConstant(slot0) && FgStack::IsArgument(slot1)) ||
5038         (FgStack::IsConstant(slot1) && FgStack::IsArgument(slot0)))
5039     {
5040         compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST);
5041     }
5042
5043     // Arg feeds range check
5044     if ((FgStack::IsArrayLen(slot0) && FgStack::IsArgument(slot1)) ||
5045         (FgStack::IsArrayLen(slot1) && FgStack::IsArgument(slot0)))
5046     {
5047         compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_RANGE_CHECK);
5048     }
5049
5050     // Check for an incoming arg that's a constant
5051     if (isInlining)
5052     {
5053         if (FgStack::IsArgument(slot0))
5054         {
5055             unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
5056             if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5057             {
5058                 compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5059             }
5060         }
5061
5062         if (FgStack::IsArgument(slot1))
5063         {
5064             unsigned varNum = FgStack::SlotTypeToArgNum(slot1);
5065             if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5066             {
5067                 compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5068             }
5069         }
5070     }
5071 }
5072
5073 /*****************************************************************************
5074  *
5075  *  Finally link up the bbJumpDest of the blocks together
5076  */
5077
5078 void Compiler::fgMarkBackwardJump(BasicBlock* startBlock, BasicBlock* endBlock)
5079 {
5080     noway_assert(startBlock->bbNum <= endBlock->bbNum);
5081
5082     for (BasicBlock* block = startBlock; block != endBlock->bbNext; block = block->bbNext)
5083     {
5084         if ((block->bbFlags & BBF_BACKWARD_JUMP) == 0)
5085         {
5086             block->bbFlags |= BBF_BACKWARD_JUMP;
5087         }
5088     }
5089 }
5090
5091 /*****************************************************************************
5092  *
5093  *  Finally link up the bbJumpDest of the blocks together
5094  */
5095
5096 void Compiler::fgLinkBasicBlocks()
5097 {
5098     /* Create the basic block lookup tables */
5099
5100     fgInitBBLookup();
5101
5102     /* First block is always reachable */
5103
5104     fgFirstBB->bbRefs = 1;
5105
5106     /* Walk all the basic blocks, filling in the target addresses */
5107
5108     for (BasicBlock* curBBdesc = fgFirstBB; curBBdesc; curBBdesc = curBBdesc->bbNext)
5109     {
5110         switch (curBBdesc->bbJumpKind)
5111         {
5112             case BBJ_COND:
5113             case BBJ_ALWAYS:
5114             case BBJ_LEAVE:
5115                 curBBdesc->bbJumpDest = fgLookupBB(curBBdesc->bbJumpOffs);
5116                 curBBdesc->bbJumpDest->bbRefs++;
5117                 if (curBBdesc->bbJumpDest->bbNum <= curBBdesc->bbNum)
5118                 {
5119                     fgMarkBackwardJump(curBBdesc->bbJumpDest, curBBdesc);
5120                 }
5121
5122                 /* Is the next block reachable? */
5123
5124                 if (curBBdesc->bbJumpKind == BBJ_ALWAYS || curBBdesc->bbJumpKind == BBJ_LEAVE)
5125                 {
5126                     break;
5127                 }
5128
5129                 if (!curBBdesc->bbNext)
5130                 {
5131                     BADCODE("Fall thru the end of a method");
5132                 }
5133
5134             // Fall through, the next block is also reachable
5135
5136             case BBJ_NONE:
5137                 curBBdesc->bbNext->bbRefs++;
5138                 break;
5139
5140             case BBJ_EHFINALLYRET:
5141             case BBJ_EHFILTERRET:
5142             case BBJ_THROW:
5143             case BBJ_RETURN:
5144                 break;
5145
5146             case BBJ_SWITCH:
5147
5148                 unsigned jumpCnt;
5149                 jumpCnt = curBBdesc->bbJumpSwt->bbsCount;
5150                 BasicBlock** jumpPtr;
5151                 jumpPtr = curBBdesc->bbJumpSwt->bbsDstTab;
5152
5153                 do
5154                 {
5155                     *jumpPtr = fgLookupBB((unsigned)*(size_t*)jumpPtr);
5156                     (*jumpPtr)->bbRefs++;
5157                     if ((*jumpPtr)->bbNum <= curBBdesc->bbNum)
5158                     {
5159                         fgMarkBackwardJump(*jumpPtr, curBBdesc);
5160                     }
5161                 } while (++jumpPtr, --jumpCnt);
5162
5163                 /* Default case of CEE_SWITCH (next block), is at end of jumpTab[] */
5164
5165                 noway_assert(*(jumpPtr - 1) == curBBdesc->bbNext);
5166                 break;
5167
5168             case BBJ_CALLFINALLY: // BBJ_CALLFINALLY and BBJ_EHCATCHRET don't appear until later
5169             case BBJ_EHCATCHRET:
5170             default:
5171                 noway_assert(!"Unexpected bbJumpKind");
5172                 break;
5173         }
5174     }
5175 }
5176
5177 /*****************************************************************************
5178  *
5179  *  Walk the instrs to create the basic blocks. Returns the number of BBJ_RETURN in method
5180  */
5181
5182 unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget)
5183 {
5184     unsigned    retBlocks;
5185     const BYTE* codeBegp = codeAddr;
5186     const BYTE* codeEndp = codeAddr + codeSize;
5187     bool        tailCall = false;
5188     unsigned    curBBoffs;
5189     BasicBlock* curBBdesc;
5190
5191     retBlocks = 0;
5192     /* Clear the beginning offset for the first BB */
5193
5194     curBBoffs = 0;
5195
5196     if (opts.compDbgCode && (info.compVarScopesCount > 0))
5197     {
5198         compResetScopeLists();
5199
5200         // Ignore scopes beginning at offset 0
5201         while (compGetNextEnterScope(0))
5202         { /* do nothing */
5203         }
5204         while (compGetNextExitScope(0))
5205         { /* do nothing */
5206         }
5207     }
5208
5209     BBjumpKinds jmpKind;
5210
5211     do
5212     {
5213         OPCODE     opcode;
5214         unsigned   sz;
5215         unsigned   jmpAddr = DUMMY_INIT(BAD_IL_OFFSET);
5216         unsigned   bbFlags = 0;
5217         BBswtDesc* swtDsc  = nullptr;
5218         unsigned   nxtBBoffs;
5219
5220         opcode = (OPCODE)getU1LittleEndian(codeAddr);
5221         codeAddr += sizeof(__int8);
5222         jmpKind = BBJ_NONE;
5223
5224     DECODE_OPCODE:
5225
5226         /* Get the size of additional parameters */
5227
5228         noway_assert(opcode < CEE_COUNT);
5229
5230         sz = opcodeSizes[opcode];
5231
5232         switch (opcode)
5233         {
5234             signed jmpDist;
5235
5236             case CEE_PREFIX1:
5237                 if (jumpTarget[codeAddr - codeBegp] != JT_NONE)
5238                 {
5239                     BADCODE3("jump target between prefix 0xFE and opcode", " at offset %04X",
5240                              (IL_OFFSET)(codeAddr - codeBegp));
5241                 }
5242
5243                 opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr));
5244                 codeAddr += sizeof(__int8);
5245                 goto DECODE_OPCODE;
5246
5247             /* Check to see if we have a jump/return opcode */
5248
5249             case CEE_BRFALSE:
5250             case CEE_BRFALSE_S:
5251             case CEE_BRTRUE:
5252             case CEE_BRTRUE_S:
5253
5254             case CEE_BEQ:
5255             case CEE_BEQ_S:
5256             case CEE_BGE:
5257             case CEE_BGE_S:
5258             case CEE_BGE_UN:
5259             case CEE_BGE_UN_S:
5260             case CEE_BGT:
5261             case CEE_BGT_S:
5262             case CEE_BGT_UN:
5263             case CEE_BGT_UN_S:
5264             case CEE_BLE:
5265             case CEE_BLE_S:
5266             case CEE_BLE_UN:
5267             case CEE_BLE_UN_S:
5268             case CEE_BLT:
5269             case CEE_BLT_S:
5270             case CEE_BLT_UN:
5271             case CEE_BLT_UN_S:
5272             case CEE_BNE_UN:
5273             case CEE_BNE_UN_S:
5274
5275                 jmpKind = BBJ_COND;
5276                 goto JMP;
5277
5278             case CEE_LEAVE:
5279             case CEE_LEAVE_S:
5280
5281                 // We need to check if we are jumping out of a finally-protected try.
5282                 jmpKind = BBJ_LEAVE;
5283                 goto JMP;
5284
5285             case CEE_BR:
5286             case CEE_BR_S:
5287                 jmpKind = BBJ_ALWAYS;
5288                 goto JMP;
5289
5290             JMP:
5291
5292                 /* Compute the target address of the jump */
5293
5294                 jmpDist = (sz == 1) ? getI1LittleEndian(codeAddr) : getI4LittleEndian(codeAddr);
5295
5296                 if (compIsForInlining() && jmpDist == 0 && (opcode == CEE_BR || opcode == CEE_BR_S))
5297                 {
5298                     continue; /* NOP */
5299                 }
5300
5301                 jmpAddr = (IL_OFFSET)(codeAddr - codeBegp) + sz + jmpDist;
5302                 break;
5303
5304             case CEE_SWITCH:
5305             {
5306                 unsigned jmpBase;
5307                 unsigned jmpCnt; // # of switch cases (excluding defualt)
5308
5309                 BasicBlock** jmpTab;
5310                 BasicBlock** jmpPtr;
5311
5312                 /* Allocate the switch descriptor */
5313
5314                 swtDsc = new (this, CMK_BasicBlock) BBswtDesc;
5315
5316                 /* Read the number of entries in the table */
5317
5318                 jmpCnt = getU4LittleEndian(codeAddr);
5319                 codeAddr += 4;
5320
5321                 /* Compute  the base offset for the opcode */
5322
5323                 jmpBase = (IL_OFFSET)((codeAddr - codeBegp) + jmpCnt * sizeof(DWORD));
5324
5325                 /* Allocate the jump table */
5326
5327                 jmpPtr = jmpTab = new (this, CMK_BasicBlock) BasicBlock*[jmpCnt + 1];
5328
5329                 /* Fill in the jump table */
5330
5331                 for (unsigned count = jmpCnt; count; count--)
5332                 {
5333                     jmpDist = getI4LittleEndian(codeAddr);
5334                     codeAddr += 4;
5335
5336                     // store the offset in the pointer.  We change these in fgLinkBasicBlocks().
5337                     *jmpPtr++ = (BasicBlock*)(size_t)(jmpBase + jmpDist);
5338                 }
5339
5340                 /* Append the default label to the target table */
5341
5342                 *jmpPtr++ = (BasicBlock*)(size_t)jmpBase;
5343
5344                 /* Make sure we found the right number of labels */
5345
5346                 noway_assert(jmpPtr == jmpTab + jmpCnt + 1);
5347
5348                 /* Compute the size of the switch opcode operands */
5349
5350                 sz = sizeof(DWORD) + jmpCnt * sizeof(DWORD);
5351
5352                 /* Fill in the remaining fields of the switch descriptor */
5353
5354                 swtDsc->bbsCount  = jmpCnt + 1;
5355                 swtDsc->bbsDstTab = jmpTab;
5356
5357                 /* This is definitely a jump */
5358
5359                 jmpKind     = BBJ_SWITCH;
5360                 fgHasSwitch = true;
5361
5362 #ifndef LEGACY_BACKEND
5363                 if (opts.compProcedureSplitting)
5364                 {
5365                     // TODO-CQ: We might need to create a switch table; we won't know for sure until much later.
5366                     // However, switch tables don't work with hot/cold splitting, currently. The switch table data needs
5367                     // a relocation such that if the base (the first block after the prolog) and target of the switch
5368                     // branch are put in different sections, the difference stored in the table is updated. However, our
5369                     // relocation implementation doesn't support three different pointers (relocation address, base, and
5370                     // target). So, we need to change our switch table implementation to be more like
5371                     // JIT64: put the table in the code section, in the same hot/cold section as the switch jump itself
5372                     // (maybe immediately after the switch jump), and make the "base" address be also in that section,
5373                     // probably the address after the switch jump.
5374                     opts.compProcedureSplitting = false;
5375                     JITDUMP("Turning off procedure splitting for this method, as it might need switch tables; "
5376                             "implementation limitation.\n");
5377                 }
5378 #endif // !LEGACY_BACKEND
5379             }
5380                 goto GOT_ENDP;
5381
5382             case CEE_ENDFILTER:
5383                 bbFlags |= BBF_DONT_REMOVE;
5384                 jmpKind = BBJ_EHFILTERRET;
5385                 break;
5386
5387             case CEE_ENDFINALLY:
5388                 jmpKind = BBJ_EHFINALLYRET;
5389                 break;
5390
5391             case CEE_TAILCALL:
5392                 if (compIsForInlining())
5393                 {
5394                     // TODO-CQ: We can inline some callees with explicit tail calls if we can guarantee that the calls
5395                     // can be dispatched as tail calls from the caller.
5396                     compInlineResult->NoteFatal(InlineObservation::CALLEE_EXPLICIT_TAIL_PREFIX);
5397                     retBlocks++;
5398                     return retBlocks;
5399                 }
5400
5401                 __fallthrough;
5402
5403             case CEE_READONLY:
5404             case CEE_CONSTRAINED:
5405             case CEE_VOLATILE:
5406             case CEE_UNALIGNED:
5407                 // fgFindJumpTargets should have ruled out this possibility
5408                 //   (i.e. a prefix opcodes as last intruction in a block)
5409                 noway_assert(codeAddr < codeEndp);
5410
5411                 if (jumpTarget[codeAddr - codeBegp] != JT_NONE)
5412                 {
5413                     BADCODE3("jump target between prefix and an opcode", " at offset %04X",
5414                              (IL_OFFSET)(codeAddr - codeBegp));
5415                 }
5416                 break;
5417
5418             case CEE_CALL:
5419             case CEE_CALLVIRT:
5420             case CEE_CALLI:
5421             {
5422                 if (compIsForInlining() ||               // Ignore tail call in the inlinee. Period.
5423                     (!tailCall && !compTailCallStress()) // A new BB with BBJ_RETURN would have been created
5424
5425                     // after a tailcall statement.
5426                     // We need to keep this invariant if we want to stress the tailcall.
5427                     // That way, the potential (tail)call statement is always the last
5428                     // statement in the block.
5429                     // Otherwise, we will assert at the following line in fgMorphCall()
5430                     //     noway_assert(fgMorphStmt->gtNext == NULL);
5431                     )
5432                 {
5433                     // Neither .tailcall prefix, no tailcall stress. So move on.
5434                     break;
5435                 }
5436
5437                 // Make sure the code sequence is legal for the tail call.
5438                 // If so, mark this BB as having a BBJ_RETURN.
5439
5440                 if (codeAddr >= codeEndp - sz)
5441                 {
5442                     BADCODE3("No code found after the call instruction", " at offset %04X",
5443                              (IL_OFFSET)(codeAddr - codeBegp));
5444                 }
5445
5446                 if (tailCall)
5447                 {
5448                     bool isCallPopAndRet = false;
5449
5450                     // impIsTailCallILPattern uses isRecursive flag to determine whether ret in a fallthrough block is
5451                     // allowed. We don't know at this point whether the call is recursive so we conservatively pass
5452                     // false. This will only affect explicit tail calls when IL verification is not needed for the
5453                     // method.
5454                     bool isRecursive = false;
5455                     if (!impIsTailCallILPattern(tailCall, opcode, codeAddr + sz, codeEndp, isRecursive,
5456                                                 &isCallPopAndRet))
5457                     {
5458 #ifdef _TARGET_AMD64_
5459                         BADCODE3("tail call not followed by ret or pop+ret", " at offset %04X",
5460                                  (IL_OFFSET)(codeAddr - codeBegp));
5461 #else
5462                         BADCODE3("tail call not followed by ret", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5463 #endif //_TARGET_AMD64_
5464                     }
5465
5466 #ifdef _TARGET_AMD64_
5467                     if (isCallPopAndRet)
5468                     {
5469                         // By breaking here, we let pop and ret opcodes to be
5470                         // imported after tail call.  If tail prefix is honored,
5471                         // stmts corresponding to pop and ret will be removed
5472                         // in fgMorphCall().
5473                         break;
5474                     }
5475 #endif //_TARGET_AMD64_
5476                 }
5477                 else
5478                 {
5479                     OPCODE nextOpcode = (OPCODE)getU1LittleEndian(codeAddr + sz);
5480
5481                     if (nextOpcode != CEE_RET)
5482                     {
5483                         noway_assert(compTailCallStress());
5484                         // Next OPCODE is not a CEE_RET, bail the attempt to stress the tailcall.
5485                         // (I.e. We will not make a new BB after the "call" statement.)
5486                         break;
5487                     }
5488                 }
5489             }
5490
5491             /* For tail call, we just call CORINFO_HELP_TAILCALL, and it jumps to the
5492                target. So we don't need an epilog - just like CORINFO_HELP_THROW.
5493                Make the block BBJ_RETURN, but we will change it to BBJ_THROW
5494                if the tailness of the call is satisfied.
5495                NOTE : The next instruction is guaranteed to be a CEE_RET
5496                and it will create another BasicBlock. But there may be an
5497                jump directly to that CEE_RET. If we want to avoid creating
5498                an unnecessary block, we need to check if the CEE_RETURN is
5499                the target of a jump.
5500              */
5501
5502             // fall-through
5503
5504             case CEE_JMP:
5505             /* These are equivalent to a return from the current method
5506                But instead of directly returning to the caller we jump and
5507                execute something else in between */
5508             case CEE_RET:
5509                 retBlocks++;
5510                 jmpKind = BBJ_RETURN;
5511                 break;
5512
5513             case CEE_THROW:
5514             case CEE_RETHROW:
5515                 jmpKind = BBJ_THROW;
5516                 break;
5517
5518 #ifdef DEBUG
5519 // make certain we did not forget any flow of control instructions
5520 // by checking the 'ctrl' field in opcode.def. First filter out all
5521 // non-ctrl instructions
5522 #define BREAK(name)                                                                                                    \
5523     case name:                                                                                                         \
5524         break;
5525 #define NEXT(name)                                                                                                     \
5526     case name:                                                                                                         \
5527         break;
5528 #define CALL(name)
5529 #define THROW(name)
5530 #undef RETURN // undef contract RETURN macro
5531 #define RETURN(name)
5532 #define META(name)
5533 #define BRANCH(name)
5534 #define COND_BRANCH(name)
5535 #define PHI(name)
5536
5537 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) ctrl(name)
5538 #include "opcode.def"
5539 #undef OPDEF
5540
5541 #undef PHI
5542 #undef BREAK
5543 #undef CALL
5544 #undef NEXT
5545 #undef THROW
5546 #undef RETURN
5547 #undef META
5548 #undef BRANCH
5549 #undef COND_BRANCH
5550
5551             // These ctrl-flow opcodes don't need any special handling
5552             case CEE_NEWOBJ: // CTRL_CALL
5553                 break;
5554
5555             // what's left are forgotten instructions
5556             default:
5557                 BADCODE("Unrecognized control Opcode");
5558                 break;
5559 #else  // !DEBUG
5560             default:
5561                 break;
5562 #endif // !DEBUG
5563         }
5564
5565         /* Jump over the operand */
5566
5567         codeAddr += sz;
5568
5569     GOT_ENDP:
5570
5571         tailCall = (opcode == CEE_TAILCALL);
5572
5573         /* Make sure a jump target isn't in the middle of our opcode */
5574
5575         if (sz)
5576         {
5577             IL_OFFSET offs = (IL_OFFSET)(codeAddr - codeBegp) - sz; // offset of the operand
5578
5579             for (unsigned i = 0; i < sz; i++, offs++)
5580             {
5581                 if (jumpTarget[offs] != JT_NONE)
5582                 {
5583                     BADCODE3("jump into the middle of an opcode", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5584                 }
5585             }
5586         }
5587
5588         /* Compute the offset of the next opcode */
5589
5590         nxtBBoffs = (IL_OFFSET)(codeAddr - codeBegp);
5591
5592         bool foundScope = false;
5593
5594         if (opts.compDbgCode && (info.compVarScopesCount > 0))
5595         {
5596             while (compGetNextEnterScope(nxtBBoffs))
5597             {
5598                 foundScope = true;
5599             }
5600             while (compGetNextExitScope(nxtBBoffs))
5601             {
5602                 foundScope = true;
5603             }
5604         }
5605
5606         /* Do we have a jump? */
5607
5608         if (jmpKind == BBJ_NONE)
5609         {
5610             /* No jump; make sure we don't fall off the end of the function */
5611
5612             if (codeAddr == codeEndp)
5613             {
5614                 BADCODE3("missing return opcode", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5615             }
5616
5617             /* If a label follows this opcode, we'll have to make a new BB */
5618
5619             bool makeBlock = (jumpTarget[nxtBBoffs] != JT_NONE);
5620
5621             if (!makeBlock && foundScope)
5622             {
5623                 makeBlock = true;
5624 #ifdef DEBUG
5625                 if (verbose)
5626                 {
5627                     printf("Splitting at BBoffs = %04u\n", nxtBBoffs);
5628                 }
5629 #endif // DEBUG
5630             }
5631
5632             if (!makeBlock)
5633             {
5634                 continue;
5635             }
5636         }
5637
5638         /* We need to create a new basic block */
5639
5640         curBBdesc = fgNewBasicBlock(jmpKind);
5641
5642         curBBdesc->bbFlags |= bbFlags;
5643         curBBdesc->bbRefs = 0;
5644
5645         curBBdesc->bbCodeOffs    = curBBoffs;
5646         curBBdesc->bbCodeOffsEnd = nxtBBoffs;
5647
5648         unsigned profileWeight;
5649         if (fgGetProfileWeightForBasicBlock(curBBoffs, &profileWeight))
5650         {
5651             curBBdesc->setBBProfileWeight(profileWeight);
5652             if (profileWeight == 0)
5653             {
5654                 curBBdesc->bbSetRunRarely();
5655             }
5656             else
5657             {
5658                 // Note that bbNewBasicBlock (called from fgNewBasicBlock) may have
5659                 // already marked the block as rarely run.  In that case (and when we know
5660                 // that the block profile weight is non-zero) we want to unmark that.
5661
5662                 curBBdesc->bbFlags &= ~BBF_RUN_RARELY;
5663             }
5664         }
5665
5666         switch (jmpKind)
5667         {
5668             case BBJ_SWITCH:
5669                 curBBdesc->bbJumpSwt = swtDsc;
5670                 break;
5671
5672             case BBJ_COND:
5673             case BBJ_ALWAYS:
5674             case BBJ_LEAVE:
5675                 noway_assert(jmpAddr != DUMMY_INIT(BAD_IL_OFFSET));
5676                 curBBdesc->bbJumpOffs = jmpAddr;
5677                 break;
5678
5679             default:
5680                 break;
5681         }
5682
5683         DBEXEC(verbose, curBBdesc->dspBlockHeader(this, false, false, false));
5684
5685         /* Remember where the next BB will start */
5686
5687         curBBoffs = nxtBBoffs;
5688     } while (codeAddr < codeEndp);
5689
5690     noway_assert(codeAddr == codeEndp);
5691
5692     /* Finally link up the bbJumpDest of the blocks together */
5693
5694     fgLinkBasicBlocks();
5695
5696     return retBlocks;
5697 }
5698
5699 /*****************************************************************************
5700  *
5701  *  Main entry point to discover the basic blocks for the current function.
5702  */
5703
5704 void Compiler::fgFindBasicBlocks()
5705 {
5706 #ifdef DEBUG
5707     if (verbose)
5708     {
5709         printf("*************** In fgFindBasicBlocks() for %s\n", info.compFullName);
5710     }
5711 #endif
5712
5713     /* Allocate the 'jump target' vector
5714      *
5715      *  We need one extra byte as we mark
5716      *  jumpTarget[info.compILCodeSize] with JT_ADDR
5717      *  when we need to add a dummy block
5718      *  to record the end of a try or handler region.
5719      */
5720     BYTE* jumpTarget = new (this, CMK_Unknown) BYTE[info.compILCodeSize + 1];
5721     memset(jumpTarget, JT_NONE, info.compILCodeSize + 1);
5722     noway_assert(JT_NONE == 0);
5723
5724     /* Walk the instrs to find all jump targets */
5725
5726     fgFindJumpTargets(info.compCode, info.compILCodeSize, jumpTarget);
5727     if (compDonotInline())
5728     {
5729         return;
5730     }
5731
5732     unsigned XTnum;
5733
5734     /* Are there any exception handlers? */
5735
5736     if (info.compXcptnsCount > 0)
5737     {
5738         noway_assert(!compIsForInlining());
5739
5740         /* Check and mark all the exception handlers */
5741
5742         for (XTnum = 0; XTnum < info.compXcptnsCount; XTnum++)
5743         {
5744             DWORD             tmpOffset;
5745             CORINFO_EH_CLAUSE clause;
5746             info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
5747             noway_assert(clause.HandlerLength != (unsigned)-1);
5748
5749             if (clause.TryLength <= 0)
5750             {
5751                 BADCODE("try block length <=0");
5752             }
5753
5754             /* Mark the 'try' block extent and the handler itself */
5755
5756             if (clause.TryOffset > info.compILCodeSize)
5757             {
5758                 BADCODE("try offset is > codesize");
5759             }
5760             if (jumpTarget[clause.TryOffset] == JT_NONE)
5761             {
5762                 jumpTarget[clause.TryOffset] = JT_ADDR;
5763             }
5764
5765             tmpOffset = clause.TryOffset + clause.TryLength;
5766             if (tmpOffset > info.compILCodeSize)
5767             {
5768                 BADCODE("try end is > codesize");
5769             }
5770             if (jumpTarget[tmpOffset] == JT_NONE)
5771             {
5772                 jumpTarget[tmpOffset] = JT_ADDR;
5773             }
5774
5775             if (clause.HandlerOffset > info.compILCodeSize)
5776             {
5777                 BADCODE("handler offset > codesize");
5778             }
5779             if (jumpTarget[clause.HandlerOffset] == JT_NONE)
5780             {
5781                 jumpTarget[clause.HandlerOffset] = JT_ADDR;
5782             }
5783
5784             tmpOffset = clause.HandlerOffset + clause.HandlerLength;
5785             if (tmpOffset > info.compILCodeSize)
5786             {
5787                 BADCODE("handler end > codesize");
5788             }
5789             if (jumpTarget[tmpOffset] == JT_NONE)
5790             {
5791                 jumpTarget[tmpOffset] = JT_ADDR;
5792             }
5793
5794             if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5795             {
5796                 if (clause.FilterOffset > info.compILCodeSize)
5797                 {
5798                     BADCODE("filter offset > codesize");
5799                 }
5800                 if (jumpTarget[clause.FilterOffset] == JT_NONE)
5801                 {
5802                     jumpTarget[clause.FilterOffset] = JT_ADDR;
5803                 }
5804             }
5805         }
5806     }
5807
5808 #ifdef DEBUG
5809     if (verbose)
5810     {
5811         bool anyJumpTargets = false;
5812         printf("Jump targets:\n");
5813         for (unsigned i = 0; i < info.compILCodeSize + 1; i++)
5814         {
5815             if (jumpTarget[i] == JT_NONE)
5816             {
5817                 continue;
5818             }
5819
5820             anyJumpTargets = true;
5821             printf("  IL_%04x", i);
5822
5823             if (jumpTarget[i] & JT_ADDR)
5824             {
5825                 printf(" addr");
5826             }
5827             if (jumpTarget[i] & JT_MULTI)
5828             {
5829                 printf(" multi");
5830             }
5831             printf("\n");
5832         }
5833         if (!anyJumpTargets)
5834         {
5835             printf("  none\n");
5836         }
5837     }
5838 #endif // DEBUG
5839
5840     /* Now create the basic blocks */
5841
5842     unsigned retBlocks = fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget);
5843
5844     if (compIsForInlining())
5845     {
5846
5847 #ifdef DEBUG
5848         // If fgFindJumpTargets marked the call as "no return" there
5849         // really should be no BBJ_RETURN blocks in the method.
5850         //
5851         // Note LegacyPolicy does not mark calls as no return, so if
5852         // it's active, skip the check.
5853         if (!compInlineResult->UsesLegacyPolicy())
5854         {
5855             bool markedNoReturn = (impInlineInfo->iciCall->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN) != 0;
5856             assert((markedNoReturn && (retBlocks == 0)) || (!markedNoReturn && (retBlocks >= 1)));
5857         }
5858 #endif // DEBUG
5859
5860         if (compInlineResult->IsFailure())
5861         {
5862             return;
5863         }
5864
5865         noway_assert(info.compXcptnsCount == 0);
5866         compHndBBtab = impInlineInfo->InlinerCompiler->compHndBBtab;
5867         compHndBBtabAllocCount =
5868             impInlineInfo->InlinerCompiler->compHndBBtabAllocCount; // we probably only use the table, not add to it.
5869         compHndBBtabCount    = impInlineInfo->InlinerCompiler->compHndBBtabCount;
5870         info.compXcptnsCount = impInlineInfo->InlinerCompiler->info.compXcptnsCount;
5871
5872         // Use a spill temp for the return value if there are multiple return blocks,
5873         // or if the inlinee has GC ref locals.
5874         if ((info.compRetNativeType != TYP_VOID) && ((retBlocks > 1) || impInlineInfo->HasGcRefLocals()))
5875         {
5876             // The lifetime of this var might expand multiple BBs. So it is a long lifetime compiler temp.
5877             lvaInlineeReturnSpillTemp                  = lvaGrabTemp(false DEBUGARG("Inline return value spill temp"));
5878             lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType;
5879         }
5880
5881         return;
5882     }
5883
5884     /* Mark all blocks within 'try' blocks as such */
5885
5886     if (info.compXcptnsCount == 0)
5887     {
5888         return;
5889     }
5890
5891     if (info.compXcptnsCount > MAX_XCPTN_INDEX)
5892     {
5893         IMPL_LIMITATION("too many exception clauses");
5894     }
5895
5896     /* Allocate the exception handler table */
5897
5898     fgAllocEHTable();
5899
5900     /* Assume we don't need to sort the EH table (such that nested try/catch
5901      * appear before their try or handler parent). The EH verifier will notice
5902      * when we do need to sort it.
5903      */
5904
5905     fgNeedToSortEHTable = false;
5906
5907     verInitEHTree(info.compXcptnsCount);
5908     EHNodeDsc* initRoot = ehnNext; // remember the original root since
5909                                    // it may get modified during insertion
5910
5911     // Annotate BBs with exception handling information required for generating correct eh code
5912     // as well as checking for correct IL
5913
5914     EHblkDsc* HBtab;
5915
5916     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
5917     {
5918         CORINFO_EH_CLAUSE clause;
5919         info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
5920         noway_assert(clause.HandlerLength != (unsigned)-1); // @DEPRECATED
5921
5922 #ifdef DEBUG
5923         if (verbose)
5924         {
5925             dispIncomingEHClause(XTnum, clause);
5926         }
5927 #endif // DEBUG
5928
5929         IL_OFFSET tryBegOff    = clause.TryOffset;
5930         IL_OFFSET tryEndOff    = tryBegOff + clause.TryLength;
5931         IL_OFFSET filterBegOff = 0;
5932         IL_OFFSET hndBegOff    = clause.HandlerOffset;
5933         IL_OFFSET hndEndOff    = hndBegOff + clause.HandlerLength;
5934
5935         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5936         {
5937             filterBegOff = clause.FilterOffset;
5938         }
5939
5940         if (tryEndOff > info.compILCodeSize)
5941         {
5942             BADCODE3("end of try block beyond end of method for try", " at offset %04X", tryBegOff);
5943         }
5944         if (hndEndOff > info.compILCodeSize)
5945         {
5946             BADCODE3("end of hnd block beyond end of method for try", " at offset %04X", tryBegOff);
5947         }
5948
5949         HBtab->ebdTryBegOffset    = tryBegOff;
5950         HBtab->ebdTryEndOffset    = tryEndOff;
5951         HBtab->ebdFilterBegOffset = filterBegOff;
5952         HBtab->ebdHndBegOffset    = hndBegOff;
5953         HBtab->ebdHndEndOffset    = hndEndOff;
5954
5955         /* Convert the various addresses to basic blocks */
5956
5957         BasicBlock* tryBegBB = fgLookupBB(tryBegOff);
5958         BasicBlock* tryEndBB =
5959             fgLookupBB(tryEndOff); // note: this can be NULL if the try region is at the end of the function
5960         BasicBlock* hndBegBB = fgLookupBB(hndBegOff);
5961         BasicBlock* hndEndBB = nullptr;
5962         BasicBlock* filtBB   = nullptr;
5963         BasicBlock* block;
5964
5965         //
5966         // Assert that the try/hnd beginning blocks are set up correctly
5967         //
5968         if (tryBegBB == nullptr)
5969         {
5970             BADCODE("Try Clause is invalid");
5971         }
5972
5973         if (hndBegBB == nullptr)
5974         {
5975             BADCODE("Handler Clause is invalid");
5976         }
5977
5978         tryBegBB->bbFlags |= BBF_HAS_LABEL;
5979         hndBegBB->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
5980
5981 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
5982         // This will change the block weight from 0 to 1
5983         // and clear the rarely run flag
5984         hndBegBB->makeBlockHot();
5985 #else
5986         hndBegBB->bbSetRunRarely();   // handler entry points are rarely executed
5987 #endif
5988
5989         if (hndEndOff < info.compILCodeSize)
5990         {
5991             hndEndBB = fgLookupBB(hndEndOff);
5992         }
5993
5994         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5995         {
5996             filtBB = HBtab->ebdFilter = fgLookupBB(clause.FilterOffset);
5997
5998             filtBB->bbCatchTyp = BBCT_FILTER;
5999             filtBB->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
6000
6001             hndBegBB->bbCatchTyp = BBCT_FILTER_HANDLER;
6002
6003 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
6004             // This will change the block weight from 0 to 1
6005             // and clear the rarely run flag
6006             filtBB->makeBlockHot();
6007 #else
6008             filtBB->bbSetRunRarely(); // filter entry points are rarely executed
6009 #endif
6010
6011             // Mark all BBs that belong to the filter with the XTnum of the corresponding handler
6012             for (block = filtBB; /**/; block = block->bbNext)
6013             {
6014                 if (block == nullptr)
6015                 {
6016                     BADCODE3("Missing endfilter for filter", " at offset %04X", filtBB->bbCodeOffs);
6017                     return;
6018                 }
6019
6020                 // Still inside the filter
6021                 block->setHndIndex(XTnum);
6022
6023                 if (block->bbJumpKind == BBJ_EHFILTERRET)
6024                 {
6025                     // Mark catch handler as successor.
6026                     block->bbJumpDest = hndBegBB;
6027                     assert(block->bbJumpDest->bbCatchTyp == BBCT_FILTER_HANDLER);
6028                     break;
6029                 }
6030             }
6031
6032             if (!block->bbNext || block->bbNext != hndBegBB)
6033             {
6034                 BADCODE3("Filter does not immediately precede handler for filter", " at offset %04X",
6035                          filtBB->bbCodeOffs);
6036             }
6037         }
6038         else
6039         {
6040             HBtab->ebdTyp = clause.ClassToken;
6041
6042             /* Set bbCatchTyp as appropriate */
6043
6044             if (clause.Flags & CORINFO_EH_CLAUSE_FINALLY)
6045             {
6046                 hndBegBB->bbCatchTyp = BBCT_FINALLY;
6047             }
6048             else
6049             {
6050                 if (clause.Flags & CORINFO_EH_CLAUSE_FAULT)
6051                 {
6052                     hndBegBB->bbCatchTyp = BBCT_FAULT;
6053                 }
6054                 else
6055                 {
6056                     hndBegBB->bbCatchTyp = clause.ClassToken;
6057
6058                     // These values should be non-zero value that will
6059                     // not collide with real tokens for bbCatchTyp
6060                     if (clause.ClassToken == 0)
6061                     {
6062                         BADCODE("Exception catch type is Null");
6063                     }
6064
6065                     noway_assert(clause.ClassToken != BBCT_FAULT);
6066                     noway_assert(clause.ClassToken != BBCT_FINALLY);
6067                     noway_assert(clause.ClassToken != BBCT_FILTER);
6068                     noway_assert(clause.ClassToken != BBCT_FILTER_HANDLER);
6069                 }
6070             }
6071         }
6072
6073         /* Mark the initial block and last blocks in the 'try' region */
6074
6075         tryBegBB->bbFlags |= BBF_TRY_BEG | BBF_HAS_LABEL;
6076
6077         /*  Prevent future optimizations of removing the first block   */
6078         /*  of a TRY block and the first block of an exception handler */
6079
6080         tryBegBB->bbFlags |= BBF_DONT_REMOVE;
6081         hndBegBB->bbFlags |= BBF_DONT_REMOVE;
6082         hndBegBB->bbRefs++; // The first block of a handler gets an extra, "artificial" reference count.
6083
6084         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
6085         {
6086             filtBB->bbFlags |= BBF_DONT_REMOVE;
6087             filtBB->bbRefs++; // The first block of a filter gets an extra, "artificial" reference count.
6088         }
6089
6090         tryBegBB->bbFlags |= BBF_DONT_REMOVE;
6091         hndBegBB->bbFlags |= BBF_DONT_REMOVE;
6092
6093         //
6094         // Store the info to the table of EH block handlers
6095         //
6096
6097         HBtab->ebdHandlerType = ToEHHandlerType(clause.Flags);
6098
6099         HBtab->ebdTryBeg  = tryBegBB;
6100         HBtab->ebdTryLast = (tryEndBB == nullptr) ? fgLastBB : tryEndBB->bbPrev;
6101
6102         HBtab->ebdHndBeg  = hndBegBB;
6103         HBtab->ebdHndLast = (hndEndBB == nullptr) ? fgLastBB : hndEndBB->bbPrev;
6104
6105         //
6106         // Assert that all of our try/hnd blocks are setup correctly.
6107         //
6108         if (HBtab->ebdTryLast == nullptr)
6109         {
6110             BADCODE("Try Clause is invalid");
6111         }
6112
6113         if (HBtab->ebdHndLast == nullptr)
6114         {
6115             BADCODE("Handler Clause is invalid");
6116         }
6117
6118         //
6119         // Verify that it's legal
6120         //
6121
6122         verInsertEhNode(&clause, HBtab);
6123
6124     } // end foreach handler table entry
6125
6126     fgSortEHTable();
6127
6128     // Next, set things related to nesting that depend on the sorting being complete.
6129
6130     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
6131     {
6132         /* Mark all blocks in the finally/fault or catch clause */
6133
6134         BasicBlock* tryBegBB = HBtab->ebdTryBeg;
6135         BasicBlock* hndBegBB = HBtab->ebdHndBeg;
6136
6137         IL_OFFSET tryBegOff = HBtab->ebdTryBegOffset;
6138         IL_OFFSET tryEndOff = HBtab->ebdTryEndOffset;
6139
6140         IL_OFFSET hndBegOff = HBtab->ebdHndBegOffset;
6141         IL_OFFSET hndEndOff = HBtab->ebdHndEndOffset;
6142
6143         BasicBlock* block;
6144
6145         for (block = hndBegBB; block && (block->bbCodeOffs < hndEndOff); block = block->bbNext)
6146         {
6147             if (!block->hasHndIndex())
6148             {
6149                 block->setHndIndex(XTnum);
6150             }
6151
6152             // All blocks in a catch handler or filter are rarely run, except the entry
6153             if ((block != hndBegBB) && (hndBegBB->bbCatchTyp != BBCT_FINALLY))
6154             {
6155                 block->bbSetRunRarely();
6156             }
6157         }
6158
6159         /* Mark all blocks within the covered range of the try */
6160
6161         for (block = tryBegBB; block && (block->bbCodeOffs < tryEndOff); block = block->bbNext)
6162         {
6163             /* Mark this BB as belonging to a 'try' block */
6164
6165             if (!block->hasTryIndex())
6166             {
6167                 block->setTryIndex(XTnum);
6168             }
6169
6170 #ifdef DEBUG
6171             /* Note: the BB can't span the 'try' block */
6172
6173             if (!(block->bbFlags & BBF_INTERNAL))
6174             {
6175                 noway_assert(tryBegOff <= block->bbCodeOffs);
6176                 noway_assert(tryEndOff >= block->bbCodeOffsEnd || tryEndOff == tryBegOff);
6177             }
6178 #endif
6179         }
6180
6181 /*  Init ebdHandlerNestingLevel of current clause, and bump up value for all
6182  *  enclosed clauses (which have to be before it in the table).
6183  *  Innermost try-finally blocks must precede outermost
6184  *  try-finally blocks.
6185  */
6186
6187 #if !FEATURE_EH_FUNCLETS
6188         HBtab->ebdHandlerNestingLevel = 0;
6189 #endif // !FEATURE_EH_FUNCLETS
6190
6191         HBtab->ebdEnclosingTryIndex = EHblkDsc::NO_ENCLOSING_INDEX;
6192         HBtab->ebdEnclosingHndIndex = EHblkDsc::NO_ENCLOSING_INDEX;
6193
6194         noway_assert(XTnum < compHndBBtabCount);
6195         noway_assert(XTnum == ehGetIndex(HBtab));
6196
6197         for (EHblkDsc* xtab = compHndBBtab; xtab < HBtab; xtab++)
6198         {
6199 #if !FEATURE_EH_FUNCLETS
6200             if (jitIsBetween(xtab->ebdHndBegOffs(), hndBegOff, hndEndOff))
6201             {
6202                 xtab->ebdHandlerNestingLevel++;
6203             }
6204 #endif // !FEATURE_EH_FUNCLETS
6205
6206             /* If we haven't recorded an enclosing try index for xtab then see
6207              *  if this EH region should be recorded.  We check if the
6208              *  first offset in the xtab lies within our region.  If so,
6209              *  the last offset also must lie within the region, due to
6210              *  nesting rules. verInsertEhNode(), below, will check for proper nesting.
6211              */
6212             if (xtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
6213             {
6214                 bool begBetween = jitIsBetween(xtab->ebdTryBegOffs(), tryBegOff, tryEndOff);
6215                 if (begBetween)
6216                 {
6217                     // Record the enclosing scope link
6218                     xtab->ebdEnclosingTryIndex = (unsigned short)XTnum;
6219                 }
6220             }
6221
6222             /* Do the same for the enclosing handler index.
6223              */
6224             if (xtab->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX)
6225             {
6226                 bool begBetween = jitIsBetween(xtab->ebdTryBegOffs(), hndBegOff, hndEndOff);
6227                 if (begBetween)
6228                 {
6229                     // Record the enclosing scope link
6230                     xtab->ebdEnclosingHndIndex = (unsigned short)XTnum;
6231                 }
6232             }
6233         }
6234
6235     } // end foreach handler table entry
6236
6237 #if !FEATURE_EH_FUNCLETS
6238
6239     EHblkDsc* HBtabEnd;
6240     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
6241     {
6242         if (ehMaxHndNestingCount <= HBtab->ebdHandlerNestingLevel)
6243             ehMaxHndNestingCount = HBtab->ebdHandlerNestingLevel + 1;
6244     }
6245
6246 #endif // !FEATURE_EH_FUNCLETS
6247
6248 #ifndef DEBUG
6249     if (tiVerificationNeeded)
6250 #endif
6251     {
6252         // always run these checks for a debug build
6253         verCheckNestingLevel(initRoot);
6254     }
6255
6256 #ifndef DEBUG
6257     // fgNormalizeEH assumes that this test has been passed.  And Ssa assumes that fgNormalizeEHTable
6258     // has been run.  So do this unless we're in minOpts mode (and always in debug).
6259     if (tiVerificationNeeded || !opts.MinOpts())
6260 #endif
6261     {
6262         fgCheckBasicBlockControlFlow();
6263     }
6264
6265 #ifdef DEBUG
6266     if (verbose)
6267     {
6268         JITDUMP("*************** After fgFindBasicBlocks() has created the EH table\n");
6269         fgDispHandlerTab();
6270     }
6271
6272     // We can't verify the handler table until all the IL legality checks have been done (above), since bad IL
6273     // (such as illegal nesting of regions) will trigger asserts here.
6274     fgVerifyHandlerTab();
6275 #endif
6276
6277     fgNormalizeEH();
6278 }
6279
6280 /*****************************************************************************
6281  * Check control flow constraints for well formed IL. Bail if any of the constraints
6282  * are violated.
6283  */
6284
6285 void Compiler::fgCheckBasicBlockControlFlow()
6286 {
6287     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6288
6289     EHblkDsc* HBtab;
6290
6291     for (BasicBlock* blk = fgFirstBB; blk; blk = blk->bbNext)
6292     {
6293         if (blk->bbFlags & BBF_INTERNAL)
6294         {
6295             continue;
6296         }
6297
6298         switch (blk->bbJumpKind)
6299         {
6300             case BBJ_NONE: // block flows into the next one (no jump)
6301
6302                 fgControlFlowPermitted(blk, blk->bbNext);
6303
6304                 break;
6305
6306             case BBJ_ALWAYS: // block does unconditional jump to target
6307
6308                 fgControlFlowPermitted(blk, blk->bbJumpDest);
6309
6310                 break;
6311
6312             case BBJ_COND: // block conditionally jumps to the target
6313
6314                 fgControlFlowPermitted(blk, blk->bbNext);
6315
6316                 fgControlFlowPermitted(blk, blk->bbJumpDest);
6317
6318                 break;
6319
6320             case BBJ_RETURN: // block ends with 'ret'
6321
6322                 if (blk->hasTryIndex() || blk->hasHndIndex())
6323                 {
6324                     BADCODE3("Return from a protected block", ". Before offset %04X", blk->bbCodeOffsEnd);
6325                 }
6326                 break;
6327
6328             case BBJ_EHFINALLYRET:
6329             case BBJ_EHFILTERRET:
6330
6331                 if (!blk->hasHndIndex()) // must be part of a handler
6332                 {
6333                     BADCODE3("Missing handler", ". Before offset %04X", blk->bbCodeOffsEnd);
6334                 }
6335
6336                 HBtab = ehGetDsc(blk->getHndIndex());
6337
6338                 // Endfilter allowed only in a filter block
6339                 if (blk->bbJumpKind == BBJ_EHFILTERRET)
6340                 {
6341                     if (!HBtab->HasFilter())
6342                     {
6343                         BADCODE("Unexpected endfilter");
6344                     }
6345                 }
6346                 // endfinally allowed only in a finally/fault block
6347                 else if (!HBtab->HasFinallyOrFaultHandler())
6348                 {
6349                     BADCODE("Unexpected endfinally");
6350                 }
6351
6352                 // The handler block should be the innermost block
6353                 // Exception blocks are listed, innermost first.
6354                 if (blk->hasTryIndex() && (blk->getTryIndex() < blk->getHndIndex()))
6355                 {
6356                     BADCODE("endfinally / endfilter in nested try block");
6357                 }
6358
6359                 break;
6360
6361             case BBJ_THROW: // block ends with 'throw'
6362                 /* throw is permitted from every BB, so nothing to check */
6363                 /* importer makes sure that rethrow is done from a catch */
6364                 break;
6365
6366             case BBJ_LEAVE: // block always jumps to the target, maybe out of guarded
6367                             // region. Used temporarily until importing
6368                 fgControlFlowPermitted(blk, blk->bbJumpDest, TRUE);
6369
6370                 break;
6371
6372             case BBJ_SWITCH: // block ends with a switch statement
6373
6374                 BBswtDesc* swtDesc;
6375                 swtDesc = blk->bbJumpSwt;
6376
6377                 assert(swtDesc);
6378
6379                 unsigned i;
6380                 for (i = 0; i < swtDesc->bbsCount; i++)
6381                 {
6382                     fgControlFlowPermitted(blk, swtDesc->bbsDstTab[i]);
6383                 }
6384
6385                 break;
6386
6387             case BBJ_EHCATCHRET:  // block ends with a leave out of a catch (only #if FEATURE_EH_FUNCLETS)
6388             case BBJ_CALLFINALLY: // block always calls the target finally
6389             default:
6390                 noway_assert(!"Unexpected bbJumpKind"); // these blocks don't get created until importing
6391                 break;
6392         }
6393     }
6394 }
6395
6396 /****************************************************************************
6397  * Check that the leave from the block is legal.
6398  * Consider removing this check here if we  can do it cheaply during importing
6399  */
6400
6401 void Compiler::fgControlFlowPermitted(BasicBlock* blkSrc, BasicBlock* blkDest, BOOL isLeave)
6402 {
6403     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6404
6405     unsigned srcHndBeg, destHndBeg;
6406     unsigned srcHndEnd, destHndEnd;
6407     bool     srcInFilter, destInFilter;
6408     bool     srcInCatch = false;
6409
6410     EHblkDsc* srcHndTab;
6411
6412     srcHndTab = ehInitHndRange(blkSrc, &srcHndBeg, &srcHndEnd, &srcInFilter);
6413     ehInitHndRange(blkDest, &destHndBeg, &destHndEnd, &destInFilter);
6414
6415     /* Impose the rules for leaving or jumping from handler blocks */
6416
6417     if (blkSrc->hasHndIndex())
6418     {
6419         srcInCatch = srcHndTab->HasCatchHandler() && srcHndTab->InHndRegionILRange(blkSrc);
6420
6421         /* Are we jumping within the same handler index? */
6422         if (BasicBlock::sameHndRegion(blkSrc, blkDest))
6423         {
6424             /* Do we have a filter clause? */
6425             if (srcHndTab->HasFilter())
6426             {
6427                 /* filters and catch handlers share same eh index  */
6428                 /* we need to check for control flow between them. */
6429                 if (srcInFilter != destInFilter)
6430                 {
6431                     if (!jitIsBetween(blkDest->bbCodeOffs, srcHndBeg, srcHndEnd))
6432                     {
6433                         BADCODE3("Illegal control flow between filter and handler", ". Before offset %04X",
6434                                  blkSrc->bbCodeOffsEnd);
6435                     }
6436                 }
6437             }
6438         }
6439         else
6440         {
6441             /* The handler indexes of blkSrc and blkDest are different */
6442             if (isLeave)
6443             {
6444                 /* Any leave instructions must not enter the dest handler from outside*/
6445                 if (!jitIsBetween(srcHndBeg, destHndBeg, destHndEnd))
6446                 {
6447                     BADCODE3("Illegal use of leave to enter handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6448                 }
6449             }
6450             else
6451             {
6452                 /* We must use a leave to exit a handler */
6453                 BADCODE3("Illegal control flow out of a handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6454             }
6455
6456             /* Do we have a filter clause? */
6457             if (srcHndTab->HasFilter())
6458             {
6459                 /* It is ok to leave from the handler block of a filter, */
6460                 /* but not from the filter block of a filter             */
6461                 if (srcInFilter != destInFilter)
6462                 {
6463                     BADCODE3("Illegal to leave a filter handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6464                 }
6465             }
6466
6467             /* We should never leave a finally handler */
6468             if (srcHndTab->HasFinallyHandler())
6469             {
6470                 BADCODE3("Illegal to leave a finally handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6471             }
6472
6473             /* We should never leave a fault handler */
6474             if (srcHndTab->HasFaultHandler())
6475             {
6476                 BADCODE3("Illegal to leave a fault handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6477             }
6478         }
6479     }
6480     else if (blkDest->hasHndIndex())
6481     {
6482         /* blkSrc was not inside a handler, but blkDst is inside a handler */
6483         BADCODE3("Illegal control flow into a handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6484     }
6485
6486     /* Are we jumping from a catch handler into the corresponding try? */
6487     /* VB uses this for "on error goto "                               */
6488
6489     if (isLeave && srcInCatch)
6490     {
6491         // inspect all handlers containing the jump source
6492
6493         bool      bValidJumpToTry   = false; // are we jumping in a valid way from a catch to the corresponding try?
6494         bool      bCatchHandlerOnly = true;  // false if we are jumping out of a non-catch handler
6495         EHblkDsc* ehTableEnd;
6496         EHblkDsc* ehDsc;
6497
6498         for (ehDsc = compHndBBtab, ehTableEnd = compHndBBtab + compHndBBtabCount;
6499              bCatchHandlerOnly && ehDsc < ehTableEnd; ehDsc++)
6500         {
6501             if (ehDsc->InHndRegionILRange(blkSrc))
6502             {
6503                 if (ehDsc->HasCatchHandler())
6504                 {
6505                     if (ehDsc->InTryRegionILRange(blkDest))
6506                     {
6507                         // If we already considered the jump for a different try/catch,
6508                         // we would have two overlapping try regions with two overlapping catch
6509                         // regions, which is illegal.
6510                         noway_assert(!bValidJumpToTry);
6511
6512                         // Allowed if it is the first instruction of an inner try
6513                         // (and all trys in between)
6514                         //
6515                         // try {
6516                         //  ..
6517                         // _tryAgain:
6518                         //  ..
6519                         //      try {
6520                         //      _tryNestedInner:
6521                         //        ..
6522                         //          try {
6523                         //          _tryNestedIllegal:
6524                         //            ..
6525                         //          } catch {
6526                         //            ..
6527                         //          }
6528                         //        ..
6529                         //      } catch {
6530                         //        ..
6531                         //      }
6532                         //  ..
6533                         // } catch {
6534                         //  ..
6535                         //  leave _tryAgain         // Allowed
6536                         //  ..
6537                         //  leave _tryNestedInner   // Allowed
6538                         //  ..
6539                         //  leave _tryNestedIllegal // Not Allowed
6540                         //  ..
6541                         // }
6542                         //
6543                         // Note: The leave is allowed also from catches nested inside the catch shown above.
6544
6545                         /* The common case where leave is to the corresponding try */
6546                         if (ehDsc->ebdIsSameTry(this, blkDest->getTryIndex()) ||
6547                             /* Also allowed is a leave to the start of a try which starts in the handler's try */
6548                             fgFlowToFirstBlockOfInnerTry(ehDsc->ebdTryBeg, blkDest, false))
6549                         {
6550                             bValidJumpToTry = true;
6551                         }
6552                     }
6553                 }
6554                 else
6555                 {
6556                     // We are jumping from a handler which is not a catch handler.
6557
6558                     // If it's a handler, but not a catch handler, it must be either a finally or fault
6559                     if (!ehDsc->HasFinallyOrFaultHandler())
6560                     {
6561                         BADCODE3("Handlers must be catch, finally, or fault", ". Before offset %04X",
6562                                  blkSrc->bbCodeOffsEnd);
6563                     }
6564
6565                     // Are we jumping out of this handler?
6566                     if (!ehDsc->InHndRegionILRange(blkDest))
6567                     {
6568                         bCatchHandlerOnly = false;
6569                     }
6570                 }
6571             }
6572             else if (ehDsc->InFilterRegionILRange(blkSrc))
6573             {
6574                 // Are we jumping out of a filter?
6575                 if (!ehDsc->InFilterRegionILRange(blkDest))
6576                 {
6577                     bCatchHandlerOnly = false;
6578                 }
6579             }
6580         }
6581
6582         if (bCatchHandlerOnly)
6583         {
6584             if (bValidJumpToTry)
6585             {
6586                 return;
6587             }
6588             else
6589             {
6590                 // FALL THROUGH
6591                 // This is either the case of a leave to outside the try/catch,
6592                 // or a leave to a try not nested in this try/catch.
6593                 // The first case is allowed, the second one will be checked
6594                 // later when we check the try block rules (it is illegal if we
6595                 // jump to the middle of the destination try).
6596             }
6597         }
6598         else
6599         {
6600             BADCODE3("illegal leave to exit a finally, fault or filter", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6601         }
6602     }
6603
6604     /* Check all the try block rules */
6605
6606     IL_OFFSET srcTryBeg;
6607     IL_OFFSET srcTryEnd;
6608     IL_OFFSET destTryBeg;
6609     IL_OFFSET destTryEnd;
6610
6611     ehInitTryRange(blkSrc, &srcTryBeg, &srcTryEnd);
6612     ehInitTryRange(blkDest, &destTryBeg, &destTryEnd);
6613
6614     /* Are we jumping between try indexes? */
6615     if (!BasicBlock::sameTryRegion(blkSrc, blkDest))
6616     {
6617         // Are we exiting from an inner to outer try?
6618         if (jitIsBetween(srcTryBeg, destTryBeg, destTryEnd) && jitIsBetween(srcTryEnd - 1, destTryBeg, destTryEnd))
6619         {
6620             if (!isLeave)
6621             {
6622                 BADCODE3("exit from try block without a leave", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6623             }
6624         }
6625         else if (jitIsBetween(destTryBeg, srcTryBeg, srcTryEnd))
6626         {
6627             // check that the dest Try is first instruction of an inner try
6628             if (!fgFlowToFirstBlockOfInnerTry(blkSrc, blkDest, false))
6629             {
6630                 BADCODE3("control flow into middle of try", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6631             }
6632         }
6633         else // there is no nesting relationship between src and dest
6634         {
6635             if (isLeave)
6636             {
6637                 // check that the dest Try is first instruction of an inner try sibling
6638                 if (!fgFlowToFirstBlockOfInnerTry(blkSrc, blkDest, true))
6639                 {
6640                     BADCODE3("illegal leave into middle of try", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6641                 }
6642             }
6643             else
6644             {
6645                 BADCODE3("illegal control flow in to/out of try block", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6646             }
6647         }
6648     }
6649 }
6650
6651 /*****************************************************************************
6652  *  Check that blkDest is the first block of an inner try or a sibling
6653  *    with no intervening trys in between
6654  */
6655
6656 bool Compiler::fgFlowToFirstBlockOfInnerTry(BasicBlock* blkSrc, BasicBlock* blkDest, bool sibling)
6657 {
6658     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6659
6660     noway_assert(blkDest->hasTryIndex());
6661
6662     unsigned XTnum     = blkDest->getTryIndex();
6663     unsigned lastXTnum = blkSrc->hasTryIndex() ? blkSrc->getTryIndex() : compHndBBtabCount;
6664     noway_assert(XTnum < compHndBBtabCount);
6665     noway_assert(lastXTnum <= compHndBBtabCount);
6666
6667     EHblkDsc* HBtab = ehGetDsc(XTnum);
6668
6669     // check that we are not jumping into middle of try
6670     if (HBtab->ebdTryBeg != blkDest)
6671     {
6672         return false;
6673     }
6674
6675     if (sibling)
6676     {
6677         noway_assert(!BasicBlock::sameTryRegion(blkSrc, blkDest));
6678
6679         // find the l.u.b of the two try ranges
6680         // Set lastXTnum to the l.u.b.
6681
6682         HBtab = ehGetDsc(lastXTnum);
6683
6684         for (lastXTnum++, HBtab++; lastXTnum < compHndBBtabCount; lastXTnum++, HBtab++)
6685         {
6686             if (jitIsBetweenInclusive(blkDest->bbNum, HBtab->ebdTryBeg->bbNum, HBtab->ebdTryLast->bbNum))
6687             {
6688                 break;
6689             }
6690         }
6691     }
6692
6693     // now check there are no intervening trys between dest and l.u.b
6694     // (it is ok to have intervening trys as long as they all start at
6695     //  the same code offset)
6696
6697     HBtab = ehGetDsc(XTnum);
6698
6699     for (XTnum++, HBtab++; XTnum < lastXTnum; XTnum++, HBtab++)
6700     {
6701         if (HBtab->ebdTryBeg->bbNum < blkDest->bbNum && blkDest->bbNum <= HBtab->ebdTryLast->bbNum)
6702         {
6703             return false;
6704         }
6705     }
6706
6707     return true;
6708 }
6709
6710 /*****************************************************************************
6711  *  Returns the handler nesting level of the block.
6712  *  *pFinallyNesting is set to the nesting level of the inner-most
6713  *  finally-protected try the block is in.
6714  */
6715
6716 unsigned Compiler::fgGetNestingLevel(BasicBlock* block, unsigned* pFinallyNesting)
6717 {
6718     unsigned  curNesting = 0;            // How many handlers is the block in
6719     unsigned  tryFin     = (unsigned)-1; // curNesting when we see innermost finally-protected try
6720     unsigned  XTnum;
6721     EHblkDsc* HBtab;
6722
6723     /* We find the block's handler nesting level by walking over the
6724        complete exception table and find enclosing clauses. */
6725
6726     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
6727     {
6728         noway_assert(HBtab->ebdTryBeg && HBtab->ebdHndBeg);
6729
6730         if (HBtab->HasFinallyHandler() && (tryFin == (unsigned)-1) && bbInTryRegions(XTnum, block))
6731         {
6732             tryFin = curNesting;
6733         }
6734         else if (bbInHandlerRegions(XTnum, block))
6735         {
6736             curNesting++;
6737         }
6738     }
6739
6740     if (tryFin == (unsigned)-1)
6741     {
6742         tryFin = curNesting;
6743     }
6744
6745     if (pFinallyNesting)
6746     {
6747         *pFinallyNesting = curNesting - tryFin;
6748     }
6749
6750     return curNesting;
6751 }
6752
6753 /*****************************************************************************
6754  *
6755  *  Import the basic blocks of the procedure.
6756  */
6757
6758 void Compiler::fgImport()
6759 {
6760     fgHasPostfix = false;
6761
6762     impImport(fgFirstBB);
6763
6764     if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION))
6765     {
6766         CorInfoMethodRuntimeFlags verFlag;
6767         verFlag = tiIsVerifiableCode ? CORINFO_FLG_VERIFIABLE : CORINFO_FLG_UNVERIFIABLE;
6768         info.compCompHnd->setMethodAttribs(info.compMethodHnd, verFlag);
6769     }
6770 }
6771
6772 /*****************************************************************************
6773  * This function returns true if tree is a node with a call
6774  * that unconditionally throws an exception
6775  */
6776
6777 bool Compiler::fgIsThrow(GenTreePtr tree)
6778 {
6779     if ((tree->gtOper != GT_CALL) || (tree->gtCall.gtCallType != CT_HELPER))
6780     {
6781         return false;
6782     }
6783
6784     // TODO-Throughput: Replace all these calls to eeFindHelper() with a table based lookup
6785
6786     if ((tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_OVERFLOW)) ||
6787         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_VERIFICATION)) ||
6788         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_RNGCHKFAIL)) ||
6789         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWDIVZERO)) ||
6790         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWNULLREF)) ||
6791         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW)) ||
6792         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_RETHROW)))
6793     {
6794         noway_assert(tree->gtFlags & GTF_CALL);
6795         noway_assert(tree->gtFlags & GTF_EXCEPT);
6796         return true;
6797     }
6798
6799     // TODO-CQ: there are a bunch of managed methods in [mscorlib]System.ThrowHelper
6800     // that would be nice to recognize.
6801
6802     return false;
6803 }
6804
6805 /*****************************************************************************
6806  * This function returns true for blocks that are in different hot-cold regions.
6807  * It returns false when the blocks are both in the same regions
6808  */
6809
6810 bool Compiler::fgInDifferentRegions(BasicBlock* blk1, BasicBlock* blk2)
6811 {
6812     noway_assert(blk1 != nullptr);
6813     noway_assert(blk2 != nullptr);
6814
6815     if (fgFirstColdBlock == nullptr)
6816     {
6817         return false;
6818     }
6819
6820     // If one block is Hot and the other is Cold then we are in different regions
6821     return ((blk1->bbFlags & BBF_COLD) != (blk2->bbFlags & BBF_COLD));
6822 }
6823
6824 bool Compiler::fgIsBlockCold(BasicBlock* blk)
6825 {
6826     noway_assert(blk != nullptr);
6827
6828     if (fgFirstColdBlock == nullptr)
6829     {
6830         return false;
6831     }
6832
6833     return ((blk->bbFlags & BBF_COLD) != 0);
6834 }
6835
6836 /*****************************************************************************
6837  * This function returns true if tree is a GT_COMMA node with a call
6838  * that unconditionally throws an exception
6839  */
6840
6841 bool Compiler::fgIsCommaThrow(GenTreePtr tree, bool forFolding /* = false */)
6842 {
6843     // Instead of always folding comma throws,
6844     // with stress enabled we only fold half the time
6845
6846     if (forFolding && compStressCompile(STRESS_FOLD, 50))
6847     {
6848         return false; /* Don't fold */
6849     }
6850
6851     /* Check for cast of a GT_COMMA with a throw overflow */
6852     if ((tree->gtOper == GT_COMMA) && (tree->gtFlags & GTF_CALL) && (tree->gtFlags & GTF_EXCEPT))
6853     {
6854         return (fgIsThrow(tree->gtOp.gtOp1));
6855     }
6856     return false;
6857 }
6858
6859 //------------------------------------------------------------------------
6860 // fgIsIndirOfAddrOfLocal: Determine whether "tree" is an indirection of a local.
6861 //
6862 // Arguments:
6863 //    tree - The tree node under consideration
6864 //
6865 // Return Value:
6866 //    If "tree" is a indirection (GT_IND, GT_BLK, or GT_OBJ) whose arg is an ADDR,
6867 //    whose arg in turn is a LCL_VAR, return that LCL_VAR node, else nullptr.
6868 //
6869 // static
6870 GenTreePtr Compiler::fgIsIndirOfAddrOfLocal(GenTreePtr tree)
6871 {
6872     GenTreePtr res = nullptr;
6873     if (tree->OperIsIndir())
6874     {
6875         GenTreePtr addr = tree->AsIndir()->Addr();
6876
6877         // Post rationalization, we can have Indir(Lea(..) trees. Therefore to recognize
6878         // Indir of addr of a local, skip over Lea in Indir(Lea(base, index, scale, offset))
6879         // to get to base variable.
6880         if (addr->OperGet() == GT_LEA)
6881         {
6882             // We use this method in backward dataflow after liveness computation - fgInterBlockLocalVarLiveness().
6883             // Therefore it is critical that we don't miss 'uses' of any local.  It may seem this method overlooks
6884             // if the index part of the LEA has indir( someAddrOperator ( lclVar ) ) to search for a use but it's
6885             // covered by the fact we're traversing the expression in execution order and we also visit the index.
6886             GenTreeAddrMode* lea  = addr->AsAddrMode();
6887             GenTreePtr       base = lea->Base();
6888
6889             if (base != nullptr)
6890             {
6891                 if (base->OperGet() == GT_IND)
6892                 {
6893                     return fgIsIndirOfAddrOfLocal(base);
6894                 }
6895                 // else use base as addr
6896                 addr = base;
6897             }
6898         }
6899
6900         if (addr->OperGet() == GT_ADDR)
6901         {
6902             GenTreePtr lclvar = addr->gtOp.gtOp1;
6903             if (lclvar->OperGet() == GT_LCL_VAR)
6904             {
6905                 res = lclvar;
6906             }
6907         }
6908         else if (addr->OperGet() == GT_LCL_VAR_ADDR)
6909         {
6910             res = addr;
6911         }
6912     }
6913     return res;
6914 }
6915
6916 GenTreeCall* Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfoHelpFunc helper)
6917 {
6918     bool     bNeedClassID = true;
6919     unsigned callFlags    = 0;
6920
6921     var_types type = TYP_BYREF;
6922
6923     // This is sort of ugly, as we have knowledge of what the helper is returning.
6924     // We need the return type.
6925     switch (helper)
6926     {
6927         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
6928             bNeedClassID = false;
6929             __fallthrough;
6930
6931         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
6932             callFlags |= GTF_CALL_HOISTABLE;
6933             __fallthrough;
6934
6935         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
6936         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
6937         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
6938         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
6939         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
6940             // type = TYP_BYREF;
6941             break;
6942
6943         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
6944             bNeedClassID = false;
6945             __fallthrough;
6946
6947         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
6948             callFlags |= GTF_CALL_HOISTABLE;
6949             __fallthrough;
6950
6951         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
6952         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
6953         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
6954         case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
6955             type = TYP_I_IMPL;
6956             break;
6957
6958         default:
6959             assert(!"unknown shared statics helper");
6960             break;
6961     }
6962
6963     GenTreeArgList* argList = nullptr;
6964
6965     GenTreePtr opModuleIDArg;
6966     GenTreePtr opClassIDArg;
6967
6968     // Get the class ID
6969     unsigned clsID;
6970     size_t   moduleID;
6971     void*    pclsID;
6972     void*    pmoduleID;
6973
6974     clsID = info.compCompHnd->getClassDomainID(cls, &pclsID);
6975
6976     moduleID = info.compCompHnd->getClassModuleIdForStatics(cls, nullptr, &pmoduleID);
6977
6978     if (!(callFlags & GTF_CALL_HOISTABLE))
6979     {
6980         if (info.compCompHnd->getClassAttribs(cls) & CORINFO_FLG_BEFOREFIELDINIT)
6981         {
6982             callFlags |= GTF_CALL_HOISTABLE;
6983         }
6984     }
6985
6986     if (pmoduleID)
6987     {
6988         opModuleIDArg = gtNewIconHandleNode((size_t)pmoduleID, GTF_ICON_CIDMID_HDL);
6989         opModuleIDArg = gtNewOperNode(GT_IND, TYP_I_IMPL, opModuleIDArg);
6990         opModuleIDArg->gtFlags |= GTF_IND_INVARIANT;
6991     }
6992     else
6993     {
6994         opModuleIDArg = gtNewIconNode((size_t)moduleID, TYP_I_IMPL);
6995     }
6996
6997     if (bNeedClassID)
6998     {
6999         if (pclsID)
7000         {
7001             opClassIDArg = gtNewIconHandleNode((size_t)pclsID, GTF_ICON_CIDMID_HDL);
7002             opClassIDArg = gtNewOperNode(GT_IND, TYP_INT, opClassIDArg);
7003             opClassIDArg->gtFlags |= GTF_IND_INVARIANT;
7004         }
7005         else
7006         {
7007             opClassIDArg = gtNewIconNode(clsID, TYP_INT);
7008         }
7009
7010         // call the helper to get the base
7011         argList = gtNewArgList(opModuleIDArg, opClassIDArg);
7012     }
7013     else
7014     {
7015         argList = gtNewArgList(opModuleIDArg);
7016     }
7017
7018     if (!s_helperCallProperties.NoThrow(helper))
7019     {
7020         callFlags |= GTF_EXCEPT;
7021     }
7022
7023     return gtNewHelperCallNode(helper, type, callFlags, argList);
7024 }
7025
7026 GenTreeCall* Compiler::fgGetSharedCCtor(CORINFO_CLASS_HANDLE cls)
7027 {
7028 #ifdef FEATURE_READYTORUN_COMPILER
7029     if (opts.IsReadyToRun())
7030     {
7031         CORINFO_RESOLVED_TOKEN resolvedToken;
7032         memset(&resolvedToken, 0, sizeof(resolvedToken));
7033         resolvedToken.hClass = cls;
7034
7035         return impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_STATIC_BASE, TYP_BYREF);
7036     }
7037 #endif
7038
7039     // Call the shared non gc static helper, as its the fastest
7040     return fgGetStaticsCCtorHelper(cls, info.compCompHnd->getSharedCCtorHelper(cls));
7041 }
7042
7043 //
7044 // Returns true unless the address expression could
7045 // never represent a NULL
7046 //
7047 bool Compiler::fgAddrCouldBeNull(GenTreePtr addr)
7048 {
7049     if (addr->gtOper == GT_ADDR)
7050     {
7051         if (addr->gtOp.gtOp1->gtOper == GT_CNS_INT)
7052         {
7053             GenTreePtr cns1Tree = addr->gtOp.gtOp1;
7054             if (!cns1Tree->IsIconHandle())
7055             {
7056                 // Indirection of some random constant...
7057                 // It is safest just to return true
7058                 return true;
7059             }
7060         }
7061         else if (addr->gtOp.gtOp1->OperIsLocalAddr())
7062         {
7063             return false;
7064         }
7065         return false; // we can't have a null address
7066     }
7067     else if (addr->gtOper == GT_ADD)
7068     {
7069         if (addr->gtOp.gtOp1->gtOper == GT_CNS_INT)
7070         {
7071             GenTreePtr cns1Tree = addr->gtOp.gtOp1;
7072             if (!cns1Tree->IsIconHandle())
7073             {
7074                 if (!fgIsBigOffset(cns1Tree->gtIntCon.gtIconVal))
7075                 {
7076                     // Op1 was an ordinary small constant
7077                     return fgAddrCouldBeNull(addr->gtOp.gtOp2);
7078                 }
7079             }
7080             else // Op1 was a handle represented as a constant
7081             {
7082                 // Is Op2 also a constant?
7083                 if (addr->gtOp.gtOp2->gtOper == GT_CNS_INT)
7084                 {
7085                     GenTreePtr cns2Tree = addr->gtOp.gtOp2;
7086                     // Is this an addition of a handle and constant
7087                     if (!cns2Tree->IsIconHandle())
7088                     {
7089                         if (!fgIsBigOffset(cns2Tree->gtIntCon.gtIconVal))
7090                         {
7091                             // Op2 was an ordinary small constant
7092                             return false; // we can't have a null address
7093                         }
7094                     }
7095                 }
7096             }
7097         }
7098         else
7099         {
7100             // Op1 is not a constant
7101             // What about Op2?
7102             if (addr->gtOp.gtOp2->gtOper == GT_CNS_INT)
7103             {
7104                 GenTreePtr cns2Tree = addr->gtOp.gtOp2;
7105                 // Is this an addition of a small constant
7106                 if (!cns2Tree->IsIconHandle())
7107                 {
7108                     if (!fgIsBigOffset(cns2Tree->gtIntCon.gtIconVal))
7109                     {
7110                         // Op2 was an ordinary small constant
7111                         return fgAddrCouldBeNull(addr->gtOp.gtOp1);
7112                     }
7113                 }
7114             }
7115         }
7116     }
7117     return true; // default result: addr could be null
7118 }
7119
7120 /*****************************************************************************
7121  *  Optimize the call to the delegate constructor.
7122  */
7123
7124 GenTreePtr Compiler::fgOptimizeDelegateConstructor(GenTreeCall*            call,
7125                                                    CORINFO_CONTEXT_HANDLE* ExactContextHnd,
7126                                                    CORINFO_RESOLVED_TOKEN* ldftnToken)
7127 {
7128     noway_assert(call->gtCallType == CT_USER_FUNC);
7129     CORINFO_METHOD_HANDLE methHnd = call->gtCallMethHnd;
7130     CORINFO_CLASS_HANDLE  clsHnd  = info.compCompHnd->getMethodClass(methHnd);
7131
7132     GenTreePtr targetMethod = call->gtCallArgs->Rest()->Current();
7133     noway_assert(targetMethod->TypeGet() == TYP_I_IMPL);
7134     genTreeOps            oper            = targetMethod->OperGet();
7135     CORINFO_METHOD_HANDLE targetMethodHnd = nullptr;
7136     GenTreePtr            qmarkNode       = nullptr;
7137     if (oper == GT_FTN_ADDR)
7138     {
7139         targetMethodHnd = targetMethod->gtFptrVal.gtFptrMethod;
7140     }
7141     else if (oper == GT_CALL && targetMethod->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_VIRTUAL_FUNC_PTR))
7142     {
7143         GenTreePtr handleNode = targetMethod->gtCall.gtCallArgs->Rest()->Rest()->Current();
7144
7145         if (handleNode->OperGet() == GT_CNS_INT)
7146         {
7147             // it's a ldvirtftn case, fetch the methodhandle off the helper for ldvirtftn. It's the 3rd arg
7148             targetMethodHnd = CORINFO_METHOD_HANDLE(handleNode->gtIntCon.gtCompileTimeHandle);
7149         }
7150         // Sometimes the argument to this is the result of a generic dictionary lookup, which shows
7151         // up as a GT_QMARK.
7152         else if (handleNode->OperGet() == GT_QMARK)
7153         {
7154             qmarkNode = handleNode;
7155         }
7156     }
7157     // Sometimes we don't call CORINFO_HELP_VIRTUAL_FUNC_PTR but instead just call
7158     // CORINFO_HELP_RUNTIMEHANDLE_METHOD directly.
7159     else if (oper == GT_QMARK)
7160     {
7161         qmarkNode = targetMethod;
7162     }
7163     if (qmarkNode)
7164     {
7165         noway_assert(qmarkNode->OperGet() == GT_QMARK);
7166         // The argument is actually a generic dictionary lookup.  For delegate creation it looks
7167         // like:
7168         // GT_QMARK
7169         //  GT_COLON
7170         //      op1 -> call
7171         //              Arg 1 -> token (has compile time handle)
7172         //      op2 -> lclvar
7173         //
7174         //
7175         // In this case I can find the token (which is a method handle) and that is the compile time
7176         // handle.
7177         noway_assert(qmarkNode->gtOp.gtOp2->OperGet() == GT_COLON);
7178         noway_assert(qmarkNode->gtOp.gtOp2->gtOp.gtOp1->OperGet() == GT_CALL);
7179         GenTreeCall* runtimeLookupCall = qmarkNode->gtOp.gtOp2->gtOp.gtOp1->AsCall();
7180
7181         // This could be any of CORINFO_HELP_RUNTIMEHANDLE_(METHOD|CLASS)(_LOG?)
7182         GenTreePtr tokenNode = runtimeLookupCall->gtCallArgs->gtOp.gtOp2->gtOp.gtOp1;
7183         noway_assert(tokenNode->OperGet() == GT_CNS_INT);
7184         targetMethodHnd = CORINFO_METHOD_HANDLE(tokenNode->gtIntCon.gtCompileTimeHandle);
7185     }
7186
7187 #ifdef FEATURE_READYTORUN_COMPILER
7188     if (opts.IsReadyToRun())
7189     {
7190         if (IsTargetAbi(CORINFO_CORERT_ABI))
7191         {
7192             if (ldftnToken != nullptr)
7193             {
7194                 GenTreePtr           thisPointer       = call->gtCallObjp;
7195                 GenTreePtr           targetObjPointers = call->gtCallArgs->Current();
7196                 GenTreeArgList*      helperArgs        = nullptr;
7197                 CORINFO_LOOKUP       pLookup;
7198                 CORINFO_CONST_LOOKUP entryPoint;
7199                 info.compCompHnd->getReadyToRunDelegateCtorHelper(ldftnToken, clsHnd, &pLookup);
7200                 if (!pLookup.lookupKind.needsRuntimeLookup)
7201                 {
7202                     helperArgs = gtNewArgList(thisPointer, targetObjPointers);
7203                     entryPoint = pLookup.constLookup;
7204                 }
7205                 else
7206                 {
7207                     assert(oper != GT_FTN_ADDR);
7208                     CORINFO_CONST_LOOKUP genericLookup;
7209                     info.compCompHnd->getReadyToRunHelper(ldftnToken, &pLookup.lookupKind,
7210                                                           CORINFO_HELP_READYTORUN_GENERIC_HANDLE, &genericLookup);
7211                     GenTreePtr ctxTree = getRuntimeContextTree(pLookup.lookupKind.runtimeLookupKind);
7212                     helperArgs         = gtNewArgList(thisPointer, targetObjPointers, ctxTree);
7213                     entryPoint         = genericLookup;
7214                 }
7215                 call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, GTF_EXCEPT, helperArgs);
7216                 call->setEntryPoint(entryPoint);
7217             }
7218         }
7219         // ReadyToRun has this optimization for a non-virtual function pointers only for now.
7220         else if (oper == GT_FTN_ADDR)
7221         {
7222             GenTreePtr      thisPointer       = call->gtCallObjp;
7223             GenTreePtr      targetObjPointers = call->gtCallArgs->Current();
7224             GenTreeArgList* helperArgs        = gtNewArgList(thisPointer, targetObjPointers);
7225
7226             call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, GTF_EXCEPT, helperArgs);
7227
7228             CORINFO_LOOKUP entryPoint;
7229             info.compCompHnd->getReadyToRunDelegateCtorHelper(ldftnToken, clsHnd, &entryPoint);
7230             assert(!entryPoint.lookupKind.needsRuntimeLookup);
7231             call->setEntryPoint(entryPoint.constLookup);
7232         }
7233     }
7234     else
7235 #endif
7236         if (targetMethodHnd != nullptr)
7237     {
7238         CORINFO_METHOD_HANDLE alternateCtor = nullptr;
7239         DelegateCtorArgs      ctorData;
7240         ctorData.pMethod = info.compMethodHnd;
7241         ctorData.pArg3   = nullptr;
7242         ctorData.pArg4   = nullptr;
7243         ctorData.pArg5   = nullptr;
7244
7245         alternateCtor = info.compCompHnd->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, &ctorData);
7246         if (alternateCtor != methHnd)
7247         {
7248             // we erase any inline info that may have been set for generics has it is not needed here,
7249             // and in fact it will pass the wrong info to the inliner code
7250             *ExactContextHnd = nullptr;
7251
7252             call->gtCallMethHnd = alternateCtor;
7253
7254             noway_assert(call->gtCallArgs->Rest()->Rest() == nullptr);
7255             GenTreeArgList* addArgs = nullptr;
7256             if (ctorData.pArg5)
7257             {
7258                 GenTreePtr arg5 = gtNewIconHandleNode(size_t(ctorData.pArg5), GTF_ICON_FTN_ADDR);
7259                 addArgs         = gtNewListNode(arg5, addArgs);
7260             }
7261             if (ctorData.pArg4)
7262             {
7263                 GenTreePtr arg4 = gtNewIconHandleNode(size_t(ctorData.pArg4), GTF_ICON_FTN_ADDR);
7264                 addArgs         = gtNewListNode(arg4, addArgs);
7265             }
7266             if (ctorData.pArg3)
7267             {
7268                 GenTreePtr arg3 = gtNewIconHandleNode(size_t(ctorData.pArg3), GTF_ICON_FTN_ADDR);
7269                 addArgs         = gtNewListNode(arg3, addArgs);
7270             }
7271             call->gtCallArgs->Rest()->Rest() = addArgs;
7272         }
7273     }
7274     return call;
7275 }
7276
7277 bool Compiler::fgCastNeeded(GenTreePtr tree, var_types toType)
7278 {
7279     //
7280     // If tree is a relop and we need an 4-byte integer
7281     //  then we never need to insert a cast
7282     //
7283     if ((tree->OperKind() & GTK_RELOP) && (genActualType(toType) == TYP_INT))
7284     {
7285         return false;
7286     }
7287
7288     var_types fromType;
7289
7290     //
7291     // Is the tree as GT_CAST or a GT_CALL ?
7292     //
7293     if (tree->OperGet() == GT_CAST)
7294     {
7295         fromType = tree->CastToType();
7296     }
7297     else if (tree->OperGet() == GT_CALL)
7298     {
7299         fromType = (var_types)tree->gtCall.gtReturnType;
7300     }
7301     else
7302     {
7303         fromType = tree->TypeGet();
7304     }
7305
7306     //
7307     // If both types are the same then an additional cast is not necessary
7308     //
7309     if (toType == fromType)
7310     {
7311         return false;
7312     }
7313     //
7314     // If the sign-ness of the two types are different then a cast is necessary
7315     //
7316     if (varTypeIsUnsigned(toType) != varTypeIsUnsigned(fromType))
7317     {
7318         return true;
7319     }
7320     //
7321     // If the from type is the same size or smaller then an additional cast is not necessary
7322     //
7323     if (genTypeSize(toType) >= genTypeSize(fromType))
7324     {
7325         return false;
7326     }
7327
7328     //
7329     // Looks like we will need the cast
7330     //
7331     return true;
7332 }
7333
7334 // If assigning to a local var, add a cast if the target is
7335 // marked as NormalizedOnStore. Returns true if any change was made
7336 GenTreePtr Compiler::fgDoNormalizeOnStore(GenTreePtr tree)
7337 {
7338     //
7339     // Only normalize the stores in the global morph phase
7340     //
7341     if (fgGlobalMorph)
7342     {
7343         noway_assert(tree->OperGet() == GT_ASG);
7344
7345         GenTreePtr op1 = tree->gtOp.gtOp1;
7346         GenTreePtr op2 = tree->gtOp.gtOp2;
7347
7348         if (op1->gtOper == GT_LCL_VAR && genActualType(op1->TypeGet()) == TYP_INT)
7349         {
7350             // Small-typed arguments and aliased locals are normalized on load.
7351             // Other small-typed locals are normalized on store.
7352             // If it is an assignment to one of the latter, insert the cast on RHS
7353             unsigned   varNum = op1->gtLclVarCommon.gtLclNum;
7354             LclVarDsc* varDsc = &lvaTable[varNum];
7355
7356             if (varDsc->lvNormalizeOnStore())
7357             {
7358                 noway_assert(op1->gtType <= TYP_INT);
7359                 op1->gtType = TYP_INT;
7360
7361                 if (fgCastNeeded(op2, varDsc->TypeGet()))
7362                 {
7363                     op2              = gtNewCastNode(TYP_INT, op2, varDsc->TypeGet());
7364                     tree->gtOp.gtOp2 = op2;
7365
7366                     // Propagate GTF_COLON_COND
7367                     op2->gtFlags |= (tree->gtFlags & GTF_COLON_COND);
7368                 }
7369             }
7370         }
7371     }
7372
7373     return tree;
7374 }
7375
7376 /*****************************************************************************
7377  *
7378  *  Mark whether the edge "srcBB -> dstBB" forms a loop that will always
7379  *  execute a call or not.
7380  */
7381
7382 inline void Compiler::fgLoopCallTest(BasicBlock* srcBB, BasicBlock* dstBB)
7383 {
7384     /* Bail if this is not a backward edge */
7385
7386     if (srcBB->bbNum < dstBB->bbNum)
7387     {
7388         return;
7389     }
7390
7391     /* Unless we already know that there is a loop without a call here ... */
7392
7393     if (!(dstBB->bbFlags & BBF_LOOP_CALL0))
7394     {
7395         /* Check whether there is a loop path that doesn't call */
7396
7397         if (optReachWithoutCall(dstBB, srcBB))
7398         {
7399             dstBB->bbFlags |= BBF_LOOP_CALL0;
7400             dstBB->bbFlags &= ~BBF_LOOP_CALL1;
7401         }
7402         else
7403         {
7404             dstBB->bbFlags |= BBF_LOOP_CALL1;
7405         }
7406     }
7407     // if this loop will always call, then we can omit the GC Poll
7408     if ((GCPOLL_NONE != opts.compGCPollType) && (dstBB->bbFlags & BBF_LOOP_CALL1))
7409     {
7410         srcBB->bbFlags &= ~BBF_NEEDS_GCPOLL;
7411     }
7412 }
7413
7414 /*****************************************************************************
7415  *
7416  *  Mark which loops are guaranteed to execute a call.
7417  */
7418
7419 void Compiler::fgLoopCallMark()
7420 {
7421     BasicBlock* block;
7422
7423     /* If we've already marked all the block, bail */
7424
7425     if (fgLoopCallMarked)
7426     {
7427         return;
7428     }
7429
7430     fgLoopCallMarked = true;
7431
7432     /* Walk the blocks, looking for backward edges */
7433
7434     for (block = fgFirstBB; block; block = block->bbNext)
7435     {
7436         switch (block->bbJumpKind)
7437         {
7438             case BBJ_COND:
7439             case BBJ_CALLFINALLY:
7440             case BBJ_ALWAYS:
7441             case BBJ_EHCATCHRET:
7442                 fgLoopCallTest(block, block->bbJumpDest);
7443                 break;
7444
7445             case BBJ_SWITCH:
7446
7447                 unsigned jumpCnt;
7448                 jumpCnt = block->bbJumpSwt->bbsCount;
7449                 BasicBlock** jumpPtr;
7450                 jumpPtr = block->bbJumpSwt->bbsDstTab;
7451
7452                 do
7453                 {
7454                     fgLoopCallTest(block, *jumpPtr);
7455                 } while (++jumpPtr, --jumpCnt);
7456
7457                 break;
7458
7459             default:
7460                 break;
7461         }
7462     }
7463 }
7464
7465 /*****************************************************************************
7466  *
7467  *  Note the fact that the given block is a loop header.
7468  */
7469
7470 inline void Compiler::fgMarkLoopHead(BasicBlock* block)
7471 {
7472 #ifdef DEBUG
7473     if (verbose)
7474     {
7475         printf("fgMarkLoopHead: Checking loop head block BB%02u: ", block->bbNum);
7476     }
7477 #endif
7478
7479     /* Have we decided to generate fully interruptible code already? */
7480
7481     if (genInterruptible)
7482     {
7483 #ifdef DEBUG
7484         if (verbose)
7485         {
7486             printf("method is already fully interruptible\n");
7487         }
7488 #endif
7489         return;
7490     }
7491
7492     /* Is the loop head block known to execute a method call? */
7493
7494     if (block->bbFlags & BBF_GC_SAFE_POINT)
7495     {
7496 #ifdef DEBUG
7497         if (verbose)
7498         {
7499             printf("this block will execute a call\n");
7500         }
7501 #endif
7502         // single block loops that contain GC safe points don't need polls.
7503         block->bbFlags &= ~BBF_NEEDS_GCPOLL;
7504         return;
7505     }
7506
7507     /* Are dominator sets available? */
7508
7509     if (fgDomsComputed)
7510     {
7511         /* Make sure that we know which loops will always execute calls */
7512
7513         if (!fgLoopCallMarked)
7514         {
7515             fgLoopCallMark();
7516         }
7517
7518         /* Will every trip through our loop execute a call? */
7519
7520         if (block->bbFlags & BBF_LOOP_CALL1)
7521         {
7522 #ifdef DEBUG
7523             if (verbose)
7524             {
7525                 printf("this block dominates a block that will execute a call\n");
7526             }
7527 #endif
7528             return;
7529         }
7530     }
7531
7532     /*
7533      *  We have to make this method fully interruptible since we can not
7534      *  ensure that this loop will execute a call every time it loops.
7535      *
7536      *  We'll also need to generate a full register map for this method.
7537      */
7538
7539     assert(!codeGen->isGCTypeFixed());
7540
7541     if (!compCanEncodePtrArgCntMax())
7542     {
7543 #ifdef DEBUG
7544         if (verbose)
7545         {
7546             printf("a callsite with more than 1023 pushed args exists\n");
7547         }
7548 #endif
7549         return;
7550     }
7551
7552 #ifdef DEBUG
7553     if (verbose)
7554     {
7555         printf("no guaranteed callsite exits, marking method as fully interruptible\n");
7556     }
7557 #endif
7558
7559     // only enable fully interruptible code for if we're hijacking.
7560     if (GCPOLL_NONE == opts.compGCPollType)
7561     {
7562         genInterruptible = true;
7563     }
7564 }
7565
7566 GenTreePtr Compiler::fgGetCritSectOfStaticMethod()
7567 {
7568     noway_assert(!compIsForInlining());
7569
7570     noway_assert(info.compIsStatic); // This method should only be called for static methods.
7571
7572     GenTreePtr tree = nullptr;
7573
7574     CORINFO_LOOKUP_KIND kind = info.compCompHnd->getLocationOfThisType(info.compMethodHnd);
7575
7576     if (!kind.needsRuntimeLookup)
7577     {
7578         void *critSect = nullptr, **pCrit = nullptr;
7579         critSect = info.compCompHnd->getMethodSync(info.compMethodHnd, (void**)&pCrit);
7580         noway_assert((!critSect) != (!pCrit));
7581
7582         tree = gtNewIconEmbHndNode(critSect, pCrit, GTF_ICON_METHOD_HDL);
7583     }
7584     else
7585     {
7586         // Collectible types requires that for shared generic code, if we use the generic context paramter
7587         // that we report it. (This is a conservative approach, we could detect some cases particularly when the
7588         // context parameter is this that we don't need the eager reporting logic.)
7589         lvaGenericsContextUseCount++;
7590
7591         switch (kind.runtimeLookupKind)
7592         {
7593             case CORINFO_LOOKUP_THISOBJ:
7594             {
7595                 noway_assert(!"Should never get this for static method.");
7596                 break;
7597             }
7598
7599             case CORINFO_LOOKUP_CLASSPARAM:
7600             {
7601                 // In this case, the hidden param is the class handle.
7602                 tree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL);
7603                 break;
7604             }
7605
7606             case CORINFO_LOOKUP_METHODPARAM:
7607             {
7608                 // In this case, the hidden param is the method handle.
7609                 tree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL);
7610                 // Call helper CORINFO_HELP_GETCLASSFROMMETHODPARAM to get the class handle
7611                 // from the method handle.
7612                 tree = gtNewHelperCallNode(CORINFO_HELP_GETCLASSFROMMETHODPARAM, TYP_I_IMPL, 0, gtNewArgList(tree));
7613                 break;
7614             }
7615
7616             default:
7617             {
7618                 noway_assert(!"Unknown LOOKUP_KIND");
7619                 break;
7620             }
7621         }
7622
7623         noway_assert(tree); // tree should now contain the CORINFO_CLASS_HANDLE for the exact class.
7624
7625         // Given the class handle, get the pointer to the Monitor.
7626         tree = gtNewHelperCallNode(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, TYP_I_IMPL, 0, gtNewArgList(tree));
7627     }
7628
7629     noway_assert(tree);
7630     return tree;
7631 }
7632
7633 #if FEATURE_EH_FUNCLETS
7634
7635 /*****************************************************************************
7636  *
7637  *  Add monitor enter/exit calls for synchronized methods, and a try/fault
7638  *  to ensure the 'exit' is called if the 'enter' was successful. On x86, we
7639  *  generate monitor enter/exit calls and tell the VM the code location of
7640  *  these calls. When an exception occurs between those locations, the VM
7641  *  automatically releases the lock. For non-x86 platforms, the JIT is
7642  *  responsible for creating a try/finally to protect the monitor enter/exit,
7643  *  and the VM doesn't need to know anything special about the method during
7644  *  exception processing -- it's just a normal try/finally.
7645  *
7646  *  We generate the following code:
7647  *
7648  *      void Foo()
7649  *      {
7650  *          unsigned byte acquired = 0;
7651  *          try {
7652  *              JIT_MonEnterWorker(<lock object>, &acquired);
7653  *
7654  *              *** all the preexisting user code goes here ***
7655  *
7656  *              JIT_MonExitWorker(<lock object>, &acquired);
7657  *          } fault {
7658  *              JIT_MonExitWorker(<lock object>, &acquired);
7659  *         }
7660  *      L_return:
7661  *         ret
7662  *      }
7663  *
7664  *  If the lock is actually acquired, then the 'acquired' variable is set to 1
7665  *  by the helper call. During normal exit, the finally is called, 'acquired'
7666  *  is 1, and the lock is released. If an exception occurs before the lock is
7667  *  acquired, but within the 'try' (extremely unlikely, but possible), 'acquired'
7668  *  will be 0, and the monitor exit call will quickly return without attempting
7669  *  to release the lock. Otherwise, 'acquired' will be 1, and the lock will be
7670  *  released during exception processing.
7671  *
7672  *  For synchronized methods, we generate a single return block.
7673  *  We can do this without creating additional "step" blocks because "ret" blocks
7674  *  must occur at the top-level (of the original code), not nested within any EH
7675  *  constructs. From the CLI spec, 12.4.2.8.2.3 "ret": "Shall not be enclosed in any
7676  *  protected block, filter, or handler." Also, 3.57: "The ret instruction cannot be
7677  *  used to transfer control out of a try, filter, catch, or finally block. From within
7678  *  a try or catch, use the leave instruction with a destination of a ret instruction
7679  *  that is outside all enclosing exception blocks."
7680  *
7681  *  In addition, we can add a "fault" at the end of a method and be guaranteed that no
7682  *  control falls through. From the CLI spec, section 12.4 "Control flow": "Control is not
7683  *  permitted to simply fall through the end of a method. All paths shall terminate with one
7684  *  of these instructions: ret, throw, jmp, or (tail. followed by call, calli, or callvirt)."
7685  *
7686  *  We only need to worry about "ret" and "throw", as the CLI spec prevents any other
7687  *  alternatives. Section 15.4.3.3 "Implementation information" states about exiting
7688  *  synchronized methods: "Exiting a synchronized method using a tail. call shall be
7689  *  implemented as though the tail. had not been specified." Section 3.37 "jmp" states:
7690  *  "The jmp instruction cannot be used to transferred control out of a try, filter,
7691  *  catch, fault or finally block; or out of a synchronized region." And, "throw" will
7692  *  be handled naturally; no additional work is required.
7693  */
7694
7695 void Compiler::fgAddSyncMethodEnterExit()
7696 {
7697     assert((info.compFlags & CORINFO_FLG_SYNCH) != 0);
7698
7699     // We need to do this transformation before funclets are created.
7700     assert(!fgFuncletsCreated);
7701
7702     // Assume we don't need to update the bbPreds lists.
7703     assert(!fgComputePredsDone);
7704
7705 #if !FEATURE_EH
7706     // If we don't support EH, we can't add the EH needed by synchronized methods.
7707     // Of course, we could simply ignore adding the EH constructs, since we don't
7708     // support exceptions being thrown in this mode, but we would still need to add
7709     // the monitor enter/exit, and that doesn't seem worth it for this minor case.
7710     // By the time EH is working, we can just enable the whole thing.
7711     NYI("No support for synchronized methods");
7712 #endif // !FEATURE_EH
7713
7714     // Create a scratch first BB where we can put the new variable initialization.
7715     // Don't put the scratch BB in the protected region.
7716
7717     fgEnsureFirstBBisScratch();
7718
7719     // Create a block for the start of the try region, where the monitor enter call
7720     // will go.
7721
7722     assert(fgFirstBB->bbFallsThrough());
7723
7724     BasicBlock* tryBegBB  = fgNewBBafter(BBJ_NONE, fgFirstBB, false);
7725     BasicBlock* tryNextBB = tryBegBB->bbNext;
7726     BasicBlock* tryLastBB = fgLastBB;
7727
7728     // If we have profile data the new block will inherit the next block's weight
7729     if (tryNextBB->hasProfileWeight())
7730     {
7731         tryBegBB->inheritWeight(tryNextBB);
7732     }
7733
7734     // Create a block for the fault.
7735
7736     assert(!tryLastBB->bbFallsThrough());
7737     BasicBlock* faultBB = fgNewBBafter(BBJ_EHFINALLYRET, tryLastBB, false);
7738
7739     assert(tryLastBB->bbNext == faultBB);
7740     assert(faultBB->bbNext == nullptr);
7741     assert(faultBB == fgLastBB);
7742
7743     { // Scope the EH region creation
7744
7745         // Add the new EH region at the end, since it is the least nested,
7746         // and thus should be last.
7747
7748         EHblkDsc* newEntry;
7749         unsigned  XTnew = compHndBBtabCount;
7750
7751         newEntry = fgAddEHTableEntry(XTnew);
7752
7753         // Initialize the new entry
7754
7755         newEntry->ebdHandlerType = EH_HANDLER_FAULT;
7756
7757         newEntry->ebdTryBeg  = tryBegBB;
7758         newEntry->ebdTryLast = tryLastBB;
7759
7760         newEntry->ebdHndBeg  = faultBB;
7761         newEntry->ebdHndLast = faultBB;
7762
7763         newEntry->ebdTyp = 0; // unused for fault
7764
7765         newEntry->ebdEnclosingTryIndex = EHblkDsc::NO_ENCLOSING_INDEX;
7766         newEntry->ebdEnclosingHndIndex = EHblkDsc::NO_ENCLOSING_INDEX;
7767
7768         newEntry->ebdTryBegOffset    = tryBegBB->bbCodeOffs;
7769         newEntry->ebdTryEndOffset    = tryLastBB->bbCodeOffsEnd;
7770         newEntry->ebdFilterBegOffset = 0;
7771         newEntry->ebdHndBegOffset    = 0; // handler doesn't correspond to any IL
7772         newEntry->ebdHndEndOffset    = 0; // handler doesn't correspond to any IL
7773
7774         // Set some flags on the new region. This is the same as when we set up
7775         // EH regions in fgFindBasicBlocks(). Note that the try has no enclosing
7776         // handler, and the fault has no enclosing try.
7777
7778         tryBegBB->bbFlags |= BBF_HAS_LABEL | BBF_DONT_REMOVE | BBF_TRY_BEG | BBF_IMPORTED;
7779
7780         faultBB->bbFlags |= BBF_HAS_LABEL | BBF_DONT_REMOVE | BBF_IMPORTED;
7781         faultBB->bbCatchTyp = BBCT_FAULT;
7782
7783         tryBegBB->setTryIndex(XTnew);
7784         tryBegBB->clearHndIndex();
7785
7786         faultBB->clearTryIndex();
7787         faultBB->setHndIndex(XTnew);
7788
7789         // Walk the user code blocks and set all blocks that don't already have a try handler
7790         // to point to the new try handler.
7791
7792         BasicBlock* tmpBB;
7793         for (tmpBB = tryBegBB->bbNext; tmpBB != faultBB; tmpBB = tmpBB->bbNext)
7794         {
7795             if (!tmpBB->hasTryIndex())
7796             {
7797                 tmpBB->setTryIndex(XTnew);
7798             }
7799         }
7800
7801         // Walk the EH table. Make every EH entry that doesn't already have an enclosing
7802         // try index mark this new entry as their enclosing try index.
7803
7804         unsigned  XTnum;
7805         EHblkDsc* HBtab;
7806
7807         for (XTnum = 0, HBtab = compHndBBtab; XTnum < XTnew; XTnum++, HBtab++)
7808         {
7809             if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
7810             {
7811                 HBtab->ebdEnclosingTryIndex =
7812                     (unsigned short)XTnew; // This EH region wasn't previously nested, but now it is.
7813             }
7814         }
7815
7816 #ifdef DEBUG
7817         if (verbose)
7818         {
7819             JITDUMP("Synchronized method - created additional EH descriptor EH#%u for try/fault wrapping monitor "
7820                     "enter/exit\n",
7821                     XTnew);
7822             fgDispBasicBlocks();
7823             fgDispHandlerTab();
7824         }
7825
7826         fgVerifyHandlerTab();
7827 #endif // DEBUG
7828     }
7829
7830     // Create a 'monitor acquired' boolean (actually, an unsigned byte: 1 = acquired, 0 = not acquired).
7831
7832     var_types typeMonAcquired = TYP_UBYTE;
7833     this->lvaMonAcquired      = lvaGrabTemp(true DEBUGARG("Synchronized method monitor acquired boolean"));
7834
7835     lvaTable[lvaMonAcquired].lvType = typeMonAcquired;
7836
7837     { // Scope the variables of the variable initialization
7838
7839         // Initialize the 'acquired' boolean.
7840
7841         GenTreePtr zero     = gtNewZeroConNode(genActualType(typeMonAcquired));
7842         GenTreePtr varNode  = gtNewLclvNode(lvaMonAcquired, typeMonAcquired);
7843         GenTreePtr initNode = gtNewAssignNode(varNode, zero);
7844
7845         fgInsertStmtAtEnd(fgFirstBB, initNode);
7846
7847 #ifdef DEBUG
7848         if (verbose)
7849         {
7850             printf("\nSynchronized method - Add 'acquired' initialization in first block BB%02u [%08p]\n", fgFirstBB,
7851                    dspPtr(fgFirstBB));
7852             gtDispTree(initNode);
7853             printf("\n");
7854         }
7855 #endif
7856     }
7857
7858     // Make a copy of the 'this' pointer to be used in the handler so it does not inhibit enregistration
7859     // of all uses of the variable.
7860     unsigned lvaCopyThis = 0;
7861     if (!info.compIsStatic)
7862     {
7863         lvaCopyThis                  = lvaGrabTemp(true DEBUGARG("Synchronized method monitor acquired boolean"));
7864         lvaTable[lvaCopyThis].lvType = TYP_REF;
7865
7866         GenTreePtr thisNode = gtNewLclvNode(info.compThisArg, TYP_REF);
7867         GenTreePtr copyNode = gtNewLclvNode(lvaCopyThis, TYP_REF);
7868         GenTreePtr initNode = gtNewAssignNode(copyNode, thisNode);
7869
7870         fgInsertStmtAtEnd(tryBegBB, initNode);
7871     }
7872
7873     fgCreateMonitorTree(lvaMonAcquired, info.compThisArg, tryBegBB, true /*enter*/);
7874
7875     // exceptional case
7876     fgCreateMonitorTree(lvaMonAcquired, lvaCopyThis, faultBB, false /*exit*/);
7877
7878     // non-exceptional cases
7879     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
7880     {
7881         if (block->bbJumpKind == BBJ_RETURN)
7882         {
7883             fgCreateMonitorTree(lvaMonAcquired, info.compThisArg, block, false /*exit*/);
7884         }
7885     }
7886 }
7887
7888 // fgCreateMonitorTree: Create tree to execute a monitor enter or exit operation for synchronized methods
7889 //    lvaMonAcquired: lvaNum of boolean variable that tracks if monitor has been acquired.
7890 //    lvaThisVar: lvaNum of variable being used as 'this' pointer, may not be the original one.  Is only used for
7891 //    nonstatic methods
7892 //    block: block to insert the tree in.  It is inserted at the end or in the case of a return, immediately before the
7893 //    GT_RETURN
7894 //    enter: whether to create a monitor enter or exit
7895
7896 GenTree* Compiler::fgCreateMonitorTree(unsigned lvaMonAcquired, unsigned lvaThisVar, BasicBlock* block, bool enter)
7897 {
7898     // Insert the expression "enter/exitCrit(this, &acquired)" or "enter/exitCrit(handle, &acquired)"
7899
7900     var_types  typeMonAcquired = TYP_UBYTE;
7901     GenTreePtr varNode         = gtNewLclvNode(lvaMonAcquired, typeMonAcquired);
7902     GenTreePtr varAddrNode     = gtNewOperNode(GT_ADDR, TYP_BYREF, varNode);
7903     GenTreePtr tree;
7904
7905     if (info.compIsStatic)
7906     {
7907         tree = fgGetCritSectOfStaticMethod();
7908         tree = gtNewHelperCallNode(enter ? CORINFO_HELP_MON_ENTER_STATIC : CORINFO_HELP_MON_EXIT_STATIC, TYP_VOID, 0,
7909                                    gtNewArgList(tree, varAddrNode));
7910     }
7911     else
7912     {
7913         tree = gtNewLclvNode(lvaThisVar, TYP_REF);
7914         tree = gtNewHelperCallNode(enter ? CORINFO_HELP_MON_ENTER : CORINFO_HELP_MON_EXIT, TYP_VOID, 0,
7915                                    gtNewArgList(tree, varAddrNode));
7916     }
7917
7918 #ifdef DEBUG
7919     if (verbose)
7920     {
7921         printf("\nSynchronized method - Add monitor %s call to block BB%02u [%08p]\n", enter ? "enter" : "exit", block,
7922                dspPtr(block));
7923         gtDispTree(tree);
7924         printf("\n");
7925     }
7926 #endif
7927
7928     if (block->bbJumpKind == BBJ_RETURN && block->lastStmt()->gtStmtExpr->gtOper == GT_RETURN)
7929     {
7930         GenTree* retNode = block->lastStmt()->gtStmtExpr;
7931         GenTree* retExpr = retNode->gtOp.gtOp1;
7932
7933         if (retExpr != nullptr)
7934         {
7935             // have to insert this immediately before the GT_RETURN so we transform:
7936             // ret(...) ->
7937             // ret(comma(comma(tmp=...,call mon_exit), tmp)
7938             //
7939             //
7940             // Before morph stage, it is possible to have a case of GT_RETURN(TYP_LONG, op1) where op1's type is
7941             // TYP_STRUCT (of 8-bytes) and op1 is call node. See the big comment block in impReturnInstruction()
7942             // for details for the case where info.compRetType is not the same as info.compRetNativeType.  For
7943             // this reason pass compMethodInfo->args.retTypeClass which is guaranteed to be a valid class handle
7944             // if the return type is a value class.  Note that fgInsertCommFormTemp() in turn uses this class handle
7945             // if the type of op1 is TYP_STRUCT to perform lvaSetStruct() on the new temp that is created, which
7946             // in turn passes it to VM to know the size of value type.
7947             GenTree* temp = fgInsertCommaFormTemp(&retNode->gtOp.gtOp1, info.compMethodInfo->args.retTypeClass);
7948
7949             GenTree* lclVar                 = retNode->gtOp.gtOp1->gtOp.gtOp2;
7950             retNode->gtOp.gtOp1->gtOp.gtOp2 = gtNewOperNode(GT_COMMA, retExpr->TypeGet(), tree, lclVar);
7951         }
7952         else
7953         {
7954             // Insert this immediately before the GT_RETURN
7955             fgInsertStmtNearEnd(block, tree);
7956         }
7957     }
7958     else
7959     {
7960         fgInsertStmtAtEnd(block, tree);
7961     }
7962
7963     return tree;
7964 }
7965
7966 // Convert a BBJ_RETURN block in a synchronized method to a BBJ_ALWAYS.
7967 // We've previously added a 'try' block around the original program code using fgAddSyncMethodEnterExit().
7968 // Thus, we put BBJ_RETURN blocks inside a 'try'. In IL this is illegal. Instead, we would
7969 // see a 'leave' inside a 'try' that would get transformed into BBJ_CALLFINALLY/BBJ_ALWAYS blocks
7970 // during importing, and the BBJ_ALWAYS would point at an outer block with the BBJ_RETURN.
7971 // Here, we mimic some of the logic of importing a LEAVE to get the same effect for synchronized methods.
7972 void Compiler::fgConvertSyncReturnToLeave(BasicBlock* block)
7973 {
7974     assert(!fgFuncletsCreated);
7975     assert(info.compFlags & CORINFO_FLG_SYNCH);
7976     assert(genReturnBB != nullptr);
7977     assert(genReturnBB != block);
7978     assert(fgReturnCount <= 1); // We have a single return for synchronized methods
7979     assert(block->bbJumpKind == BBJ_RETURN);
7980     assert((block->bbFlags & BBF_HAS_JMP) == 0);
7981     assert(block->hasTryIndex());
7982     assert(!block->hasHndIndex());
7983     assert(compHndBBtabCount >= 1);
7984
7985     unsigned tryIndex = block->getTryIndex();
7986     assert(tryIndex == compHndBBtabCount - 1); // The BBJ_RETURN must be at the top-level before we inserted the
7987                                                // try/finally, which must be the last EH region.
7988
7989     EHblkDsc* ehDsc = ehGetDsc(tryIndex);
7990     assert(ehDsc->ebdEnclosingTryIndex ==
7991            EHblkDsc::NO_ENCLOSING_INDEX); // There are no enclosing regions of the BBJ_RETURN block
7992     assert(ehDsc->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
7993
7994     // Convert the BBJ_RETURN to BBJ_ALWAYS, jumping to genReturnBB.
7995     block->bbJumpKind = BBJ_ALWAYS;
7996     block->bbJumpDest = genReturnBB;
7997     block->bbJumpDest->bbRefs++;
7998
7999 #ifdef DEBUG
8000     if (verbose)
8001     {
8002         printf("Synchronized method - convert block BB%02u to BBJ_ALWAYS [targets BB%02u]\n", block->bbNum,
8003                block->bbJumpDest->bbNum);
8004     }
8005 #endif
8006 }
8007
8008 #endif // FEATURE_EH_FUNCLETS
8009
8010 //------------------------------------------------------------------------
8011 // fgAddReversePInvokeEnterExit: Add enter/exit calls for reverse PInvoke methods
8012 //
8013 // Arguments:
8014 //      None.
8015 //
8016 // Return Value:
8017 //      None.
8018
8019 void Compiler::fgAddReversePInvokeEnterExit()
8020 {
8021     assert(opts.IsReversePInvoke());
8022
8023     lvaReversePInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Reverse Pinvoke FrameVar"));
8024
8025     LclVarDsc* varDsc   = &lvaTable[lvaReversePInvokeFrameVar];
8026     varDsc->lvType      = TYP_BLK;
8027     varDsc->lvExactSize = eeGetEEInfo()->sizeOfReversePInvokeFrame;
8028
8029     GenTreePtr tree;
8030
8031     // Add enter pinvoke exit callout at the start of prolog
8032
8033     tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));
8034
8035     tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, TYP_VOID, 0, gtNewArgList(tree));
8036
8037     fgEnsureFirstBBisScratch();
8038
8039     fgInsertStmtAtBeg(fgFirstBB, tree);
8040
8041 #ifdef DEBUG
8042     if (verbose)
8043     {
8044         printf("\nReverse PInvoke method - Add reverse pinvoke enter in first basic block [%08p]\n", dspPtr(fgFirstBB));
8045         gtDispTree(tree);
8046         printf("\n");
8047     }
8048 #endif
8049
8050     // Add reverse pinvoke exit callout at the end of epilog
8051
8052     tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));
8053
8054     tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, TYP_VOID, 0, gtNewArgList(tree));
8055
8056     assert(genReturnBB != nullptr);
8057
8058     fgInsertStmtAtEnd(genReturnBB, tree);
8059
8060 #ifdef DEBUG
8061     if (verbose)
8062     {
8063         printf("\nReverse PInvoke method - Add reverse pinvoke exit in return basic block [%08p]\n",
8064                dspPtr(genReturnBB));
8065         gtDispTree(tree);
8066         printf("\n");
8067     }
8068 #endif
8069 }
8070
8071 /*****************************************************************************
8072  *
8073  *  Return 'true' if there is more than one BBJ_RETURN block.
8074  */
8075
8076 bool Compiler::fgMoreThanOneReturnBlock()
8077 {
8078     unsigned retCnt = 0;
8079
8080     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
8081     {
8082         if (block->bbJumpKind == BBJ_RETURN)
8083         {
8084             retCnt++;
8085             if (retCnt > 1)
8086             {
8087                 return true;
8088             }
8089         }
8090     }
8091
8092     return false;
8093 }
8094
8095 /*****************************************************************************
8096  *
8097  *  Add any internal blocks/trees we may need
8098  */
8099
8100 void Compiler::fgAddInternal()
8101 {
8102     noway_assert(!compIsForInlining());
8103
8104 #ifndef LEGACY_BACKEND
8105     // The RyuJIT backend requires a scratch BB into which it can safely insert a P/Invoke method prolog if one is
8106     // required. Create it here.
8107     if (info.compCallUnmanaged != 0)
8108     {
8109         fgEnsureFirstBBisScratch();
8110         fgFirstBB->bbFlags |= BBF_DONT_REMOVE;
8111     }
8112 #endif // !LEGACY_BACKEND
8113
8114     /*
8115         <BUGNUM> VSW441487 </BUGNUM>
8116
8117         The "this" pointer is implicitly used in the following cases:
8118             1. Locking of synchronized methods
8119             2. Dictionary access of shared generics code
8120             3. If a method has "catch(FooException<T>)", the EH code accesses "this" to determine T.
8121             4. Initializing the type from generic methods which require precise cctor semantics
8122             5. Verifier does special handling of "this" in the .ctor
8123
8124         However, we might overwrite it with a "starg 0".
8125         In this case, we will redirect all "ldarg(a)/starg(a) 0" to a temp lvaTable[lvaArg0Var]
8126     */
8127
8128     if (!info.compIsStatic)
8129     {
8130         if (lvaArg0Var != info.compThisArg)
8131         {
8132             // When we're using the general encoder, we mark compThisArg address-taken to ensure that it is not
8133             // enregistered (since the decoder always reports a stack location for "this" for generics
8134             // context vars).
8135             bool lva0CopiedForGenericsCtxt;
8136 #ifndef JIT32_GCENCODER
8137             lva0CopiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0);
8138 #else  // JIT32_GCENCODER
8139             lva0CopiedForGenericsCtxt = false;
8140 #endif // JIT32_GCENCODER
8141             noway_assert(lva0CopiedForGenericsCtxt || !lvaTable[info.compThisArg].lvAddrExposed);
8142             noway_assert(!lvaTable[info.compThisArg].lvHasILStoreOp);
8143             noway_assert(lvaTable[lvaArg0Var].lvAddrExposed || lvaTable[lvaArg0Var].lvHasILStoreOp ||
8144                          lva0CopiedForGenericsCtxt);
8145
8146             var_types thisType = lvaTable[info.compThisArg].TypeGet();
8147
8148             // Now assign the original input "this" to the temp
8149
8150             GenTreePtr tree;
8151
8152             tree = gtNewLclvNode(lvaArg0Var, thisType);
8153
8154             tree = gtNewAssignNode(tree,                                     // dst
8155                                    gtNewLclvNode(info.compThisArg, thisType) // src
8156                                    );
8157
8158             /* Create a new basic block and stick the assignment in it */
8159
8160             fgEnsureFirstBBisScratch();
8161
8162             fgInsertStmtAtEnd(fgFirstBB, tree);
8163
8164 #ifdef DEBUG
8165             if (verbose)
8166             {
8167                 printf("\nCopy \"this\" to lvaArg0Var in first basic block [%08p]\n", dspPtr(fgFirstBB));
8168                 gtDispTree(tree);
8169                 printf("\n");
8170             }
8171 #endif
8172         }
8173     }
8174
8175     // Grab a temp for the security object.
8176     // (Note: opts.compDbgEnC currently also causes the security object to be generated. See Compiler::compCompile)
8177     if (opts.compNeedSecurityCheck)
8178     {
8179         noway_assert(lvaSecurityObject == BAD_VAR_NUM);
8180         lvaSecurityObject                  = lvaGrabTempWithImplicitUse(false DEBUGARG("security check"));
8181         lvaTable[lvaSecurityObject].lvType = TYP_REF;
8182     }
8183
8184     /* Assume we will generate a single shared return sequence */
8185
8186     ULONG returnWeight = 0;
8187     bool  oneReturn;
8188     bool  allProfWeight;
8189
8190     //
8191     //  We will generate just one epilog (return block)
8192     //   when we are asked to generate enter/leave callbacks
8193     //   or for methods with PInvoke
8194     //   or for methods calling into unmanaged code
8195     //   or for synchronized methods.
8196     //
8197     if (compIsProfilerHookNeeded() || (info.compCallUnmanaged != 0) || opts.IsReversePInvoke() ||
8198         ((info.compFlags & CORINFO_FLG_SYNCH) != 0))
8199     {
8200         // We will generate only one return block
8201         // We will transform the BBJ_RETURN blocks
8202         //  into jumps to the one return block
8203         //
8204         oneReturn     = true;
8205         allProfWeight = false;
8206     }
8207     else
8208     {
8209         //
8210         // We are allowed to have multiple individual exits
8211         // However we can still decide to have a single return
8212         //
8213         oneReturn     = false;
8214         allProfWeight = true;
8215
8216         // Count the BBJ_RETURN blocks and set the returnWeight to the
8217         // sum of all these blocks.
8218         //
8219         fgReturnCount = 0;
8220         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
8221         {
8222             if (block->bbJumpKind == BBJ_RETURN)
8223             {
8224                 //
8225                 // returnCount is the count of BBJ_RETURN blocks in this method
8226                 //
8227                 fgReturnCount++;
8228                 //
8229                 // If all BBJ_RETURN blocks have a valid profiled weights
8230                 // then allProfWeight will be true, else it is false
8231                 //
8232                 if (!block->hasProfileWeight())
8233                 {
8234                     allProfWeight = false;
8235                 }
8236                 //
8237                 // returnWeight is the sum of the weights of all BBJ_RETURN blocks
8238                 returnWeight += block->bbWeight;
8239             }
8240         }
8241
8242         //
8243         // If we only have one (or zero) return blocks then
8244         // we do not need a special one return block
8245         //
8246         if (fgReturnCount > 1)
8247         {
8248             //
8249             // should we generate a single return block?
8250             //
8251             if (fgReturnCount > 4)
8252             {
8253                 // Our epilog encoding only supports up to 4 epilogs
8254                 // TODO-CQ: support >4 return points for ARM/AMD64, which presumably support any number of epilogs?
8255                 //
8256                 oneReturn = true;
8257             }
8258             else if (compCodeOpt() == SMALL_CODE)
8259             {
8260                 // For the Small_Code case we always generate a
8261                 // single return block when we have multiple
8262                 // return points
8263                 //
8264                 oneReturn = true;
8265             }
8266         }
8267     }
8268
8269 #if FEATURE_EH_FUNCLETS
8270     // Add the synchronized method enter/exit calls and try/finally protection. Note
8271     // that this must happen before the one BBJ_RETURN block is created below, so the
8272     // BBJ_RETURN block gets placed at the top-level, not within an EH region. (Otherwise,
8273     // we'd have to be really careful when creating the synchronized method try/finally
8274     // not to include the BBJ_RETURN block.)
8275     if ((info.compFlags & CORINFO_FLG_SYNCH) != 0)
8276     {
8277         fgAddSyncMethodEnterExit();
8278     }
8279 #endif // FEATURE_EH_FUNCLETS
8280
8281     if (oneReturn)
8282     {
8283         genReturnBB         = fgNewBBinRegion(BBJ_RETURN);
8284         genReturnBB->bbRefs = 1; // bbRefs gets update later, for now it should be 1
8285         fgReturnCount++;
8286
8287         if (allProfWeight)
8288         {
8289             //
8290             // if we have profile data for all BBJ_RETURN blocks
8291             // then we can set BBF_PROF_WEIGHT for genReturnBB
8292             //
8293             genReturnBB->bbFlags |= BBF_PROF_WEIGHT;
8294         }
8295         else
8296         {
8297             //
8298             // We can't rely upon the calculated returnWeight unless
8299             // all of the BBJ_RETURN blocks had valid profile weights
8300             // So we will use the weight of the first block instead
8301             //
8302             returnWeight = fgFirstBB->bbWeight;
8303         }
8304
8305         //
8306         // Set the weight of the oneReturn block
8307         //
8308         genReturnBB->bbWeight = min(returnWeight, BB_MAX_WEIGHT);
8309
8310         if (returnWeight == 0)
8311         {
8312             //
8313             // If necessary set the Run Rarely flag
8314             //
8315             genReturnBB->bbFlags |= BBF_RUN_RARELY;
8316         }
8317         else
8318         {
8319             // Make sure that the RunRarely flag is clear
8320             // because fgNewBBinRegion will set it to true
8321             //
8322             genReturnBB->bbFlags &= ~BBF_RUN_RARELY;
8323         }
8324
8325         genReturnBB->bbFlags |= (BBF_INTERNAL | BBF_DONT_REMOVE);
8326
8327         noway_assert(genReturnBB->bbNext == nullptr);
8328
8329 #ifdef DEBUG
8330         if (verbose)
8331         {
8332             printf("\n genReturnBB [BB%02u] created\n", genReturnBB->bbNum);
8333         }
8334 #endif
8335     }
8336     else
8337     {
8338         //
8339         // We don't have a oneReturn block for this method
8340         //
8341         genReturnBB = nullptr;
8342     }
8343
8344     // If there is a return value, then create a temp for it.  Real returns will store the value in there and
8345     // it'll be reloaded by the single return.
8346     if (genReturnBB && compMethodHasRetVal())
8347     {
8348         genReturnLocal = lvaGrabTemp(true DEBUGARG("Single return block return value"));
8349
8350         if (compMethodReturnsNativeScalarType())
8351         {
8352             lvaTable[genReturnLocal].lvType = genActualType(info.compRetNativeType);
8353         }
8354         else if (compMethodReturnsRetBufAddr())
8355         {
8356             lvaTable[genReturnLocal].lvType = TYP_BYREF;
8357         }
8358         else if (compMethodReturnsMultiRegRetType())
8359         {
8360             lvaTable[genReturnLocal].lvType = TYP_STRUCT;
8361             lvaSetStruct(genReturnLocal, info.compMethodInfo->args.retTypeClass, true);
8362             lvaTable[genReturnLocal].lvIsMultiRegRet = true;
8363         }
8364         else
8365         {
8366             assert(!"unreached");
8367         }
8368
8369         if (varTypeIsFloating(lvaTable[genReturnLocal].lvType))
8370         {
8371             this->compFloatingPointUsed = true;
8372         }
8373
8374         if (!varTypeIsFloating(info.compRetType))
8375         {
8376             lvaTable[genReturnLocal].setPrefReg(REG_INTRET, this);
8377         }
8378 #ifdef REG_FLOATRET
8379         else
8380         {
8381             lvaTable[genReturnLocal].setPrefReg(REG_FLOATRET, this);
8382         }
8383 #endif
8384
8385 #ifdef DEBUG
8386         // This temporary should not be converted to a double in stress mode,
8387         // because we introduce assigns to it after the stress conversion
8388         lvaTable[genReturnLocal].lvKeepType = 1;
8389 #endif
8390     }
8391     else
8392     {
8393         genReturnLocal = BAD_VAR_NUM;
8394     }
8395
8396     if (info.compCallUnmanaged != 0)
8397     {
8398         // The P/Invoke helpers only require a frame variable, so only allocate the
8399         // TCB variable if we're not using them.
8400         if (!opts.ShouldUsePInvokeHelpers())
8401         {
8402             info.compLvFrameListRoot = lvaGrabTemp(false DEBUGARG("Pinvoke FrameListRoot"));
8403         }
8404
8405         lvaInlinedPInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Pinvoke FrameVar"));
8406
8407         LclVarDsc* varDsc = &lvaTable[lvaInlinedPInvokeFrameVar];
8408         varDsc->addPrefReg(RBM_PINVOKE_TCB, this);
8409         varDsc->lvType = TYP_BLK;
8410         // Make room for the inlined frame.
8411         varDsc->lvExactSize = eeGetEEInfo()->inlinedCallFrameInfo.size;
8412 #if FEATURE_FIXED_OUT_ARGS
8413         // Grab and reserve space for TCB, Frame regs used in PInvoke epilog to pop the inlined frame.
8414         // See genPInvokeMethodEpilog() for use of the grabbed var. This is only necessary if we are
8415         // not using the P/Invoke helpers.
8416         if (!opts.ShouldUsePInvokeHelpers() && compJmpOpUsed)
8417         {
8418             lvaPInvokeFrameRegSaveVar = lvaGrabTempWithImplicitUse(false DEBUGARG("PInvokeFrameRegSave Var"));
8419             varDsc                    = &lvaTable[lvaPInvokeFrameRegSaveVar];
8420             varDsc->lvType            = TYP_BLK;
8421             varDsc->lvExactSize       = 2 * REGSIZE_BYTES;
8422         }
8423 #endif
8424     }
8425
8426     // Do we need to insert a "JustMyCode" callback?
8427
8428     CORINFO_JUST_MY_CODE_HANDLE* pDbgHandle = nullptr;
8429     CORINFO_JUST_MY_CODE_HANDLE  dbgHandle  = nullptr;
8430     if (opts.compDbgCode && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB))
8431     {
8432         dbgHandle = info.compCompHnd->getJustMyCodeHandle(info.compMethodHnd, &pDbgHandle);
8433     }
8434
8435 #ifdef _TARGET_ARM64_
8436     // TODO-ARM64-NYI: don't do just-my-code
8437     dbgHandle  = nullptr;
8438     pDbgHandle = nullptr;
8439 #endif // _TARGET_ARM64_
8440
8441     noway_assert(!dbgHandle || !pDbgHandle);
8442
8443     if (dbgHandle || pDbgHandle)
8444     {
8445         GenTreePtr guardCheckVal =
8446             gtNewOperNode(GT_IND, TYP_INT, gtNewIconEmbHndNode(dbgHandle, pDbgHandle, GTF_ICON_TOKEN_HDL));
8447         GenTreePtr guardCheckCond = gtNewOperNode(GT_EQ, TYP_INT, guardCheckVal, gtNewZeroConNode(TYP_INT));
8448         guardCheckCond->gtFlags |= GTF_RELOP_QMARK;
8449
8450         // Create the callback which will yield the final answer
8451
8452         GenTreePtr callback = gtNewHelperCallNode(CORINFO_HELP_DBG_IS_JUST_MY_CODE, TYP_VOID);
8453         callback            = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), callback);
8454
8455         // Stick the conditional call at the start of the method
8456
8457         fgEnsureFirstBBisScratch();
8458         fgInsertStmtAtEnd(fgFirstBB, gtNewQmarkNode(TYP_VOID, guardCheckCond, callback));
8459     }
8460
8461     /* Do we need to call out for security ? */
8462
8463     if (tiSecurityCalloutNeeded)
8464     {
8465         // We must have grabbed this local.
8466         noway_assert(opts.compNeedSecurityCheck);
8467         noway_assert(lvaSecurityObject != BAD_VAR_NUM);
8468
8469         GenTreePtr tree;
8470
8471         /* Insert the expression "call JIT_Security_Prolog(MethodHnd, &SecurityObject)" */
8472
8473         tree = gtNewIconEmbMethHndNode(info.compMethodHnd);
8474
8475         tree = gtNewHelperCallNode(info.compCompHnd->getSecurityPrologHelper(info.compMethodHnd), TYP_VOID, 0,
8476                                    gtNewArgList(tree, gtNewOperNode(GT_ADDR, TYP_BYREF,
8477                                                                     gtNewLclvNode(lvaSecurityObject, TYP_REF))));
8478
8479         /* Create a new basic block and stick the call in it */
8480
8481         fgEnsureFirstBBisScratch();
8482
8483         fgInsertStmtAtEnd(fgFirstBB, tree);
8484
8485 #ifdef DEBUG
8486         if (verbose)
8487         {
8488             printf("\ntiSecurityCalloutNeeded - Add call JIT_Security_Prolog(%08p) statement ",
8489                    dspPtr(info.compMethodHnd));
8490             printTreeID(tree);
8491             printf(" in first basic block [%08p]\n", dspPtr(fgFirstBB));
8492             gtDispTree(tree);
8493             printf("\n");
8494         }
8495 #endif
8496     }
8497
8498 #if !FEATURE_EH_FUNCLETS
8499
8500     /* Is this a 'synchronized' method? */
8501
8502     if (info.compFlags & CORINFO_FLG_SYNCH)
8503     {
8504         GenTreePtr tree = NULL;
8505
8506         /* Insert the expression "enterCrit(this)" or "enterCrit(handle)" */
8507
8508         if (info.compIsStatic)
8509         {
8510             tree = fgGetCritSectOfStaticMethod();
8511
8512             tree = gtNewHelperCallNode(CORINFO_HELP_MON_ENTER_STATIC, TYP_VOID, 0, gtNewArgList(tree));
8513         }
8514         else
8515         {
8516             noway_assert(lvaTable[info.compThisArg].lvType == TYP_REF);
8517
8518             tree = gtNewLclvNode(info.compThisArg, TYP_REF);
8519
8520             tree = gtNewHelperCallNode(CORINFO_HELP_MON_ENTER, TYP_VOID, 0, gtNewArgList(tree));
8521         }
8522
8523         /* Create a new basic block and stick the call in it */
8524
8525         fgEnsureFirstBBisScratch();
8526
8527         fgInsertStmtAtEnd(fgFirstBB, tree);
8528
8529 #ifdef DEBUG
8530         if (verbose)
8531         {
8532             printf("\nSynchronized method - Add enterCrit statement in first basic block [%08p]\n", dspPtr(fgFirstBB));
8533             gtDispTree(tree);
8534             printf("\n");
8535         }
8536 #endif
8537
8538         /* We must be generating a single exit point for this to work */
8539
8540         noway_assert(oneReturn);
8541         noway_assert(genReturnBB);
8542
8543         /* Create the expression "exitCrit(this)" or "exitCrit(handle)" */
8544
8545         if (info.compIsStatic)
8546         {
8547             tree = fgGetCritSectOfStaticMethod();
8548
8549             tree = gtNewHelperCallNode(CORINFO_HELP_MON_EXIT_STATIC, TYP_VOID, 0, gtNewArgList(tree));
8550         }
8551         else
8552         {
8553             tree = gtNewLclvNode(info.compThisArg, TYP_REF);
8554
8555             tree = gtNewHelperCallNode(CORINFO_HELP_MON_EXIT, TYP_VOID, 0, gtNewArgList(tree));
8556         }
8557
8558         fgInsertStmtAtEnd(genReturnBB, tree);
8559
8560 #ifdef DEBUG
8561         if (verbose)
8562         {
8563             printf("\nSynchronized method - Add exit expression ");
8564             printTreeID(tree);
8565             printf("\n");
8566         }
8567 #endif
8568
8569         // Reset cookies used to track start and end of the protected region in synchronized methods
8570         syncStartEmitCookie = NULL;
8571         syncEndEmitCookie   = NULL;
8572     }
8573
8574 #endif // !FEATURE_EH_FUNCLETS
8575
8576     /* Do we need to do runtime call out to check the security? */
8577
8578     if (tiRuntimeCalloutNeeded)
8579     {
8580         GenTreePtr tree;
8581
8582         /* Insert the expression "call verificationRuntimeCheck(MethodHnd)" */
8583
8584         tree = gtNewIconEmbMethHndNode(info.compMethodHnd);
8585
8586         tree = gtNewHelperCallNode(CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, TYP_VOID, 0, gtNewArgList(tree));
8587
8588         /* Create a new basic block and stick the call in it */
8589
8590         fgEnsureFirstBBisScratch();
8591
8592         fgInsertStmtAtEnd(fgFirstBB, tree);
8593
8594 #ifdef DEBUG
8595         if (verbose)
8596         {
8597             printf("\ntiRuntimeCalloutNeeded - Call verificationRuntimeCheck(%08p) statement in first basic block "
8598                    "[%08p]\n",
8599                    dspPtr(info.compMethodHnd), dspPtr(fgFirstBB));
8600             gtDispTree(tree);
8601             printf("\n");
8602         }
8603 #endif
8604     }
8605
8606     if (opts.IsReversePInvoke())
8607     {
8608         fgAddReversePInvokeEnterExit();
8609     }
8610
8611     //
8612     //  Add 'return' expression to the return block if we made it as "oneReturn" before.
8613     //
8614     if (oneReturn)
8615     {
8616         GenTreePtr tree;
8617
8618         //
8619         // Make the 'return' expression.
8620         //
8621
8622         // make sure to reload the return value as part of the return (it is saved by the "real return").
8623         if (genReturnLocal != BAD_VAR_NUM)
8624         {
8625             noway_assert(compMethodHasRetVal());
8626
8627             GenTreePtr retTemp = gtNewLclvNode(genReturnLocal, lvaTable[genReturnLocal].TypeGet());
8628
8629             // make sure copy prop ignores this node (make sure it always does a reload from the temp).
8630             retTemp->gtFlags |= GTF_DONT_CSE;
8631             tree = gtNewOperNode(GT_RETURN, retTemp->gtType, retTemp);
8632         }
8633         else
8634         {
8635             noway_assert(info.compRetType == TYP_VOID || varTypeIsStruct(info.compRetType));
8636             // return void
8637             tree = new (this, GT_RETURN) GenTreeOp(GT_RETURN, TYP_VOID);
8638         }
8639
8640         /* Add 'return' expression to the return block */
8641
8642         noway_assert(genReturnBB);
8643
8644         fgInsertStmtAtEnd(genReturnBB, tree);
8645
8646 #ifdef DEBUG
8647         if (verbose)
8648         {
8649             printf("\noneReturn statement tree ");
8650             printTreeID(tree);
8651             printf(" added to genReturnBB [%08p]\n", dspPtr(genReturnBB));
8652             gtDispTree(tree);
8653             printf("\n");
8654         }
8655 #endif
8656     }
8657
8658 #ifdef DEBUG
8659     if (verbose)
8660     {
8661         printf("\n*************** After fgAddInternal()\n");
8662         fgDispBasicBlocks();
8663         fgDispHandlerTab();
8664     }
8665 #endif
8666 }
8667
8668 /*****************************************************************************
8669  *
8670  *  Create a new statement from tree and wire the links up.
8671  */
8672 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree, BasicBlock* block, IL_OFFSETX offs)
8673 {
8674     GenTreeStmt* stmt = gtNewStmt(tree, offs);
8675
8676     if (fgStmtListThreaded)
8677     {
8678         gtSetStmtInfo(stmt);
8679         fgSetStmtSeq(stmt);
8680     }
8681
8682 #if DEBUG
8683     if (block != nullptr)
8684     {
8685         fgDebugCheckNodeLinks(block, stmt);
8686     }
8687 #endif
8688
8689     return stmt;
8690 }
8691
8692 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree)
8693 {
8694     return fgNewStmtFromTree(tree, nullptr, BAD_IL_OFFSET);
8695 }
8696
8697 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree, BasicBlock* block)
8698 {
8699     return fgNewStmtFromTree(tree, block, BAD_IL_OFFSET);
8700 }
8701
8702 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree, IL_OFFSETX offs)
8703 {
8704     return fgNewStmtFromTree(tree, nullptr, offs);
8705 }
8706
8707 //------------------------------------------------------------------------
8708 // fgFindBlockILOffset: Given a block, find the IL offset corresponding to the first statement
8709 //      in the block with a legal IL offset. Skip any leading statements that have BAD_IL_OFFSET.
8710 //      If no statement has an initialized statement offset (including the case where there are
8711 //      no statements in the block), then return BAD_IL_OFFSET. This function is used when
8712 //      blocks are split or modified, and we want to maintain the IL offset as much as possible
8713 //      to preserve good debugging behavior.
8714 //
8715 // Arguments:
8716 //      block - The block to check.
8717 //
8718 // Return Value:
8719 //      The first good IL offset of a statement in the block, or BAD_IL_OFFSET if such an IL offset
8720 //      cannot be found.
8721 //
8722 IL_OFFSET Compiler::fgFindBlockILOffset(BasicBlock* block)
8723 {
8724     // This function searches for IL offsets in statement nodes, so it can't be used in LIR. We
8725     // could have a similar function for LIR that searches for GT_IL_OFFSET nodes.
8726     assert(!block->IsLIR());
8727
8728     for (GenTree* stmt = block->bbTreeList; stmt != nullptr; stmt = stmt->gtNext)
8729     {
8730         assert(stmt->IsStatement());
8731         if (stmt->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET)
8732         {
8733             return jitGetILoffs(stmt->gtStmt.gtStmtILoffsx);
8734         }
8735     }
8736
8737     return BAD_IL_OFFSET;
8738 }
8739
8740 //------------------------------------------------------------------------------
8741 // fgSplitBlockAtEnd - split the given block into two blocks.
8742 //                   All code in the block stays in the original block.
8743 //                   Control falls through from original to new block, and
8744 //                   the new block is returned.
8745 //------------------------------------------------------------------------------
8746 BasicBlock* Compiler::fgSplitBlockAtEnd(BasicBlock* curr)
8747 {
8748     // We'd like to use fgNewBBafter(), but we need to update the preds list before linking in the new block.
8749     // (We need the successors of 'curr' to be correct when we do this.)
8750     BasicBlock* newBlock = bbNewBasicBlock(curr->bbJumpKind);
8751
8752     // Start the new block with no refs. When we set the preds below, this will get updated correctly.
8753     newBlock->bbRefs = 0;
8754
8755     // For each successor of the original block, set the new block as their predecessor.
8756     // Note we are using the "rational" version of the successor iterator that does not hide the finallyret arcs.
8757     // Without these arcs, a block 'b' may not be a member of succs(preds(b))
8758     if (curr->bbJumpKind != BBJ_SWITCH)
8759     {
8760         unsigned numSuccs = curr->NumSucc(this);
8761         for (unsigned i = 0; i < numSuccs; i++)
8762         {
8763             BasicBlock* succ = curr->GetSucc(i, this);
8764             if (succ != newBlock)
8765             {
8766                 JITDUMP("BB%02u previous predecessor was BB%02u, now is BB%02u\n", succ->bbNum, curr->bbNum,
8767                         newBlock->bbNum);
8768                 fgReplacePred(succ, curr, newBlock);
8769             }
8770         }
8771
8772         newBlock->bbJumpDest = curr->bbJumpDest;
8773         curr->bbJumpDest     = nullptr;
8774     }
8775     else
8776     {
8777         // In the case of a switch statement there's more complicated logic in order to wire up the predecessor lists
8778         // but fortunately there's an existing method that implements this functionality.
8779         newBlock->bbJumpSwt = curr->bbJumpSwt;
8780
8781         fgChangeSwitchBlock(curr, newBlock);
8782
8783         curr->bbJumpSwt = nullptr;
8784     }
8785
8786     newBlock->inheritWeight(curr);
8787
8788     // Set the new block's flags. Note that the new block isn't BBF_INTERNAL unless the old block is.
8789     newBlock->bbFlags = curr->bbFlags;
8790
8791     // Remove flags that the new block can't have.
8792     newBlock->bbFlags &= ~(BBF_TRY_BEG | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1 | BBF_HAS_LABEL |
8793                            BBF_JMP_TARGET | BBF_FUNCLET_BEG | BBF_LOOP_PREHEADER | BBF_KEEP_BBJ_ALWAYS);
8794
8795     // Remove the GC safe bit on the new block. It seems clear that if we split 'curr' at the end,
8796     // such that all the code is left in 'curr', and 'newBlock' just gets the control flow, then
8797     // both 'curr' and 'newBlock' could accurately retain an existing GC safe bit. However, callers
8798     // use this function to split blocks in the middle, or at the beginning, and they don't seem to
8799     // be careful about updating this flag appropriately. So, removing the GC safe bit is simply
8800     // conservative: some functions might end up being fully interruptible that could be partially
8801     // interruptible if we exercised more care here.
8802     newBlock->bbFlags &= ~BBF_GC_SAFE_POINT;
8803
8804 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
8805     newBlock->bbFlags &= ~(BBF_FINALLY_TARGET);
8806 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
8807
8808     // The new block has no code, so we leave bbCodeOffs/bbCodeOffsEnd set to BAD_IL_OFFSET. If a caller
8809     // puts code in the block, then it needs to update these.
8810
8811     // Insert the new block in the block list after the 'curr' block.
8812     fgInsertBBafter(curr, newBlock);
8813     fgExtendEHRegionAfter(curr); // The new block is in the same EH region as the old block.
8814
8815     // Remove flags from the old block that are no longer possible.
8816     curr->bbFlags &= ~(BBF_HAS_JMP | BBF_RETLESS_CALL);
8817
8818     // Default to fallthru, and add the arc for that.
8819     curr->bbJumpKind = BBJ_NONE;
8820     fgAddRefPred(newBlock, curr);
8821
8822     return newBlock;
8823 }
8824
8825 //------------------------------------------------------------------------------
8826 // fgSplitBlockAfterStatement - Split the given block, with all code after
8827 //                              the given statement going into the second block.
8828 //------------------------------------------------------------------------------
8829 BasicBlock* Compiler::fgSplitBlockAfterStatement(BasicBlock* curr, GenTree* stmt)
8830 {
8831     assert(!curr->IsLIR()); // No statements in LIR, so you can't use this function.
8832
8833     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
8834
8835     if (stmt)
8836     {
8837         newBlock->bbTreeList = stmt->gtNext;
8838         if (newBlock->bbTreeList)
8839         {
8840             newBlock->bbTreeList->gtPrev = curr->bbTreeList->gtPrev;
8841         }
8842         curr->bbTreeList->gtPrev = stmt;
8843         stmt->gtNext             = nullptr;
8844
8845         // Update the IL offsets of the blocks to match the split.
8846
8847         assert(newBlock->bbCodeOffs == BAD_IL_OFFSET);
8848         assert(newBlock->bbCodeOffsEnd == BAD_IL_OFFSET);
8849
8850         // curr->bbCodeOffs remains the same
8851         newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
8852
8853         IL_OFFSET splitPointILOffset = fgFindBlockILOffset(newBlock);
8854
8855         curr->bbCodeOffsEnd  = splitPointILOffset;
8856         newBlock->bbCodeOffs = splitPointILOffset;
8857     }
8858     else
8859     {
8860         assert(curr->bbTreeList == nullptr); // if no tree was given then it better be an empty block
8861     }
8862
8863     return newBlock;
8864 }
8865
8866 //------------------------------------------------------------------------------
8867 // fgSplitBlockAfterNode - Split the given block, with all code after
8868 //                         the given node going into the second block.
8869 //                         This function is only used in LIR.
8870 //------------------------------------------------------------------------------
8871 BasicBlock* Compiler::fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node)
8872 {
8873     assert(curr->IsLIR());
8874
8875     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
8876
8877     if (node != nullptr)
8878     {
8879         LIR::Range& currBBRange = LIR::AsRange(curr);
8880
8881         if (node != currBBRange.LastNode())
8882         {
8883             LIR::Range nodesToMove = currBBRange.Remove(node->gtNext, currBBRange.LastNode());
8884             LIR::AsRange(newBlock).InsertAtBeginning(std::move(nodesToMove));
8885         }
8886
8887         // Update the IL offsets of the blocks to match the split.
8888
8889         assert(newBlock->bbCodeOffs == BAD_IL_OFFSET);
8890         assert(newBlock->bbCodeOffsEnd == BAD_IL_OFFSET);
8891
8892         // curr->bbCodeOffs remains the same
8893         newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
8894
8895         // Search backwards from the end of the current block looking for the IL offset to use
8896         // for the end IL offset for the original block.
8897         IL_OFFSET                   splitPointILOffset = BAD_IL_OFFSET;
8898         LIR::Range::ReverseIterator riter;
8899         LIR::Range::ReverseIterator riterEnd;
8900         for (riter = currBBRange.rbegin(), riterEnd = currBBRange.rend(); riter != riterEnd; ++riter)
8901         {
8902             if ((*riter)->gtOper == GT_IL_OFFSET)
8903             {
8904                 GenTreeStmt* stmt = (*riter)->AsStmt();
8905                 if (stmt->gtStmtILoffsx != BAD_IL_OFFSET)
8906                 {
8907                     splitPointILOffset = jitGetILoffs(stmt->gtStmtILoffsx);
8908                     break;
8909                 }
8910             }
8911         }
8912
8913         curr->bbCodeOffsEnd = splitPointILOffset;
8914
8915         // Also use this as the beginning offset of the next block. Presumably we could/should
8916         // look to see if the first node is a GT_IL_OFFSET node, and use that instead.
8917         newBlock->bbCodeOffs = splitPointILOffset;
8918     }
8919     else
8920     {
8921         assert(curr->bbTreeList == nullptr); // if no node was given then it better be an empty block
8922     }
8923
8924     return newBlock;
8925 }
8926
8927 //------------------------------------------------------------------------------
8928 // fgSplitBlockAtBeginning - Split the given block into two blocks.
8929 //                         Control falls through from original to new block,
8930 //                         and the new block is returned.
8931 //                         All code in the original block goes into the new block
8932 //------------------------------------------------------------------------------
8933 BasicBlock* Compiler::fgSplitBlockAtBeginning(BasicBlock* curr)
8934 {
8935     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
8936
8937     newBlock->bbTreeList = curr->bbTreeList;
8938     curr->bbTreeList     = nullptr;
8939
8940     // The new block now has all the code, and the old block has none. Update the
8941     // IL offsets for the block to reflect this.
8942
8943     newBlock->bbCodeOffs    = curr->bbCodeOffs;
8944     newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
8945
8946     curr->bbCodeOffs    = BAD_IL_OFFSET;
8947     curr->bbCodeOffsEnd = BAD_IL_OFFSET;
8948
8949     return newBlock;
8950 }
8951
8952 //------------------------------------------------------------------------
8953 // fgSplitEdge: Splits the edge between a block 'curr' and its successor 'succ' by creating a new block
8954 //              that replaces 'succ' as a successor of 'curr', and which branches unconditionally
8955 //              to (or falls through to) 'succ'. Note that for a BBJ_COND block 'curr',
8956 //              'succ' might be the fall-through path or the branch path from 'curr'.
8957 //
8958 // Arguments:
8959 //    curr - A block which branches conditionally to 'succ'
8960 //    succ - The target block
8961 //
8962 // Return Value:
8963 //    Returns a new block, that is a successor of 'curr' and which branches unconditionally to 'succ'
8964 //
8965 // Assumptions:
8966 //    'curr' must have a bbJumpKind of BBJ_COND or BBJ_SWITCH
8967 //
8968 // Notes:
8969 //    The returned block is empty.
8970
8971 BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ)
8972 {
8973     assert(curr->bbJumpKind == BBJ_COND || curr->bbJumpKind == BBJ_SWITCH);
8974     assert(fgGetPredForBlock(succ, curr) != nullptr);
8975
8976     BasicBlock* newBlock;
8977     if (succ == curr->bbNext)
8978     {
8979         // The successor is the fall-through path of a BBJ_COND, or
8980         // an immediately following block of a BBJ_SWITCH (which has
8981         // no fall-through path). For this case, simply insert a new
8982         // fall-through block after 'curr'.
8983         newBlock = fgNewBBafter(BBJ_NONE, curr, true /*extendRegion*/);
8984     }
8985     else
8986     {
8987         newBlock = fgNewBBinRegion(BBJ_ALWAYS, curr, curr->isRunRarely());
8988         // The new block always jumps to 'succ'
8989         newBlock->bbJumpDest = succ;
8990     }
8991     newBlock->bbFlags |= (curr->bbFlags & succ->bbFlags & (BBF_BACKWARD_JUMP));
8992
8993     JITDUMP("Splitting edge from BB%02u to BB%02u; adding BB%02u\n", curr->bbNum, succ->bbNum, newBlock->bbNum);
8994
8995     if (curr->bbJumpKind == BBJ_COND)
8996     {
8997         fgReplacePred(succ, curr, newBlock);
8998         if (curr->bbJumpDest == succ)
8999         {
9000             // Now 'curr' jumps to newBlock
9001             curr->bbJumpDest = newBlock;
9002             newBlock->bbFlags |= BBF_JMP_TARGET;
9003         }
9004         fgAddRefPred(newBlock, curr);
9005     }
9006     else
9007     {
9008         assert(curr->bbJumpKind == BBJ_SWITCH);
9009
9010         // newBlock replaces 'succ' in the switch.
9011         fgReplaceSwitchJumpTarget(curr, newBlock, succ);
9012
9013         // And 'succ' has 'newBlock' as a new predecessor.
9014         fgAddRefPred(succ, newBlock);
9015     }
9016
9017     // This isn't accurate, but it is complex to compute a reasonable number so just assume that we take the
9018     // branch 50% of the time.
9019     newBlock->inheritWeightPercentage(curr, 50);
9020
9021     // The bbLiveIn and bbLiveOut are both equal to the bbLiveIn of 'succ'
9022     if (fgLocalVarLivenessDone)
9023     {
9024         VarSetOps::Assign(this, newBlock->bbLiveIn, succ->bbLiveIn);
9025         VarSetOps::Assign(this, newBlock->bbLiveOut, succ->bbLiveIn);
9026     }
9027
9028     return newBlock;
9029 }
9030
9031 /*****************************************************************************/
9032 /*****************************************************************************/
9033
9034 void Compiler::fgFindOperOrder()
9035 {
9036 #ifdef DEBUG
9037     if (verbose)
9038     {
9039         printf("*************** In fgFindOperOrder()\n");
9040     }
9041 #endif
9042
9043     BasicBlock*  block;
9044     GenTreeStmt* stmt;
9045
9046     /* Walk the basic blocks and for each statement determine
9047      * the evaluation order, cost, FP levels, etc... */
9048
9049     for (block = fgFirstBB; block; block = block->bbNext)
9050     {
9051         compCurBB = block;
9052         for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
9053         {
9054             /* Recursively process the statement */
9055
9056             compCurStmt = stmt;
9057             gtSetStmtInfo(stmt);
9058         }
9059     }
9060 }
9061
9062 //------------------------------------------------------------------------
9063 // fgSimpleLowering: do full walk of all IR, lowering selected operations
9064 // and computing lvaOutgoingArgumentAreaSize.
9065 //
9066 // Notes:
9067 //    Lowers GT_ARR_LENGTH, GT_ARR_BOUNDS_CHECK, and GT_SIMD_CHK.
9068 //
9069 //    For target ABIs with fixed out args area, computes upper bound on
9070 //    the size of this area from the calls in the IR.
9071 //
9072 //    Outgoing arg area size is computed here because we want to run it
9073 //    after optimization (in case calls are removed) and need to look at
9074 //    all possible calls in the method.
9075
9076 void Compiler::fgSimpleLowering()
9077 {
9078 #if FEATURE_FIXED_OUT_ARGS
9079     unsigned outgoingArgSpaceSize = 0;
9080 #endif // FEATURE_FIXED_OUT_ARGS
9081
9082     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
9083     {
9084         // Walk the statement trees in this basic block.
9085         compCurBB = block; // Used in fgRngChkTarget.
9086
9087 #ifdef LEGACY_BACKEND
9088         for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt)
9089         {
9090             for (GenTreePtr tree = stmt->gtStmtList; tree; tree = tree->gtNext)
9091             {
9092 #else
9093         LIR::Range& range             = LIR::AsRange(block);
9094         for (GenTree* tree : range)
9095         {
9096             {
9097 #endif
9098
9099                 switch (tree->OperGet())
9100                 {
9101                     case GT_ARR_LENGTH:
9102                     {
9103                         GenTreeArrLen* arrLen = tree->AsArrLen();
9104                         GenTreePtr     arr    = arrLen->gtArrLen.ArrRef();
9105                         GenTreePtr     add;
9106                         GenTreePtr     con;
9107
9108                         /* Create the expression "*(array_addr + ArrLenOffs)" */
9109
9110                         noway_assert(arr->gtNext == tree);
9111
9112                         noway_assert(arrLen->ArrLenOffset() == offsetof(CORINFO_Array, length) ||
9113                                      arrLen->ArrLenOffset() == offsetof(CORINFO_String, stringLen));
9114
9115                         if ((arr->gtOper == GT_CNS_INT) && (arr->gtIntCon.gtIconVal == 0))
9116                         {
9117                             // If the array is NULL, then we should get a NULL reference
9118                             // exception when computing its length.  We need to maintain
9119                             // an invariant where there is no sum of two constants node, so
9120                             // let's simply return an indirection of NULL.
9121
9122                             add = arr;
9123                         }
9124                         else
9125                         {
9126                             con             = gtNewIconNode(arrLen->ArrLenOffset(), TYP_I_IMPL);
9127                             con->gtRsvdRegs = RBM_NONE;
9128
9129                             add             = gtNewOperNode(GT_ADD, TYP_REF, arr, con);
9130                             add->gtRsvdRegs = arr->gtRsvdRegs;
9131
9132 #ifdef LEGACY_BACKEND
9133                             con->gtCopyFPlvl(arr);
9134
9135                             add->gtCopyFPlvl(arr);
9136                             add->CopyCosts(arr);
9137
9138                             arr->gtNext = con;
9139                             con->gtPrev = arr;
9140
9141                             con->gtNext = add;
9142                             add->gtPrev = con;
9143
9144                             add->gtNext  = tree;
9145                             tree->gtPrev = add;
9146 #else
9147                             range.InsertAfter(arr, con, add);
9148 #endif
9149                         }
9150
9151                         // Change to a GT_IND.
9152                         tree->ChangeOperUnchecked(GT_IND);
9153
9154                         tree->gtOp.gtOp1 = add;
9155                         break;
9156                     }
9157
9158                     case GT_ARR_BOUNDS_CHECK:
9159 #ifdef FEATURE_SIMD
9160                     case GT_SIMD_CHK:
9161 #endif // FEATURE_SIMD
9162                     {
9163                         // Add in a call to an error routine.
9164                         fgSetRngChkTarget(tree, false);
9165                         break;
9166                     }
9167
9168 #if FEATURE_FIXED_OUT_ARGS
9169                     case GT_CALL:
9170                     {
9171                         GenTreeCall* call = tree->AsCall();
9172                         // Fast tail calls use the caller-supplied scratch
9173                         // space so have no impact on this method's outgoing arg size.
9174                         if (!call->IsFastTailCall())
9175                         {
9176                             // Update outgoing arg size to handle this call
9177                             const unsigned thisCallOutAreaSize = call->fgArgInfo->GetOutArgSize();
9178                             assert(thisCallOutAreaSize >= MIN_ARG_AREA_FOR_CALL);
9179
9180                             if (thisCallOutAreaSize > outgoingArgSpaceSize)
9181                             {
9182                                 outgoingArgSpaceSize = thisCallOutAreaSize;
9183                                 JITDUMP("Bumping outgoingArgSpaceSize to %u for call [%06d]\n", outgoingArgSpaceSize,
9184                                         dspTreeID(tree));
9185                             }
9186                             else
9187                             {
9188                                 JITDUMP("outgoingArgSpaceSize %u sufficient for call [%06d], which needs %u\n",
9189                                         outgoingArgSpaceSize, dspTreeID(tree), thisCallOutAreaSize);
9190                             }
9191                         }
9192                         else
9193                         {
9194                             JITDUMP("outgoingArgSpaceSize not impacted by fast tail call [%06d]\n", dspTreeID(tree));
9195                         }
9196                         break;
9197                     }
9198 #endif // FEATURE_FIXED_OUT_ARGS
9199
9200                     default:
9201                     {
9202                         // No other operators need processing.
9203                         break;
9204                     }
9205                 }
9206             } // foreach gtNext
9207         }     // foreach Stmt
9208     }         // foreach BB
9209
9210 #if FEATURE_FIXED_OUT_ARGS
9211     // Finish computing the outgoing args area size
9212     //
9213     // Need to make sure the MIN_ARG_AREA_FOR_CALL space is added to the frame if:
9214     // 1. there are calls to THROW_HEPLPER methods.
9215     // 2. we are generating profiling Enter/Leave/TailCall hooks. This will ensure
9216     //    that even methods without any calls will have outgoing arg area space allocated.
9217     //
9218     // An example for these two cases is Windows Amd64, where the ABI requires to have 4 slots for
9219     // the outgoing arg space if the method makes any calls.
9220     if (outgoingArgSpaceSize < MIN_ARG_AREA_FOR_CALL)
9221     {
9222         if (compUsesThrowHelper || compIsProfilerHookNeeded())
9223         {
9224             outgoingArgSpaceSize = MIN_ARG_AREA_FOR_CALL;
9225             JITDUMP("Bumping outgoingArgSpaceSize to %u for throw helper or profile hook", outgoingArgSpaceSize);
9226         }
9227     }
9228
9229     // If a function has localloc, we will need to move the outgoing arg space when the
9230     // localloc happens. When we do this, we need to maintain stack alignment. To avoid
9231     // leaving alignment-related holes when doing this move, make sure the outgoing
9232     // argument space size is a multiple of the stack alignment by aligning up to the next
9233     // stack alignment boundary.
9234     if (compLocallocUsed)
9235     {
9236         outgoingArgSpaceSize = (unsigned)roundUp(outgoingArgSpaceSize, STACK_ALIGN);
9237         JITDUMP("Bumping outgoingArgSpaceSize to %u for localloc", outgoingArgSpaceSize);
9238     }
9239
9240     // Publish the final value and mark it as read only so any update
9241     // attempt later will cause an assert.
9242     lvaOutgoingArgSpaceSize = outgoingArgSpaceSize;
9243     lvaOutgoingArgSpaceSize.MarkAsReadOnly();
9244
9245 #endif // FEATURE_FIXED_OUT_ARGS
9246
9247 #ifdef DEBUG
9248     if (verbose && fgRngChkThrowAdded)
9249     {
9250         printf("\nAfter fgSimpleLowering() added some RngChk throw blocks");
9251         fgDispBasicBlocks();
9252         fgDispHandlerTab();
9253         printf("\n");
9254     }
9255 #endif
9256 }
9257
9258 /*****************************************************************************
9259  */
9260
9261 void Compiler::fgUpdateRefCntForClone(BasicBlock* addedToBlock, GenTreePtr clonedTree)
9262 {
9263     assert(clonedTree->gtOper != GT_STMT);
9264
9265     if (lvaLocalVarRefCounted)
9266     {
9267         compCurBB = addedToBlock;
9268         fgWalkTreePre(&clonedTree, Compiler::lvaIncRefCntsCB, (void*)this, true);
9269     }
9270 }
9271
9272 /*****************************************************************************
9273  */
9274
9275 void Compiler::fgUpdateRefCntForExtract(GenTreePtr wholeTree, GenTreePtr keptTree)
9276 {
9277     if (lvaLocalVarRefCounted)
9278     {
9279         /*  Update the refCnts of removed lcl vars - The problem is that
9280          *  we have to consider back the side effects trees so we first
9281          *  increment all refCnts for side effects then decrement everything
9282          *  in the statement
9283          */
9284         if (keptTree)
9285         {
9286             fgWalkTreePre(&keptTree, Compiler::lvaIncRefCntsCB, (void*)this, true);
9287         }
9288
9289         fgWalkTreePre(&wholeTree, Compiler::lvaDecRefCntsCB, (void*)this, true);
9290     }
9291 }
9292
9293 VARSET_VALRET_TP Compiler::fgGetVarBits(GenTreePtr tree)
9294 {
9295     VARSET_TP VARSET_INIT_NOCOPY(varBits, VarSetOps::MakeEmpty(this));
9296
9297     assert(tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_LCL_FLD || tree->gtOper == GT_REG_VAR);
9298
9299     unsigned int lclNum = tree->gtLclVarCommon.gtLclNum;
9300     LclVarDsc*   varDsc = lvaTable + lclNum;
9301     if (varDsc->lvTracked)
9302     {
9303         VarSetOps::AddElemD(this, varBits, varDsc->lvVarIndex);
9304     }
9305     else if (varDsc->lvType == TYP_STRUCT && varDsc->lvPromoted)
9306     {
9307         for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i)
9308         {
9309             noway_assert(lvaTable[i].lvIsStructField);
9310             if (lvaTable[i].lvTracked)
9311             {
9312                 unsigned varIndex = lvaTable[i].lvVarIndex;
9313                 noway_assert(varIndex < lvaTrackedCount);
9314                 VarSetOps::AddElemD(this, varBits, varIndex);
9315             }
9316         }
9317     }
9318     return varBits;
9319 }
9320
9321 /*****************************************************************************
9322  *
9323  *  Find and remove any basic blocks that are useless (e.g. they have not been
9324  *  imported because they are not reachable, or they have been optimized away).
9325  */
9326
9327 void Compiler::fgRemoveEmptyBlocks()
9328 {
9329     BasicBlock* cur;
9330     BasicBlock* nxt;
9331
9332     /* If we remove any blocks, we'll have to do additional work */
9333
9334     unsigned removedBlks = 0;
9335
9336     for (cur = fgFirstBB; cur != nullptr; cur = nxt)
9337     {
9338         /* Get hold of the next block (in case we delete 'cur') */
9339
9340         nxt = cur->bbNext;
9341
9342         /* Should this block be removed? */
9343
9344         if (!(cur->bbFlags & BBF_IMPORTED))
9345         {
9346             noway_assert(cur->isEmpty());
9347
9348             if (ehCanDeleteEmptyBlock(cur))
9349             {
9350                 /* Mark the block as removed */
9351
9352                 cur->bbFlags |= BBF_REMOVED;
9353
9354                 /* Remember that we've removed a block from the list */
9355
9356                 removedBlks++;
9357
9358 #ifdef DEBUG
9359                 if (verbose)
9360                 {
9361                     printf("BB%02u was not imported, marked as removed (%d)\n", cur->bbNum, removedBlks);
9362                 }
9363 #endif // DEBUG
9364
9365                 /* Drop the block from the list */
9366
9367                 fgUnlinkBlock(cur);
9368             }
9369             else
9370             {
9371                 // We were prevented from deleting this block by EH normalization. Mark the block as imported.
9372                 cur->bbFlags |= BBF_IMPORTED;
9373             }
9374         }
9375     }
9376
9377     /* If no blocks were removed, we're done */
9378
9379     if (removedBlks == 0)
9380     {
9381         return;
9382     }
9383
9384     /*  Update all references in the exception handler table.
9385      *  Mark the new blocks as non-removable.
9386      *
9387      *  We may have made the entire try block unreachable.
9388      *  Check for this case and remove the entry from the EH table.
9389      */
9390
9391     unsigned  XTnum;
9392     EHblkDsc* HBtab;
9393     INDEBUG(unsigned delCnt = 0;)
9394
9395     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
9396     {
9397     AGAIN:
9398         /* If the beginning of the try block was not imported, we
9399          * need to remove the entry from the EH table. */
9400
9401         if (HBtab->ebdTryBeg->bbFlags & BBF_REMOVED)
9402         {
9403             noway_assert(!(HBtab->ebdTryBeg->bbFlags & BBF_IMPORTED));
9404 #ifdef DEBUG
9405             if (verbose)
9406             {
9407                 printf("Beginning of try block (BB%02u) not imported "
9408                        "- remove index #%u from the EH table\n",
9409                        HBtab->ebdTryBeg->bbNum, XTnum + delCnt);
9410             }
9411             delCnt++;
9412 #endif // DEBUG
9413
9414             fgRemoveEHTableEntry(XTnum);
9415
9416             if (XTnum < compHndBBtabCount)
9417             {
9418                 // There are more entries left to process, so do more. Note that
9419                 // HBtab now points to the next entry, that we copied down to the
9420                 // current slot. XTnum also stays the same.
9421                 goto AGAIN;
9422             }
9423
9424             break; // no more entries (we deleted the last one), so exit the loop
9425         }
9426
9427 /* At this point we know we have a valid try block */
9428
9429 #ifdef DEBUG
9430         assert(HBtab->ebdTryBeg->bbFlags & BBF_IMPORTED);
9431         assert(HBtab->ebdTryBeg->bbFlags & BBF_DONT_REMOVE);
9432
9433         assert(HBtab->ebdHndBeg->bbFlags & BBF_IMPORTED);
9434         assert(HBtab->ebdHndBeg->bbFlags & BBF_DONT_REMOVE);
9435
9436         if (HBtab->HasFilter())
9437         {
9438             assert(HBtab->ebdFilter->bbFlags & BBF_IMPORTED);
9439             assert(HBtab->ebdFilter->bbFlags & BBF_DONT_REMOVE);
9440         }
9441 #endif // DEBUG
9442
9443         fgSkipRmvdBlocks(HBtab);
9444     } /* end of the for loop over XTnum */
9445
9446     // Renumber the basic blocks
9447     JITDUMP("\nRenumbering the basic blocks for fgRemoveEmptyBlocks\n");
9448     fgRenumberBlocks();
9449
9450 #ifdef DEBUG
9451     fgVerifyHandlerTab();
9452 #endif // DEBUG
9453 }
9454
9455 /*****************************************************************************
9456  *
9457  * Remove a useless statement from a basic block.
9458  * The default is to decrement ref counts of included vars
9459  *
9460  */
9461
9462 void Compiler::fgRemoveStmt(BasicBlock* block,
9463                             GenTreePtr  node,
9464                             // whether to decrement ref counts for tracked vars in statement
9465                             bool updateRefCount)
9466 {
9467     noway_assert(node);
9468     assert(fgOrder == FGOrderTree);
9469
9470     GenTreeStmt* tree = block->firstStmt();
9471     GenTreeStmt* stmt = node->AsStmt();
9472
9473 #ifdef DEBUG
9474     if (verbose &&
9475         stmt->gtStmtExpr->gtOper != GT_NOP) // Don't print if it is a GT_NOP. Too much noise from the inliner.
9476     {
9477         printf("\nRemoving statement ");
9478         printTreeID(stmt);
9479         printf(" in BB%02u as useless:\n", block->bbNum);
9480         gtDispTree(stmt);
9481     }
9482 #endif // DEBUG
9483
9484     if (opts.compDbgCode && stmt->gtPrev != stmt && stmt->gtStmtILoffsx != BAD_IL_OFFSET)
9485     {
9486         /* TODO: For debuggable code, should we remove significant
9487            statement boundaries. Or should we leave a GT_NO_OP in its place? */
9488     }
9489
9490     /* Is it the first statement in the list? */
9491
9492     GenTreeStmt* firstStmt = block->firstStmt();
9493     if (firstStmt == stmt)
9494     {
9495         if (firstStmt->gtNext == nullptr)
9496         {
9497             assert(firstStmt == block->lastStmt());
9498
9499             /* this is the only statement - basic block becomes empty */
9500             block->bbTreeList = nullptr;
9501         }
9502         else
9503         {
9504             block->bbTreeList         = tree->gtNext;
9505             block->bbTreeList->gtPrev = tree->gtPrev;
9506         }
9507         goto DONE;
9508     }
9509
9510     /* Is it the last statement in the list? */
9511
9512     if (stmt == block->lastStmt())
9513     {
9514         stmt->gtPrev->gtNext      = nullptr;
9515         block->bbTreeList->gtPrev = stmt->gtPrev;
9516         goto DONE;
9517     }
9518
9519     tree = stmt->gtPrevStmt;
9520     noway_assert(tree);
9521
9522     tree->gtNext         = stmt->gtNext;
9523     stmt->gtNext->gtPrev = tree;
9524
9525 DONE:
9526     fgStmtRemoved = true;
9527
9528     if (optValnumCSE_phase)
9529     {
9530         optValnumCSE_UnmarkCSEs(stmt->gtStmtExpr, nullptr);
9531     }
9532     else
9533     {
9534         if (updateRefCount)
9535         {
9536             if (fgStmtListThreaded)
9537             {
9538                 fgWalkTreePre(&stmt->gtStmtExpr, Compiler::lvaDecRefCntsCB, (void*)this, true);
9539             }
9540         }
9541     }
9542
9543 #ifdef DEBUG
9544     if (verbose)
9545     {
9546         if (block->bbTreeList == nullptr)
9547         {
9548             printf("\nBB%02u becomes empty", block->bbNum);
9549         }
9550         printf("\n");
9551     }
9552 #endif // DEBUG
9553 }
9554
9555 /******************************************************************************/
9556 // Returns true if the operator is involved in control-flow
9557 // TODO-Cleanup: Move this into genTreeKinds in genTree.h
9558
9559 inline bool OperIsControlFlow(genTreeOps oper)
9560 {
9561     switch (oper)
9562     {
9563         case GT_JTRUE:
9564         case GT_JCC:
9565         case GT_SWITCH:
9566         case GT_LABEL:
9567
9568         case GT_CALL:
9569         case GT_JMP:
9570
9571         case GT_RETURN:
9572         case GT_RETFILT:
9573 #if !FEATURE_EH_FUNCLETS
9574         case GT_END_LFIN:
9575 #endif // !FEATURE_EH_FUNCLETS
9576             return true;
9577
9578         default:
9579             return false;
9580     }
9581 }
9582
9583 /******************************************************************************
9584  *  Tries to throw away a stmt. The statement can be anywhere in block->bbTreeList.
9585  *  Returns true if it did remove the statement.
9586  */
9587
9588 bool Compiler::fgCheckRemoveStmt(BasicBlock* block, GenTreePtr node)
9589 {
9590     if (opts.compDbgCode)
9591     {
9592         return false;
9593     }
9594
9595     GenTreeStmt* stmt = node->AsStmt();
9596
9597     GenTreePtr tree = stmt->gtStmtExpr;
9598     genTreeOps oper = tree->OperGet();
9599
9600     if (OperIsControlFlow(oper) || oper == GT_NO_OP)
9601     {
9602         return false;
9603     }
9604
9605     // TODO: Use a recursive version of gtNodeHasSideEffects()
9606     if (tree->gtFlags & GTF_SIDE_EFFECT)
9607     {
9608         return false;
9609     }
9610
9611     fgRemoveStmt(block, stmt);
9612     return true;
9613 }
9614
9615 /****************************************************************************************************
9616  *
9617  *
9618  */
9619 bool Compiler::fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext)
9620 {
9621     if ((block == nullptr) || (bNext == nullptr))
9622     {
9623         return false;
9624     }
9625
9626     noway_assert(block->bbNext == bNext);
9627
9628     if (block->bbJumpKind != BBJ_NONE)
9629     {
9630         return false;
9631     }
9632
9633     // If the next block has multiple incoming edges, we can still compact if the first block is empty.
9634     // However, not if it is the beginning of a handler.
9635     if (bNext->countOfInEdges() != 1 &&
9636         (!block->isEmpty() || (block->bbFlags & BBF_FUNCLET_BEG) || (block->bbCatchTyp != BBCT_NONE)))
9637     {
9638         return false;
9639     }
9640
9641     if (bNext->bbFlags & BBF_DONT_REMOVE)
9642     {
9643         return false;
9644     }
9645
9646     // Don't compact the first block if it was specially created as a scratch block.
9647     if (fgBBisScratch(block))
9648     {
9649         return false;
9650     }
9651
9652 #if defined(_TARGET_ARM_)
9653     // We can't compact a finally target block, as we need to generate special code for such blocks during code
9654     // generation
9655     if ((bNext->bbFlags & BBF_FINALLY_TARGET) != 0)
9656         return false;
9657 #endif
9658
9659     // We don't want to compact blocks that are in different Hot/Cold regions
9660     //
9661     if (fgInDifferentRegions(block, bNext))
9662     {
9663         return false;
9664     }
9665
9666     // We cannot compact two blocks in different EH regions.
9667     //
9668     if (fgCanRelocateEHRegions)
9669     {
9670         if (!BasicBlock::sameEHRegion(block, bNext))
9671         {
9672             return false;
9673         }
9674     }
9675     // if there is a switch predecessor don't bother because we'd have to update the uniquesuccs as well
9676     // (if they are valid)
9677     for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext)
9678     {
9679         if (pred->flBlock->bbJumpKind == BBJ_SWITCH)
9680         {
9681             return false;
9682         }
9683     }
9684
9685     return true;
9686 }
9687
9688 /*****************************************************************************************************
9689  *
9690  *  Function called to compact two given blocks in the flowgraph
9691  *  Assumes that all necessary checks have been performed,
9692  *  i.e. fgCanCompactBlocks returns true.
9693  *
9694  *  Uses for this function - whenever we change links, insert blocks,...
9695  *  It will keep the flowgraph data in synch - bbNum, bbRefs, bbPreds
9696  */
9697
9698 void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext)
9699 {
9700     noway_assert(block != nullptr);
9701     noway_assert((block->bbFlags & BBF_REMOVED) == 0);
9702     noway_assert(block->bbJumpKind == BBJ_NONE);
9703
9704     noway_assert(bNext == block->bbNext);
9705     noway_assert(bNext != nullptr);
9706     noway_assert((bNext->bbFlags & BBF_REMOVED) == 0);
9707     noway_assert(bNext->countOfInEdges() == 1 || block->isEmpty());
9708     noway_assert(bNext->bbPreds);
9709
9710 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9711     noway_assert((bNext->bbFlags & BBF_FINALLY_TARGET) == 0);
9712 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9713
9714     // Make sure the second block is not the start of a TRY block or an exception handler
9715
9716     noway_assert(bNext->bbCatchTyp == BBCT_NONE);
9717     noway_assert((bNext->bbFlags & BBF_TRY_BEG) == 0);
9718     noway_assert((bNext->bbFlags & BBF_DONT_REMOVE) == 0);
9719
9720     /* both or none must have an exception handler */
9721     noway_assert(block->hasTryIndex() == bNext->hasTryIndex());
9722
9723 #ifdef DEBUG
9724     if (verbose)
9725     {
9726         printf("\nCompacting blocks BB%02u and BB%02u:\n", block->bbNum, bNext->bbNum);
9727     }
9728 #endif
9729
9730     if (bNext->countOfInEdges() > 1)
9731     {
9732         JITDUMP("Second block has multiple incoming edges\n");
9733
9734         assert(block->isEmpty());
9735         block->bbFlags |= BBF_JMP_TARGET;
9736         for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext)
9737         {
9738             fgReplaceJumpTarget(pred->flBlock, block, bNext);
9739
9740             if (pred->flBlock != block)
9741             {
9742                 fgAddRefPred(block, pred->flBlock);
9743             }
9744         }
9745         bNext->bbPreds = nullptr;
9746     }
9747     else
9748     {
9749         noway_assert(bNext->bbPreds->flNext == nullptr);
9750         noway_assert(bNext->bbPreds->flBlock == block);
9751     }
9752
9753     /* Start compacting - move all the statements in the second block to the first block */
9754
9755     // First move any phi definitions of the second block after the phi defs of the first.
9756     // TODO-CQ: This may be the wrong thing to do.  If we're compacting blocks, it's because a
9757     // control-flow choice was constant-folded away.  So probably phi's need to go away,
9758     // as well, in favor of one of the incoming branches.  Or at least be modified.
9759
9760     assert(block->IsLIR() == bNext->IsLIR());
9761     if (block->IsLIR())
9762     {
9763         LIR::Range& blockRange = LIR::AsRange(block);
9764         LIR::Range& nextRange  = LIR::AsRange(bNext);
9765
9766         // Does the next block have any phis?
9767         GenTree*           nextFirstNonPhi = nullptr;
9768         LIR::ReadOnlyRange nextPhis        = nextRange.PhiNodes();
9769         if (!nextPhis.IsEmpty())
9770         {
9771             GenTree* blockLastPhi = blockRange.LastPhiNode();
9772             nextFirstNonPhi       = nextPhis.LastNode()->gtNext;
9773
9774             LIR::Range phisToMove = nextRange.Remove(std::move(nextPhis));
9775             blockRange.InsertAfter(blockLastPhi, std::move(phisToMove));
9776         }
9777         else
9778         {
9779             nextFirstNonPhi = nextRange.FirstNode();
9780         }
9781
9782         // Does the block have any other code?
9783         if (nextFirstNonPhi != nullptr)
9784         {
9785             LIR::Range nextNodes = nextRange.Remove(nextFirstNonPhi, nextRange.LastNode());
9786             blockRange.InsertAtEnd(std::move(nextNodes));
9787         }
9788     }
9789     else
9790     {
9791         GenTreePtr blkNonPhi1   = block->FirstNonPhiDef();
9792         GenTreePtr bNextNonPhi1 = bNext->FirstNonPhiDef();
9793         GenTreePtr blkFirst     = block->firstStmt();
9794         GenTreePtr bNextFirst   = bNext->firstStmt();
9795
9796         // Does the second have any phis?
9797         if (bNextFirst != nullptr && bNextFirst != bNextNonPhi1)
9798         {
9799             GenTreePtr bNextLast = bNextFirst->gtPrev;
9800             assert(bNextLast->gtNext == nullptr);
9801
9802             // Does "blk" have phis?
9803             if (blkNonPhi1 != blkFirst)
9804             {
9805                 // Yes, has phis.
9806                 // Insert after the last phi of "block."
9807                 // First, bNextPhis after last phi of block.
9808                 GenTreePtr blkLastPhi;
9809                 if (blkNonPhi1 != nullptr)
9810                 {
9811                     blkLastPhi = blkNonPhi1->gtPrev;
9812                 }
9813                 else
9814                 {
9815                     blkLastPhi = blkFirst->gtPrev;
9816                 }
9817
9818                 blkLastPhi->gtNext = bNextFirst;
9819                 bNextFirst->gtPrev = blkLastPhi;
9820
9821                 // Now, rest of "block" after last phi of "bNext".
9822                 GenTreePtr bNextLastPhi = nullptr;
9823                 if (bNextNonPhi1 != nullptr)
9824                 {
9825                     bNextLastPhi = bNextNonPhi1->gtPrev;
9826                 }
9827                 else
9828                 {
9829                     bNextLastPhi = bNextFirst->gtPrev;
9830                 }
9831
9832                 bNextLastPhi->gtNext = blkNonPhi1;
9833                 if (blkNonPhi1 != nullptr)
9834                 {
9835                     blkNonPhi1->gtPrev = bNextLastPhi;
9836                 }
9837                 else
9838                 {
9839                     // block has no non phis, so make the last statement be the last added phi.
9840                     blkFirst->gtPrev = bNextLastPhi;
9841                 }
9842
9843                 // Now update the bbTreeList of "bNext".
9844                 bNext->bbTreeList = bNextNonPhi1;
9845                 if (bNextNonPhi1 != nullptr)
9846                 {
9847                     bNextNonPhi1->gtPrev = bNextLast;
9848                 }
9849             }
9850             else
9851             {
9852                 if (blkFirst != nullptr) // If "block" has no statements, fusion will work fine...
9853                 {
9854                     // First, bNextPhis at start of block.
9855                     GenTreePtr blkLast = blkFirst->gtPrev;
9856                     block->bbTreeList  = bNextFirst;
9857                     // Now, rest of "block" (if it exists) after last phi of "bNext".
9858                     GenTreePtr bNextLastPhi = nullptr;
9859                     if (bNextNonPhi1 != nullptr)
9860                     {
9861                         // There is a first non phi, so the last phi is before it.
9862                         bNextLastPhi = bNextNonPhi1->gtPrev;
9863                     }
9864                     else
9865                     {
9866                         // All the statements are phi defns, so the last one is the prev of the first.
9867                         bNextLastPhi = bNextFirst->gtPrev;
9868                     }
9869                     bNextFirst->gtPrev   = blkLast;
9870                     bNextLastPhi->gtNext = blkFirst;
9871                     blkFirst->gtPrev     = bNextLastPhi;
9872                     // Now update the bbTreeList of "bNext"
9873                     bNext->bbTreeList = bNextNonPhi1;
9874                     if (bNextNonPhi1 != nullptr)
9875                     {
9876                         bNextNonPhi1->gtPrev = bNextLast;
9877                     }
9878                 }
9879             }
9880         }
9881
9882         // Now proceed with the updated bbTreeLists.
9883         GenTreePtr stmtList1 = block->firstStmt();
9884         GenTreePtr stmtList2 = bNext->firstStmt();
9885
9886         /* the block may have an empty list */
9887
9888         if (stmtList1)
9889         {
9890             GenTreePtr stmtLast1 = block->lastStmt();
9891
9892             /* The second block may be a GOTO statement or something with an empty bbTreeList */
9893             if (stmtList2)
9894             {
9895                 GenTreePtr stmtLast2 = bNext->lastStmt();
9896
9897                 /* append list2 to list 1 */
9898
9899                 stmtLast1->gtNext = stmtList2;
9900                 stmtList2->gtPrev = stmtLast1;
9901                 stmtList1->gtPrev = stmtLast2;
9902             }
9903         }
9904         else
9905         {
9906             /* block was formerly empty and now has bNext's statements */
9907             block->bbTreeList = stmtList2;
9908         }
9909     }
9910
9911     // Note we could update the local variable weights here by
9912     // calling lvaMarkLocalVars, with the block and weight adjustment.
9913
9914     // If either block or bNext has a profile weight
9915     // or if both block and bNext have non-zero weights
9916     // then we select the highest weight block.
9917
9918     if (block->hasProfileWeight() || bNext->hasProfileWeight() || (block->bbWeight && bNext->bbWeight))
9919     {
9920         // We are keeping block so update its fields
9921         // when bNext has a greater weight
9922
9923         if (block->bbWeight < bNext->bbWeight)
9924         {
9925             block->bbWeight = bNext->bbWeight;
9926
9927             block->bbFlags |= (bNext->bbFlags & BBF_PROF_WEIGHT); // Set the profile weight flag (if necessary)
9928             if (block->bbWeight != 0)
9929             {
9930                 block->bbFlags &= ~BBF_RUN_RARELY; // Clear any RarelyRun flag
9931             }
9932         }
9933     }
9934     // otherwise if either block has a zero weight we select the zero weight
9935     else
9936     {
9937         noway_assert((block->bbWeight == BB_ZERO_WEIGHT) || (bNext->bbWeight == BB_ZERO_WEIGHT));
9938         block->bbWeight = BB_ZERO_WEIGHT;
9939         block->bbFlags |= BBF_RUN_RARELY; // Set the RarelyRun flag
9940     }
9941
9942     /* set the right links */
9943
9944     block->bbJumpKind = bNext->bbJumpKind;
9945     VarSetOps::AssignAllowUninitRhs(this, block->bbLiveOut, bNext->bbLiveOut);
9946
9947     // Update the beginning and ending IL offsets (bbCodeOffs and bbCodeOffsEnd).
9948     // Set the beginning IL offset to the minimum, and the ending offset to the maximum, of the respective blocks.
9949     // If one block has an unknown offset, we take the other block.
9950     // We are merging into 'block', so if its values are correct, just leave them alone.
9951     // TODO: we should probably base this on the statements within.
9952
9953     if (block->bbCodeOffs == BAD_IL_OFFSET)
9954     {
9955         block->bbCodeOffs = bNext->bbCodeOffs; // If they are both BAD_IL_OFFSET, this doesn't change anything.
9956     }
9957     else if (bNext->bbCodeOffs != BAD_IL_OFFSET)
9958     {
9959         // The are both valid offsets; compare them.
9960         if (block->bbCodeOffs > bNext->bbCodeOffs)
9961         {
9962             block->bbCodeOffs = bNext->bbCodeOffs;
9963         }
9964     }
9965
9966     if (block->bbCodeOffsEnd == BAD_IL_OFFSET)
9967     {
9968         block->bbCodeOffsEnd = bNext->bbCodeOffsEnd; // If they are both BAD_IL_OFFSET, this doesn't change anything.
9969     }
9970     else if (bNext->bbCodeOffsEnd != BAD_IL_OFFSET)
9971     {
9972         // The are both valid offsets; compare them.
9973         if (block->bbCodeOffsEnd < bNext->bbCodeOffsEnd)
9974         {
9975             block->bbCodeOffsEnd = bNext->bbCodeOffsEnd;
9976         }
9977     }
9978
9979     if (((block->bbFlags & BBF_INTERNAL) != 0) && ((bNext->bbFlags & BBF_INTERNAL) == 0))
9980     {
9981         // If 'block' is an internal block and 'bNext' isn't, then adjust the flags set on 'block'.
9982         block->bbFlags &= ~BBF_INTERNAL; // Clear the BBF_INTERNAL flag
9983         block->bbFlags |= BBF_IMPORTED;  // Set the BBF_IMPORTED flag
9984     }
9985
9986     /* Update the flags for block with those found in bNext */
9987
9988     block->bbFlags |= (bNext->bbFlags & BBF_COMPACT_UPD);
9989
9990     /* mark bNext as removed */
9991
9992     bNext->bbFlags |= BBF_REMOVED;
9993
9994     /* Unlink bNext and update all the marker pointers if necessary */
9995
9996     fgUnlinkRange(block->bbNext, bNext);
9997
9998     // If bNext was the last block of a try or handler, update the EH table.
9999
10000     ehUpdateForDeletedBlock(bNext);
10001
10002     /* If we're collapsing a block created after the dominators are
10003        computed, rename the block and reuse dominator information from
10004        the other block */
10005     if (fgDomsComputed && block->bbNum > fgDomBBcount)
10006     {
10007         BlockSetOps::Assign(this, block->bbReach, bNext->bbReach);
10008         BlockSetOps::ClearD(this, bNext->bbReach);
10009
10010         block->bbIDom = bNext->bbIDom;
10011         bNext->bbIDom = nullptr;
10012
10013         // In this case, there's no need to update the preorder and postorder numbering
10014         // since we're changing the bbNum, this makes the basic block all set.
10015         block->bbNum = bNext->bbNum;
10016     }
10017
10018     /* Set the jump targets */
10019
10020     switch (bNext->bbJumpKind)
10021     {
10022         case BBJ_CALLFINALLY:
10023             // Propagate RETLESS property
10024             block->bbFlags |= (bNext->bbFlags & BBF_RETLESS_CALL);
10025
10026             __fallthrough;
10027
10028         case BBJ_COND:
10029         case BBJ_ALWAYS:
10030         case BBJ_EHCATCHRET:
10031             block->bbJumpDest = bNext->bbJumpDest;
10032
10033             /* Update the predecessor list for 'bNext->bbJumpDest' */
10034             fgReplacePred(bNext->bbJumpDest, bNext, block);
10035
10036             /* Update the predecessor list for 'bNext->bbNext' if it is different than 'bNext->bbJumpDest' */
10037             if (bNext->bbJumpKind == BBJ_COND && bNext->bbJumpDest != bNext->bbNext)
10038             {
10039                 fgReplacePred(bNext->bbNext, bNext, block);
10040             }
10041             break;
10042
10043         case BBJ_NONE:
10044             /* Update the predecessor list for 'bNext->bbNext' */
10045             fgReplacePred(bNext->bbNext, bNext, block);
10046             break;
10047
10048         case BBJ_EHFILTERRET:
10049             fgReplacePred(bNext->bbJumpDest, bNext, block);
10050             break;
10051
10052         case BBJ_EHFINALLYRET:
10053         {
10054             unsigned  hndIndex = block->getHndIndex();
10055             EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
10056
10057             if (ehDsc->HasFinallyHandler()) // No need to do this for fault handlers
10058             {
10059                 BasicBlock* begBlk;
10060                 BasicBlock* endBlk;
10061                 ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
10062
10063                 BasicBlock* finBeg = ehDsc->ebdHndBeg;
10064
10065                 for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
10066                 {
10067                     if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
10068                     {
10069                         continue;
10070                     }
10071
10072                     noway_assert(bcall->isBBCallAlwaysPair());
10073                     fgReplacePred(bcall->bbNext, bNext, block);
10074                 }
10075             }
10076         }
10077         break;
10078
10079         case BBJ_THROW:
10080         case BBJ_RETURN:
10081             /* no jumps or fall through blocks to set here */
10082             break;
10083
10084         case BBJ_SWITCH:
10085             block->bbJumpSwt = bNext->bbJumpSwt;
10086             // We are moving the switch jump from bNext to block.  Examine the jump targets
10087             // of the BBJ_SWITCH at bNext and replace the predecessor to 'bNext' with ones to 'block'
10088             fgChangeSwitchBlock(bNext, block);
10089             break;
10090
10091         default:
10092             noway_assert(!"Unexpected bbJumpKind");
10093             break;
10094     }
10095
10096     fgUpdateLoopsAfterCompacting(block, bNext);
10097
10098 #if DEBUG
10099     if (verbose && 0)
10100     {
10101         printf("\nAfter compacting:\n");
10102         fgDispBasicBlocks(false);
10103     }
10104 #endif
10105
10106 #if DEBUG
10107     if (JitConfig.JitSlowDebugChecksEnabled() != 0)
10108     {
10109         // Make sure that the predecessor lists are accurate
10110         fgDebugCheckBBlist();
10111     }
10112 #endif // DEBUG
10113 }
10114
10115 void Compiler::fgUpdateLoopsAfterCompacting(BasicBlock* block, BasicBlock* bNext)
10116 {
10117     /* Check if the removed block is not part the loop table */
10118     noway_assert(bNext);
10119
10120     for (unsigned loopNum = 0; loopNum < optLoopCount; loopNum++)
10121     {
10122         /* Some loops may have been already removed by
10123          * loop unrolling or conditional folding */
10124
10125         if (optLoopTable[loopNum].lpFlags & LPFLG_REMOVED)
10126         {
10127             continue;
10128         }
10129
10130         /* Check the loop head (i.e. the block preceding the loop) */
10131
10132         if (optLoopTable[loopNum].lpHead == bNext)
10133         {
10134             optLoopTable[loopNum].lpHead = block;
10135         }
10136
10137         /* Check the loop bottom */
10138
10139         if (optLoopTable[loopNum].lpBottom == bNext)
10140         {
10141             optLoopTable[loopNum].lpBottom = block;
10142         }
10143
10144         /* Check the loop exit */
10145
10146         if (optLoopTable[loopNum].lpExit == bNext)
10147         {
10148             noway_assert(optLoopTable[loopNum].lpExitCnt == 1);
10149             optLoopTable[loopNum].lpExit = block;
10150         }
10151
10152         /* Check the loop entry */
10153
10154         if (optLoopTable[loopNum].lpEntry == bNext)
10155         {
10156             optLoopTable[loopNum].lpEntry = block;
10157         }
10158     }
10159 }
10160
10161 /*****************************************************************************************************
10162  *
10163  *  Function called to remove a block when it is unreachable.
10164  *
10165  *  This function cannot remove the first block.
10166  */
10167
10168 void Compiler::fgUnreachableBlock(BasicBlock* block)
10169 {
10170     // genReturnBB should never be removed, as we might have special hookups there.
10171     // Therefore, we should never come here to remove the statements in the genReturnBB block.
10172     // For example, <BUGNUM> in VSW 364383, </BUGNUM>
10173     // the profiler hookup needs to have the "void GT_RETURN" statement
10174     // to properly set the info.compProfilerCallback flag.
10175     noway_assert(block != genReturnBB);
10176
10177     if (block->bbFlags & BBF_REMOVED)
10178     {
10179         return;
10180     }
10181
10182 /* Removing an unreachable block */
10183
10184 #ifdef DEBUG
10185     if (verbose)
10186     {
10187         printf("\nRemoving unreachable BB%02u\n", block->bbNum);
10188     }
10189 #endif // DEBUG
10190
10191     noway_assert(block->bbPrev != nullptr); // Can use this function to remove the first block
10192
10193 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10194     assert(!block->bbPrev->isBBCallAlwaysPair()); // can't remove the BBJ_ALWAYS of a BBJ_CALLFINALLY / BBJ_ALWAYS pair
10195 #endif                                            // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10196
10197     /* First walk the statement trees in this basic block and delete each stmt */
10198
10199     /* Make the block publicly available */
10200     compCurBB = block;
10201
10202     if (block->IsLIR())
10203     {
10204         LIR::Range& blockRange = LIR::AsRange(block);
10205         if (!blockRange.IsEmpty())
10206         {
10207             blockRange.Delete(this, block, blockRange.FirstNode(), blockRange.LastNode());
10208         }
10209     }
10210     else
10211     {
10212         // TODO-Cleanup: I'm not sure why this happens -- if the block is unreachable, why does it have phis?
10213         // Anyway, remove any phis.
10214
10215         GenTreePtr firstNonPhi = block->FirstNonPhiDef();
10216         if (block->bbTreeList != firstNonPhi)
10217         {
10218             if (firstNonPhi != nullptr)
10219             {
10220                 firstNonPhi->gtPrev = block->lastStmt();
10221             }
10222             block->bbTreeList = firstNonPhi;
10223         }
10224
10225         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
10226         {
10227             fgRemoveStmt(block, stmt);
10228         }
10229         noway_assert(block->bbTreeList == nullptr);
10230     }
10231
10232     /* Next update the loop table and bbWeights */
10233     optUpdateLoopsBeforeRemoveBlock(block);
10234
10235     /* Mark the block as removed */
10236     block->bbFlags |= BBF_REMOVED;
10237
10238     /* update bbRefs and bbPreds for the blocks reached by this block */
10239     fgRemoveBlockAsPred(block);
10240 }
10241
10242 /*****************************************************************************************************
10243  *
10244  *  Function called to remove or morph a jump when we jump to the same
10245  *  block when both the condition is true or false.
10246  */
10247 void Compiler::fgRemoveConditionalJump(BasicBlock* block)
10248 {
10249     noway_assert(block->bbJumpKind == BBJ_COND && block->bbJumpDest == block->bbNext);
10250     assert(compRationalIRForm == block->IsLIR());
10251
10252     flowList* flow = fgGetPredForBlock(block->bbNext, block);
10253     noway_assert(flow->flDupCount == 2);
10254
10255     // Change the BBJ_COND to BBJ_NONE, and adjust the refCount and dupCount.
10256     block->bbJumpKind = BBJ_NONE;
10257     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
10258     --block->bbNext->bbRefs;
10259     --flow->flDupCount;
10260
10261 #ifdef DEBUG
10262     block->bbJumpDest = nullptr;
10263     if (verbose)
10264     {
10265         printf("Block BB%02u becoming a BBJ_NONE to BB%02u (jump target is the same whether the condition is true or "
10266                "false)\n",
10267                block->bbNum, block->bbNext->bbNum);
10268     }
10269 #endif
10270
10271     /* Remove the block jump condition */
10272
10273     if (block->IsLIR())
10274     {
10275         LIR::Range& blockRange = LIR::AsRange(block);
10276
10277         GenTree* test = blockRange.LastNode();
10278         assert(test->OperIsConditionalJump());
10279
10280         bool               isClosed;
10281         unsigned           sideEffects;
10282         LIR::ReadOnlyRange testRange = blockRange.GetTreeRange(test, &isClosed, &sideEffects);
10283
10284         // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable
10285         //            diffs compared to the existing backend.
10286         if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0))
10287         {
10288             // If the jump and its operands form a contiguous, side-effect-free range,
10289             // remove them.
10290             blockRange.Delete(this, block, std::move(testRange));
10291         }
10292         else
10293         {
10294             // Otherwise, just remove the jump node itself.
10295             blockRange.Remove(test);
10296         }
10297     }
10298     else
10299     {
10300         GenTreeStmt* test = block->lastStmt();
10301         GenTree*     tree = test->gtStmtExpr;
10302
10303         noway_assert(tree->gtOper == GT_JTRUE);
10304
10305         GenTree* sideEffList = nullptr;
10306
10307         if (tree->gtFlags & GTF_SIDE_EFFECT)
10308         {
10309             gtExtractSideEffList(tree, &sideEffList);
10310
10311             if (sideEffList)
10312             {
10313                 noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
10314 #ifdef DEBUG
10315                 if (verbose)
10316                 {
10317                     printf("Extracted side effects list from condition...\n");
10318                     gtDispTree(sideEffList);
10319                     printf("\n");
10320                 }
10321 #endif
10322             }
10323         }
10324
10325         // Delete the cond test or replace it with the side effect tree
10326         if (sideEffList == nullptr)
10327         {
10328             fgRemoveStmt(block, test);
10329         }
10330         else
10331         {
10332             test->gtStmtExpr = sideEffList;
10333
10334             fgMorphBlockStmt(block, test DEBUGARG("fgRemoveConditionalJump"));
10335         }
10336     }
10337 }
10338
10339 /*****************************************************************************************************
10340  *
10341  *  Function to return the last basic block in the main part of the function. With funclets, it is
10342  *  the block immediately before the first funclet.
10343  *  An inclusive end of the main method.
10344  */
10345
10346 BasicBlock* Compiler::fgLastBBInMainFunction()
10347 {
10348 #if FEATURE_EH_FUNCLETS
10349
10350     if (fgFirstFuncletBB != nullptr)
10351     {
10352         return fgFirstFuncletBB->bbPrev;
10353     }
10354
10355 #endif // FEATURE_EH_FUNCLETS
10356
10357     assert(fgLastBB->bbNext == nullptr);
10358
10359     return fgLastBB;
10360 }
10361
10362 /*****************************************************************************************************
10363  *
10364  *  Function to return the first basic block after the main part of the function. With funclets, it is
10365  *  the block of the first funclet.  Otherwise it is NULL if there are no funclets (fgLastBB->bbNext).
10366  *  This is equivalent to fgLastBBInMainFunction()->bbNext
10367  *  An exclusive end of the main method.
10368  */
10369
10370 BasicBlock* Compiler::fgEndBBAfterMainFunction()
10371 {
10372 #if FEATURE_EH_FUNCLETS
10373
10374     if (fgFirstFuncletBB != nullptr)
10375     {
10376         return fgFirstFuncletBB;
10377     }
10378
10379 #endif // FEATURE_EH_FUNCLETS
10380
10381     assert(fgLastBB->bbNext == nullptr);
10382
10383     return nullptr;
10384 }
10385
10386 // Removes the block from the bbPrev/bbNext chain
10387 // Updates fgFirstBB and fgLastBB if necessary
10388 // Does not update fgFirstFuncletBB or fgFirstColdBlock (fgUnlinkRange does)
10389
10390 void Compiler::fgUnlinkBlock(BasicBlock* block)
10391 {
10392     if (block->bbPrev)
10393     {
10394         block->bbPrev->bbNext = block->bbNext;
10395         if (block->bbNext)
10396         {
10397             block->bbNext->bbPrev = block->bbPrev;
10398         }
10399         else
10400         {
10401             fgLastBB = block->bbPrev;
10402         }
10403     }
10404     else
10405     {
10406         assert(block == fgFirstBB);
10407         assert(block != fgLastBB);
10408         assert((fgFirstBBScratch == nullptr) || (fgFirstBBScratch == fgFirstBB));
10409
10410         fgFirstBB         = block->bbNext;
10411         fgFirstBB->bbPrev = nullptr;
10412
10413         if (fgFirstBBScratch != nullptr)
10414         {
10415 #ifdef DEBUG
10416             // We had created an initial scratch BB, but now we're deleting it.
10417             if (verbose)
10418             {
10419                 printf("Unlinking scratch BB%02u\n", block->bbNum);
10420             }
10421 #endif // DEBUG
10422             fgFirstBBScratch = nullptr;
10423         }
10424     }
10425 }
10426
10427 /*****************************************************************************************************
10428  *
10429  *  Function called to unlink basic block range [bBeg .. bEnd] from the basic block list.
10430  *
10431  *  'bBeg' can't be the first block.
10432  */
10433
10434 void Compiler::fgUnlinkRange(BasicBlock* bBeg, BasicBlock* bEnd)
10435 {
10436     assert(bBeg != nullptr);
10437     assert(bEnd != nullptr);
10438
10439     BasicBlock* bPrev = bBeg->bbPrev;
10440     assert(bPrev != nullptr); // Can't unlink a range starting with the first block
10441
10442     bPrev->setNext(bEnd->bbNext);
10443
10444     /* If we removed the last block in the method then update fgLastBB */
10445     if (fgLastBB == bEnd)
10446     {
10447         fgLastBB = bPrev;
10448         noway_assert(fgLastBB->bbNext == nullptr);
10449     }
10450
10451     // If bEnd was the first Cold basic block update fgFirstColdBlock
10452     if (fgFirstColdBlock == bEnd)
10453     {
10454         fgFirstColdBlock = bPrev->bbNext;
10455     }
10456
10457 #if FEATURE_EH_FUNCLETS
10458 #ifdef DEBUG
10459     // You can't unlink a range that includes the first funclet block. A range certainly
10460     // can't cross the non-funclet/funclet region. And you can't unlink the first block
10461     // of the first funclet with this, either. (If that's necessary, it could be allowed
10462     // by updating fgFirstFuncletBB to bEnd->bbNext.)
10463     for (BasicBlock* tempBB = bBeg; tempBB != bEnd->bbNext; tempBB = tempBB->bbNext)
10464     {
10465         assert(tempBB != fgFirstFuncletBB);
10466     }
10467 #endif // DEBUG
10468 #endif // FEATURE_EH_FUNCLETS
10469 }
10470
10471 /*****************************************************************************************************
10472  *
10473  *  Function called to remove a basic block
10474  */
10475
10476 void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable)
10477 {
10478     BasicBlock* bPrev = block->bbPrev;
10479
10480     /* The block has to be either unreachable or empty */
10481
10482     PREFIX_ASSUME(block != nullptr);
10483
10484     JITDUMP("fgRemoveBlock BB%02u\n", block->bbNum);
10485
10486     // If we've cached any mappings from switch blocks to SwitchDesc's (which contain only the
10487     // *unique* successors of the switch block), invalidate that cache, since an entry in one of
10488     // the SwitchDescs might be removed.
10489     InvalidateUniqueSwitchSuccMap();
10490
10491     noway_assert((block == fgFirstBB) || (bPrev && (bPrev->bbNext == block)));
10492     noway_assert(!(block->bbFlags & BBF_DONT_REMOVE));
10493
10494     // Should never remove a genReturnBB, as we might have special hookups there.
10495     noway_assert(block != genReturnBB);
10496
10497 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10498     // Don't remove a finally target
10499     assert(!(block->bbFlags & BBF_FINALLY_TARGET));
10500 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10501
10502     if (unreachable)
10503     {
10504         PREFIX_ASSUME(bPrev != nullptr);
10505
10506         fgUnreachableBlock(block);
10507
10508         /* If this is the last basic block update fgLastBB */
10509         if (block == fgLastBB)
10510         {
10511             fgLastBB = bPrev;
10512         }
10513
10514 #if FEATURE_EH_FUNCLETS
10515         // If block was the fgFirstFuncletBB then set fgFirstFuncletBB to block->bbNext
10516         if (block == fgFirstFuncletBB)
10517         {
10518             fgFirstFuncletBB = block->bbNext;
10519         }
10520 #endif // FEATURE_EH_FUNCLETS
10521
10522         if (bPrev->bbJumpKind == BBJ_CALLFINALLY)
10523         {
10524             // bPrev CALL becomes RETLESS as the BBJ_ALWAYS block is unreachable
10525             bPrev->bbFlags |= BBF_RETLESS_CALL;
10526
10527 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10528             NO_WAY("No retless call finally blocks; need unwind target instead");
10529 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10530         }
10531         else if (bPrev->bbJumpKind == BBJ_ALWAYS && bPrev->bbJumpDest == block->bbNext &&
10532                  !(bPrev->bbFlags & BBF_KEEP_BBJ_ALWAYS) && (block != fgFirstColdBlock) &&
10533                  (block->bbNext != fgFirstColdBlock))
10534         {
10535             // previous block is a BBJ_ALWAYS to the next block: change to BBJ_NONE.
10536             // Note that we don't do it if bPrev follows a BBJ_CALLFINALLY block (BBF_KEEP_BBJ_ALWAYS),
10537             // because that would violate our invariant that BBJ_CALLFINALLY blocks are followed by
10538             // BBJ_ALWAYS blocks.
10539             bPrev->bbJumpKind = BBJ_NONE;
10540             bPrev->bbFlags &= ~BBF_NEEDS_GCPOLL;
10541         }
10542
10543         // If this is the first Cold basic block update fgFirstColdBlock
10544         if (block == fgFirstColdBlock)
10545         {
10546             fgFirstColdBlock = block->bbNext;
10547         }
10548
10549         /* Unlink this block from the bbNext chain */
10550         fgUnlinkBlock(block);
10551
10552         /* At this point the bbPreds and bbRefs had better be zero */
10553         noway_assert((block->bbRefs == 0) && (block->bbPreds == nullptr));
10554
10555         /*  A BBJ_CALLFINALLY is usually paired with a BBJ_ALWAYS.
10556          *  If we delete such a BBJ_CALLFINALLY we also delete the BBJ_ALWAYS
10557          */
10558         if (block->isBBCallAlwaysPair())
10559         {
10560             BasicBlock* leaveBlk = block->bbNext;
10561             noway_assert(leaveBlk->bbJumpKind == BBJ_ALWAYS);
10562
10563             leaveBlk->bbFlags &= ~BBF_DONT_REMOVE;
10564             leaveBlk->bbRefs  = 0;
10565             leaveBlk->bbPreds = nullptr;
10566
10567             fgRemoveBlock(leaveBlk, true);
10568
10569 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10570             fgClearFinallyTargetBit(leaveBlk->bbJumpDest);
10571 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10572         }
10573         else if (block->bbJumpKind == BBJ_RETURN)
10574         {
10575             fgRemoveReturnBlock(block);
10576         }
10577     }
10578     else // block is empty
10579     {
10580         noway_assert(block->isEmpty());
10581
10582         /* The block cannot follow a non-retless BBJ_CALLFINALLY (because we don't know who may jump to it) */
10583         noway_assert((bPrev == nullptr) || !bPrev->isBBCallAlwaysPair());
10584
10585         /* This cannot be the last basic block */
10586         noway_assert(block != fgLastBB);
10587
10588 #ifdef DEBUG
10589         if (verbose)
10590         {
10591             printf("Removing empty BB%02u\n", block->bbNum);
10592         }
10593 #endif // DEBUG
10594
10595 #ifdef DEBUG
10596         /* Some extra checks for the empty case */
10597
10598         switch (block->bbJumpKind)
10599         {
10600             case BBJ_NONE:
10601                 break;
10602
10603             case BBJ_ALWAYS:
10604                 /* Do not remove a block that jumps to itself - used for while (true){} */
10605                 noway_assert(block->bbJumpDest != block);
10606
10607                 /* Empty GOTO can be removed iff bPrev is BBJ_NONE */
10608                 noway_assert(bPrev && bPrev->bbJumpKind == BBJ_NONE);
10609                 break;
10610
10611             default:
10612                 noway_assert(!"Empty block of this type cannot be removed!");
10613                 break;
10614         }
10615 #endif // DEBUG
10616
10617         noway_assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS);
10618
10619         /* Who is the "real" successor of this block? */
10620
10621         BasicBlock* succBlock;
10622
10623         if (block->bbJumpKind == BBJ_ALWAYS)
10624         {
10625             succBlock = block->bbJumpDest;
10626         }
10627         else
10628         {
10629             succBlock = block->bbNext;
10630         }
10631
10632         bool skipUnmarkLoop = false;
10633
10634         // If block is the backedge for a loop and succBlock precedes block
10635         // then the succBlock becomes the new LOOP HEAD
10636         // NOTE: there's an assumption here that the blocks are numbered in increasing bbNext order.
10637         // NOTE 2: if fgDomsComputed is false, then we can't check reachability. However, if this is
10638         // the case, then the loop structures probably are also invalid, and shouldn't be used. This
10639         // can be the case late in compilation (such as Lower), where remnants of earlier created
10640         // structures exist, but haven't been maintained.
10641         if (block->isLoopHead() && (succBlock->bbNum <= block->bbNum))
10642         {
10643             succBlock->bbFlags |= BBF_LOOP_HEAD;
10644             if (fgDomsComputed && fgReachable(succBlock, block))
10645             {
10646                 /* Mark all the reachable blocks between 'succBlock' and 'block', excluding 'block' */
10647                 optMarkLoopBlocks(succBlock, block, true);
10648             }
10649         }
10650         else if (succBlock->isLoopHead() && bPrev && (succBlock->bbNum <= bPrev->bbNum))
10651         {
10652             skipUnmarkLoop = true;
10653         }
10654
10655         noway_assert(succBlock);
10656
10657         // If this is the first Cold basic block update fgFirstColdBlock
10658         if (block == fgFirstColdBlock)
10659         {
10660             fgFirstColdBlock = block->bbNext;
10661         }
10662
10663 #if FEATURE_EH_FUNCLETS
10664         // Update fgFirstFuncletBB if necessary
10665         if (block == fgFirstFuncletBB)
10666         {
10667             fgFirstFuncletBB = block->bbNext;
10668         }
10669 #endif // FEATURE_EH_FUNCLETS
10670
10671         /* First update the loop table and bbWeights */
10672         optUpdateLoopsBeforeRemoveBlock(block, skipUnmarkLoop);
10673
10674         /* Remove the block */
10675
10676         if (bPrev == nullptr)
10677         {
10678             /* special case if this is the first BB */
10679
10680             noway_assert(block == fgFirstBB);
10681
10682             /* Must be a fall through to next block */
10683
10684             noway_assert(block->bbJumpKind == BBJ_NONE);
10685
10686             /* old block no longer gets the extra ref count for being the first block */
10687             block->bbRefs--;
10688             succBlock->bbRefs++;
10689
10690             /* Set the new firstBB */
10691             fgUnlinkBlock(block);
10692
10693             /* Always treat the initial block as a jump target */
10694             fgFirstBB->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
10695         }
10696         else
10697         {
10698             fgUnlinkBlock(block);
10699         }
10700
10701         /* mark the block as removed and set the change flag */
10702
10703         block->bbFlags |= BBF_REMOVED;
10704
10705         /* Update bbRefs and bbPreds.
10706          * All blocks jumping to 'block' now jump to 'succBlock'.
10707          * First, remove 'block' from the predecessor list of succBlock.
10708          */
10709
10710         fgRemoveRefPred(succBlock, block);
10711
10712         for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
10713         {
10714             BasicBlock* predBlock = pred->flBlock;
10715
10716             /* Are we changing a loop backedge into a forward jump? */
10717
10718             if (block->isLoopHead() && (predBlock->bbNum >= block->bbNum) && (predBlock->bbNum <= succBlock->bbNum))
10719             {
10720                 /* First update the loop table and bbWeights */
10721                 optUpdateLoopsBeforeRemoveBlock(predBlock);
10722             }
10723
10724             /* If predBlock is a new predecessor, then add it to succBlock's
10725                predecessor's list. */
10726             if (predBlock->bbJumpKind != BBJ_SWITCH)
10727             {
10728                 // Even if the pred is not a switch, we could have a conditional branch
10729                 // to the fallthrough, so duplicate there could be preds
10730                 for (unsigned i = 0; i < pred->flDupCount; i++)
10731                 {
10732                     fgAddRefPred(succBlock, predBlock);
10733                 }
10734             }
10735
10736             /* change all jumps to the removed block */
10737             switch (predBlock->bbJumpKind)
10738             {
10739                 default:
10740                     noway_assert(!"Unexpected bbJumpKind in fgRemoveBlock()");
10741                     break;
10742
10743                 case BBJ_NONE:
10744                     noway_assert(predBlock == bPrev);
10745                     PREFIX_ASSUME(bPrev != nullptr);
10746
10747                     /* In the case of BBJ_ALWAYS we have to change the type of its predecessor */
10748                     if (block->bbJumpKind == BBJ_ALWAYS)
10749                     {
10750                         /* bPrev now becomes a BBJ_ALWAYS */
10751                         bPrev->bbJumpKind = BBJ_ALWAYS;
10752                         bPrev->bbJumpDest = succBlock;
10753                     }
10754                     break;
10755
10756                 case BBJ_COND:
10757                     /* The links for the direct predecessor case have already been updated above */
10758                     if (predBlock->bbJumpDest != block)
10759                     {
10760                         succBlock->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
10761                         break;
10762                     }
10763
10764                     /* Check if both side of the BBJ_COND now jump to the same block */
10765                     if (predBlock->bbNext == succBlock)
10766                     {
10767                         // Make sure we are replacing "block" with "succBlock" in predBlock->bbJumpDest.
10768                         noway_assert(predBlock->bbJumpDest == block);
10769                         predBlock->bbJumpDest = succBlock;
10770                         fgRemoveConditionalJump(predBlock);
10771                         break;
10772                     }
10773
10774                     /* Fall through for the jump case */
10775                     __fallthrough;
10776
10777                 case BBJ_CALLFINALLY:
10778                 case BBJ_ALWAYS:
10779                 case BBJ_EHCATCHRET:
10780                     noway_assert(predBlock->bbJumpDest == block);
10781                     predBlock->bbJumpDest = succBlock;
10782                     succBlock->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
10783                     break;
10784
10785                 case BBJ_SWITCH:
10786                     // Change any jumps from 'predBlock' (a BBJ_SWITCH) to 'block' to jump to 'succBlock'
10787                     //
10788                     // For the jump targets of 'predBlock' (a BBJ_SWITCH) that jump to 'block'
10789                     // remove the old predecessor at 'block' from 'predBlock'  and
10790                     // add the new predecessor at 'succBlock' from 'predBlock'
10791                     //
10792                     fgReplaceSwitchJumpTarget(predBlock, succBlock, block);
10793                     break;
10794             }
10795         }
10796     }
10797
10798     if (bPrev != nullptr)
10799     {
10800         switch (bPrev->bbJumpKind)
10801         {
10802             case BBJ_CALLFINALLY:
10803                 // If prev is a BBJ_CALLFINALLY it better be marked as RETLESS
10804                 noway_assert(bPrev->bbFlags & BBF_RETLESS_CALL);
10805                 break;
10806
10807             case BBJ_ALWAYS:
10808                 // Check for branch to next block. Just make sure the BBJ_ALWAYS block is not
10809                 // part of a BBJ_CALLFINALLY/BBJ_ALWAYS pair. We do this here and don't rely on fgUpdateFlowGraph
10810                 // because we can be called by ComputeDominators and it expects it to remove this jump to
10811                 // the next block. This is the safest fix. We should remove all this BBJ_CALLFINALLY/BBJ_ALWAYS
10812                 // pairing.
10813
10814                 if ((bPrev->bbJumpDest == bPrev->bbNext) &&
10815                     !fgInDifferentRegions(bPrev, bPrev->bbJumpDest)) // We don't remove a branch from Hot -> Cold
10816                 {
10817                     if ((bPrev == fgFirstBB) || !bPrev->bbPrev->isBBCallAlwaysPair())
10818                     {
10819                         // It's safe to change the jump type
10820                         bPrev->bbJumpKind = BBJ_NONE;
10821                         bPrev->bbFlags &= ~BBF_NEEDS_GCPOLL;
10822                     }
10823                 }
10824                 break;
10825
10826             case BBJ_COND:
10827                 /* Check for branch to next block */
10828                 if (bPrev->bbJumpDest == bPrev->bbNext)
10829                 {
10830                     fgRemoveConditionalJump(bPrev);
10831                 }
10832                 break;
10833
10834             default:
10835                 break;
10836         }
10837
10838         ehUpdateForDeletedBlock(block);
10839     }
10840 }
10841
10842 /*****************************************************************************
10843  *
10844  *  Function called to connect to block that previously had a fall through
10845  */
10846
10847 BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst)
10848 {
10849     BasicBlock* jmpBlk = nullptr;
10850
10851     /* If bSrc is non-NULL */
10852
10853     if (bSrc != nullptr)
10854     {
10855         /* If bSrc falls through to a block that is not bDst, we will insert a jump to bDst */
10856
10857         if (bSrc->bbFallsThrough() && (bSrc->bbNext != bDst))
10858         {
10859             switch (bSrc->bbJumpKind)
10860             {
10861
10862                 case BBJ_NONE:
10863                     bSrc->bbJumpKind = BBJ_ALWAYS;
10864                     bSrc->bbJumpDest = bDst;
10865                     bSrc->bbJumpDest->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
10866 #ifdef DEBUG
10867                     if (verbose)
10868                     {
10869                         printf("Block BB%02u ended with a BBJ_NONE, Changed to an unconditional jump to BB%02u\n",
10870                                bSrc->bbNum, bSrc->bbJumpDest->bbNum);
10871                     }
10872 #endif
10873                     break;
10874
10875                 case BBJ_CALLFINALLY:
10876                 case BBJ_COND:
10877
10878                     // Add a new block after bSrc which jumps to 'bDst'
10879                     jmpBlk = fgNewBBafter(BBJ_ALWAYS, bSrc, true);
10880
10881                     if (fgComputePredsDone)
10882                     {
10883                         fgAddRefPred(jmpBlk, bSrc, fgGetPredForBlock(bDst, bSrc));
10884                     }
10885
10886                     // When adding a new jmpBlk we will set the bbWeight and bbFlags
10887                     //
10888                     if (fgHaveValidEdgeWeights)
10889                     {
10890                         noway_assert(fgComputePredsDone);
10891
10892                         flowList* newEdge = fgGetPredForBlock(jmpBlk, bSrc);
10893
10894                         jmpBlk->bbWeight = (newEdge->flEdgeWeightMin + newEdge->flEdgeWeightMax) / 2;
10895                         if (bSrc->bbWeight == 0)
10896                         {
10897                             jmpBlk->bbWeight = 0;
10898                         }
10899
10900                         if (jmpBlk->bbWeight == 0)
10901                         {
10902                             jmpBlk->bbFlags |= BBF_RUN_RARELY;
10903                         }
10904
10905                         BasicBlock::weight_t weightDiff = (newEdge->flEdgeWeightMax - newEdge->flEdgeWeightMin);
10906                         BasicBlock::weight_t slop       = BasicBlock::GetSlopFraction(bSrc, bDst);
10907
10908                         //
10909                         // If the [min/max] values for our edge weight is within the slop factor
10910                         //  then we will set the BBF_PROF_WEIGHT flag for the block
10911                         //
10912                         if (weightDiff <= slop)
10913                         {
10914                             jmpBlk->bbFlags |= BBF_PROF_WEIGHT;
10915                         }
10916                     }
10917                     else
10918                     {
10919                         // We set the bbWeight to the smaller of bSrc->bbWeight or bDst->bbWeight
10920                         if (bSrc->bbWeight < bDst->bbWeight)
10921                         {
10922                             jmpBlk->bbWeight = bSrc->bbWeight;
10923                             jmpBlk->bbFlags |= (bSrc->bbFlags & BBF_RUN_RARELY);
10924                         }
10925                         else
10926                         {
10927                             jmpBlk->bbWeight = bDst->bbWeight;
10928                             jmpBlk->bbFlags |= (bDst->bbFlags & BBF_RUN_RARELY);
10929                         }
10930                     }
10931
10932                     jmpBlk->bbJumpDest = bDst;
10933                     jmpBlk->bbJumpDest->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
10934
10935                     if (fgComputePredsDone)
10936                     {
10937                         fgReplacePred(bDst, bSrc, jmpBlk);
10938                     }
10939                     else
10940                     {
10941                         jmpBlk->bbFlags |= BBF_IMPORTED;
10942                     }
10943
10944 #ifdef DEBUG
10945                     if (verbose)
10946                     {
10947                         printf("Added an unconditional jump to BB%02u after block BB%02u\n", jmpBlk->bbJumpDest->bbNum,
10948                                bSrc->bbNum);
10949                     }
10950 #endif // DEBUG
10951                     break;
10952
10953                 default:
10954                     noway_assert(!"Unexpected bbJumpKind");
10955                     break;
10956             }
10957         }
10958         else
10959         {
10960             // If bSrc is an unconditional branch to the next block
10961             // then change it to a BBJ_NONE block
10962             //
10963             if ((bSrc->bbJumpKind == BBJ_ALWAYS) && !(bSrc->bbFlags & BBF_KEEP_BBJ_ALWAYS) &&
10964                 (bSrc->bbJumpDest == bSrc->bbNext))
10965             {
10966                 bSrc->bbJumpKind = BBJ_NONE;
10967                 bSrc->bbFlags &= ~BBF_NEEDS_GCPOLL;
10968 #ifdef DEBUG
10969                 if (verbose)
10970                 {
10971                     printf("Changed an unconditional jump from BB%02u to the next block BB%02u into a BBJ_NONE block\n",
10972                            bSrc->bbNum, bSrc->bbNext->bbNum);
10973                 }
10974 #endif // DEBUG
10975             }
10976         }
10977     }
10978
10979     return jmpBlk;
10980 }
10981
10982 /*****************************************************************************
10983  Walk the flow graph, reassign block numbers to keep them in ascending order.
10984  Returns 'true' if any renumbering was actually done, OR if we change the
10985  maximum number of assigned basic blocks (this can happen if we do inlining,
10986  create a new, high-numbered block, then that block goes away. We go to
10987  renumber the blocks, none of them actually change number, but we shrink the
10988  maximum assigned block number. This affects the block set epoch).
10989 */
10990
10991 bool Compiler::fgRenumberBlocks()
10992 {
10993     // If we renumber the blocks the dominator information will be out-of-date
10994     if (fgDomsComputed)
10995     {
10996         noway_assert(!"Can't call Compiler::fgRenumberBlocks() when fgDomsComputed==true");
10997     }
10998
10999 #ifdef DEBUG
11000     if (verbose)
11001     {
11002         printf("\n*************** Before renumbering the basic blocks\n");
11003         fgDispBasicBlocks();
11004         fgDispHandlerTab();
11005     }
11006 #endif // DEBUG
11007
11008     bool        renumbered  = false;
11009     bool        newMaxBBNum = false;
11010     BasicBlock* block;
11011
11012     unsigned numStart = 1 + (compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : 0);
11013     unsigned num;
11014
11015     for (block = fgFirstBB, num = numStart; block != nullptr; block = block->bbNext, num++)
11016     {
11017         noway_assert((block->bbFlags & BBF_REMOVED) == 0);
11018
11019         if (block->bbNum != num)
11020         {
11021             renumbered = true;
11022 #ifdef DEBUG
11023             if (verbose)
11024             {
11025                 printf("Renumber BB%02u to BB%02u\n", block->bbNum, num);
11026             }
11027 #endif // DEBUG
11028             block->bbNum = num;
11029         }
11030
11031         if (block->bbNext == nullptr)
11032         {
11033             fgLastBB  = block;
11034             fgBBcount = num - numStart + 1;
11035             if (compIsForInlining())
11036             {
11037                 if (impInlineInfo->InlinerCompiler->fgBBNumMax != num)
11038                 {
11039                     impInlineInfo->InlinerCompiler->fgBBNumMax = num;
11040                     newMaxBBNum                                = true;
11041                 }
11042             }
11043             else
11044             {
11045                 if (fgBBNumMax != num)
11046                 {
11047                     fgBBNumMax  = num;
11048                     newMaxBBNum = true;
11049                 }
11050             }
11051         }
11052     }
11053
11054 #ifdef DEBUG
11055     if (verbose)
11056     {
11057         printf("\n*************** After renumbering the basic blocks\n");
11058         if (renumbered)
11059         {
11060             fgDispBasicBlocks();
11061             fgDispHandlerTab();
11062         }
11063         else
11064         {
11065             printf("=============== No blocks renumbered!\n");
11066         }
11067     }
11068 #endif // DEBUG
11069
11070     // Now update the BlockSet epoch, which depends on the block numbers.
11071     // If any blocks have been renumbered then create a new BlockSet epoch.
11072     // Even if we have not renumbered any blocks, we might still need to force
11073     // a new BlockSet epoch, for one of several reasons. If there are any new
11074     // blocks with higher numbers than the former maximum numbered block, then we
11075     // need a new epoch with a new size matching the new largest numbered block.
11076     // Also, if the number of blocks is different from the last time we set the
11077     // BlockSet epoch, then we need a new epoch. This wouldn't happen if we
11078     // renumbered blocks after every block addition/deletion, but it might be
11079     // the case that we can change the number of blocks, then set the BlockSet
11080     // epoch without renumbering, then change the number of blocks again, then
11081     // renumber.
11082     if (renumbered || newMaxBBNum)
11083     {
11084         NewBasicBlockEpoch();
11085
11086         // The key in the unique switch successor map is dependent on the block number, so invalidate that cache.
11087         InvalidateUniqueSwitchSuccMap();
11088     }
11089     else
11090     {
11091         EnsureBasicBlockEpoch();
11092     }
11093
11094     // Tell our caller if any blocks actually were renumbered.
11095     return renumbered || newMaxBBNum;
11096 }
11097
11098 /*****************************************************************************
11099  *
11100  *  Is the BasicBlock bJump a forward branch?
11101  *   Optionally bSrc can be supplied to indicate that
11102  *   bJump must be forward with respect to bSrc
11103  */
11104 bool Compiler::fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc /* = NULL */)
11105 {
11106     bool result = false;
11107
11108     if ((bJump->bbJumpKind == BBJ_COND) || (bJump->bbJumpKind == BBJ_ALWAYS))
11109     {
11110         BasicBlock* bDest = bJump->bbJumpDest;
11111         BasicBlock* bTemp = (bSrc == nullptr) ? bJump : bSrc;
11112
11113         while (true)
11114         {
11115             bTemp = bTemp->bbNext;
11116
11117             if (bTemp == nullptr)
11118             {
11119                 break;
11120             }
11121
11122             if (bTemp == bDest)
11123             {
11124                 result = true;
11125                 break;
11126             }
11127         }
11128     }
11129
11130     return result;
11131 }
11132
11133 /*****************************************************************************
11134  *
11135  *  Function called to expand the set of rarely run blocks
11136  */
11137
11138 bool Compiler::fgExpandRarelyRunBlocks()
11139 {
11140     bool result = false;
11141
11142 #ifdef DEBUG
11143     if (verbose)
11144     {
11145         printf("\n*************** In fgExpandRarelyRunBlocks()\n");
11146     }
11147
11148     const char* reason = nullptr;
11149 #endif
11150
11151     // We expand the number of rarely run blocks by observing
11152     // that a block that falls into or jumps to a rarely run block,
11153     // must itself be rarely run and when we have a conditional
11154     // jump in which both branches go to rarely run blocks then
11155     // the block must itself be rarely run
11156
11157     BasicBlock* block;
11158     BasicBlock* bPrev;
11159
11160     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
11161     {
11162         if (bPrev->isRunRarely())
11163         {
11164             continue;
11165         }
11166
11167         /* bPrev is known to be a normal block here */
11168         switch (bPrev->bbJumpKind)
11169         {
11170             case BBJ_ALWAYS:
11171
11172                 /* Is the jump target rarely run? */
11173                 if (bPrev->bbJumpDest->isRunRarely())
11174                 {
11175                     INDEBUG(reason = "Unconditional jump to a rarely run block";)
11176                     goto NEW_RARELY_RUN;
11177                 }
11178                 break;
11179
11180             case BBJ_CALLFINALLY:
11181
11182                 // Check for a BBJ_CALLFINALLY followed by a rarely run paired BBJ_ALWAYS
11183                 //
11184                 if (bPrev->isBBCallAlwaysPair())
11185                 {
11186                     /* Is the next block rarely run? */
11187                     if (block->isRunRarely())
11188                     {
11189                         INDEBUG(reason = "Call of finally followed by a rarely run block";)
11190                         goto NEW_RARELY_RUN;
11191                     }
11192                 }
11193                 break;
11194
11195             case BBJ_NONE:
11196
11197                 /* is fall through target rarely run? */
11198                 if (block->isRunRarely())
11199                 {
11200                     INDEBUG(reason = "Falling into a rarely run block";)
11201                     goto NEW_RARELY_RUN;
11202                 }
11203                 break;
11204
11205             case BBJ_COND:
11206
11207                 if (!block->isRunRarely())
11208                 {
11209                     continue;
11210                 }
11211
11212                 /* If both targets of the BBJ_COND are run rarely then don't reorder */
11213                 if (bPrev->bbJumpDest->isRunRarely())
11214                 {
11215                     /* bPrev should also be marked as run rarely */
11216                     if (!bPrev->isRunRarely())
11217                     {
11218                         INDEBUG(reason = "Both sides of a conditional jump are rarely run";)
11219
11220                     NEW_RARELY_RUN:
11221                         /* If the weight of the block was obtained from a profile run,
11222                            than it's more accurate than our static analysis */
11223                         if (bPrev->hasProfileWeight())
11224                         {
11225                             continue;
11226                         }
11227                         result = true;
11228
11229 #ifdef DEBUG
11230                         assert(reason != nullptr);
11231                         if (verbose)
11232                         {
11233                             printf("%s, marking BB%02u as rarely run\n", reason, bPrev->bbNum);
11234                         }
11235 #endif // DEBUG
11236
11237                         /* Must not have previously been marked */
11238                         noway_assert(!bPrev->isRunRarely());
11239
11240                         /* Mark bPrev as a new rarely run block */
11241                         bPrev->bbSetRunRarely();
11242
11243                         BasicBlock* bPrevPrev = nullptr;
11244                         BasicBlock* tmpbb;
11245
11246                         if ((bPrev->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)
11247                         {
11248                             // If we've got a BBJ_CALLFINALLY/BBJ_ALWAYS pair, treat the BBJ_CALLFINALLY as an
11249                             // additional predecessor for the BBJ_ALWAYS block
11250                             tmpbb = bPrev->bbPrev;
11251                             noway_assert(tmpbb != nullptr);
11252 #if FEATURE_EH_FUNCLETS
11253                             noway_assert(tmpbb->isBBCallAlwaysPair());
11254                             bPrevPrev = tmpbb;
11255 #else
11256                             if (tmpbb->bbJumpKind == BBJ_CALLFINALLY)
11257                             {
11258                                 bPrevPrev = tmpbb;
11259                             }
11260 #endif
11261                         }
11262
11263                         /* Now go back to it's earliest predecessor to see */
11264                         /* if it too should now be marked as rarely run    */
11265                         flowList* pred = bPrev->bbPreds;
11266
11267                         if ((pred != nullptr) || (bPrevPrev != nullptr))
11268                         {
11269                             // bPrevPrev will be set to the lexically
11270                             // earliest predecessor of bPrev.
11271
11272                             while (pred != nullptr)
11273                             {
11274                                 if (bPrevPrev == nullptr)
11275                                 {
11276                                     // Initially we select the first block in the bbPreds list
11277                                     bPrevPrev = pred->flBlock;
11278                                     continue;
11279                                 }
11280
11281                                 // Walk the flow graph lexically forward from pred->flBlock
11282                                 // if we find (block == bPrevPrev) then
11283                                 // pred->flBlock is an earlier predecessor.
11284                                 for (tmpbb = pred->flBlock; tmpbb != nullptr; tmpbb = tmpbb->bbNext)
11285                                 {
11286                                     if (tmpbb == bPrevPrev)
11287                                     {
11288                                         /* We found an ealier predecessor */
11289                                         bPrevPrev = pred->flBlock;
11290                                         break;
11291                                     }
11292                                     else if (tmpbb == bPrev)
11293                                     {
11294                                         // We have reached bPrev so stop walking
11295                                         // as this cannot be an earlier predecessor
11296                                         break;
11297                                     }
11298                                 }
11299
11300                                 // Onto the next predecessor
11301                                 pred = pred->flNext;
11302                             }
11303
11304                             // Walk the flow graph forward from bPrevPrev
11305                             // if we don't find (tmpbb == bPrev) then our candidate
11306                             // bPrevPrev is lexically after bPrev and we do not
11307                             // want to select it as our new block
11308
11309                             for (tmpbb = bPrevPrev; tmpbb != nullptr; tmpbb = tmpbb->bbNext)
11310                             {
11311                                 if (tmpbb == bPrev)
11312                                 {
11313                                     // Set up block back to the lexically
11314                                     // earliest predecessor of pPrev
11315
11316                                     block = bPrevPrev;
11317                                 }
11318                             }
11319                         }
11320                     }
11321                     break;
11322
11323                     default:
11324                         break;
11325                 }
11326         }
11327     }
11328
11329     // Now iterate over every block to see if we can prove that a block is rarely run
11330     // (i.e. when all predecessors to the block are rarely run)
11331     //
11332     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
11333     {
11334         // If block is not run rarely, then check to make sure that it has
11335         // at least one non-rarely run block.
11336
11337         if (!block->isRunRarely())
11338         {
11339             bool rare = true;
11340
11341             /* Make sure that block has at least one normal predecessor */
11342             for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
11343             {
11344                 /* Find the fall through predecessor, if any */
11345                 if (!pred->flBlock->isRunRarely())
11346                 {
11347                     rare = false;
11348                     break;
11349                 }
11350             }
11351
11352             if (rare)
11353             {
11354                 // If 'block' is the start of a handler or filter then we cannot make it
11355                 // rarely run because we may have an exceptional edge that
11356                 // branches here.
11357                 //
11358                 if (bbIsHandlerBeg(block))
11359                 {
11360                     rare = false;
11361                 }
11362             }
11363
11364             if (rare)
11365             {
11366                 block->bbSetRunRarely();
11367                 result = true;
11368
11369 #ifdef DEBUG
11370                 if (verbose)
11371                 {
11372                     printf("All branches to BB%02u are from rarely run blocks, marking as rarely run\n", block->bbNum);
11373                 }
11374 #endif // DEBUG
11375
11376                 // When marking a BBJ_CALLFINALLY as rarely run we also mark
11377                 // the BBJ_ALWAYS that comes after it as rarely run
11378                 //
11379                 if (block->isBBCallAlwaysPair())
11380                 {
11381                     BasicBlock* bNext = block->bbNext;
11382                     PREFIX_ASSUME(bNext != nullptr);
11383                     bNext->bbSetRunRarely();
11384 #ifdef DEBUG
11385                     if (verbose)
11386                     {
11387                         printf("Also marking the BBJ_ALWAYS at BB%02u as rarely run\n", bNext->bbNum);
11388                     }
11389 #endif // DEBUG
11390                 }
11391             }
11392         }
11393
11394         /* COMPACT blocks if possible */
11395         if (bPrev->bbJumpKind == BBJ_NONE)
11396         {
11397             if (fgCanCompactBlocks(bPrev, block))
11398             {
11399                 fgCompactBlocks(bPrev, block);
11400
11401                 block = bPrev;
11402                 continue;
11403             }
11404         }
11405         //
11406         // if bPrev->bbWeight is not based upon profile data we can adjust
11407         // the weights of bPrev and block
11408         //
11409         else if (bPrev->isBBCallAlwaysPair() &&          // we must have a BBJ_CALLFINALLY and BBK_ALWAYS pair
11410                  (bPrev->bbWeight != block->bbWeight) && // the weights are currently different
11411                  !bPrev->hasProfileWeight())             // and the BBJ_CALLFINALLY block is not using profiled
11412                                                          // weights
11413         {
11414             if (block->isRunRarely())
11415             {
11416                 bPrev->bbWeight =
11417                     block->bbWeight; // the BBJ_CALLFINALLY block now has the same weight as the BBJ_ALWAYS block
11418                 bPrev->bbFlags |= BBF_RUN_RARELY; // and is now rarely run
11419 #ifdef DEBUG
11420                 if (verbose)
11421                 {
11422                     printf("Marking the BBJ_CALLFINALLY block at BB%02u as rarely run because BB%02u is rarely run\n",
11423                            bPrev->bbNum, block->bbNum);
11424                 }
11425 #endif // DEBUG
11426             }
11427             else if (bPrev->isRunRarely())
11428             {
11429                 block->bbWeight =
11430                     bPrev->bbWeight; // the BBJ_ALWAYS block now has the same weight as the BBJ_CALLFINALLY block
11431                 block->bbFlags |= BBF_RUN_RARELY; // and is now rarely run
11432 #ifdef DEBUG
11433                 if (verbose)
11434                 {
11435                     printf("Marking the BBJ_ALWAYS block at BB%02u as rarely run because BB%02u is rarely run\n",
11436                            block->bbNum, bPrev->bbNum);
11437                 }
11438 #endif // DEBUG
11439             }
11440             else // Both blocks are hot, bPrev is known not to be using profiled weight
11441             {
11442                 bPrev->bbWeight =
11443                     block->bbWeight; // the BBJ_CALLFINALLY block now has the same weight as the BBJ_ALWAYS block
11444             }
11445             noway_assert(block->bbWeight == bPrev->bbWeight);
11446         }
11447     }
11448
11449     return result;
11450 }
11451
11452 /*****************************************************************************
11453  *
11454  *  Returns true if it is allowable (based upon the EH regions)
11455  *  to place block bAfter immediately after bBefore. It is allowable
11456  *  if the 'bBefore' and 'bAfter' blocks are in the exact same EH region.
11457  */
11458
11459 bool Compiler::fgEhAllowsMoveBlock(BasicBlock* bBefore, BasicBlock* bAfter)
11460 {
11461     return BasicBlock::sameEHRegion(bBefore, bAfter);
11462 }
11463
11464 /*****************************************************************************
11465  *
11466  *  Function called to move the range of blocks [bStart .. bEnd].
11467  *  The blocks are placed immediately after the insertAfterBlk.
11468  *  fgFirstFuncletBB is not updated; that is the responsibility of the caller, if necessary.
11469  */
11470
11471 void Compiler::fgMoveBlocksAfter(BasicBlock* bStart, BasicBlock* bEnd, BasicBlock* insertAfterBlk)
11472 {
11473     /* We have decided to insert the block(s) after 'insertAfterBlk' */
11474     CLANG_FORMAT_COMMENT_ANCHOR;
11475
11476 #ifdef DEBUG
11477     if (verbose)
11478     {
11479         printf("Relocated block%s [BB%02u..BB%02u] inserted after BB%02u%s\n", (bStart == bEnd) ? "" : "s",
11480                bStart->bbNum, bEnd->bbNum, insertAfterBlk->bbNum,
11481                (insertAfterBlk->bbNext == nullptr) ? " at the end of method" : "");
11482     }
11483 #endif // DEBUG
11484
11485     /* relink [bStart .. bEnd] into the flow graph */
11486
11487     bEnd->bbNext = insertAfterBlk->bbNext;
11488     if (insertAfterBlk->bbNext)
11489     {
11490         insertAfterBlk->bbNext->bbPrev = bEnd;
11491     }
11492     insertAfterBlk->setNext(bStart);
11493
11494     /* If insertAfterBlk was fgLastBB then update fgLastBB */
11495     if (insertAfterBlk == fgLastBB)
11496     {
11497         fgLastBB = bEnd;
11498         noway_assert(fgLastBB->bbNext == nullptr);
11499     }
11500 }
11501
11502 /*****************************************************************************
11503  *
11504  *  Function called to relocate a single range to the end of the method.
11505  *  Only an entire consecutive region can be moved and it will be kept together.
11506  *  Except for the first block, the range cannot have any blocks that jump into or out of the region.
11507  *  When successful we return the bLast block which is the last block that we relocated.
11508  *  When unsuccessful we return NULL.
11509
11510     =============================================================
11511     NOTE: This function can invalidate all pointers into the EH table, as well as change the size of the EH table!
11512     =============================================================
11513  */
11514
11515 BasicBlock* Compiler::fgRelocateEHRange(unsigned regionIndex, FG_RELOCATE_TYPE relocateType)
11516 {
11517     INDEBUG(const char* reason = "None";)
11518
11519     // Figure out the range of blocks we're going to move
11520
11521     unsigned    XTnum;
11522     EHblkDsc*   HBtab;
11523     BasicBlock* bStart  = nullptr;
11524     BasicBlock* bMiddle = nullptr;
11525     BasicBlock* bLast   = nullptr;
11526     BasicBlock* bPrev   = nullptr;
11527
11528 #if FEATURE_EH_FUNCLETS
11529     // We don't support moving try regions... yet?
11530     noway_assert(relocateType == FG_RELOCATE_HANDLER);
11531 #endif // FEATURE_EH_FUNCLETS
11532
11533     HBtab = ehGetDsc(regionIndex);
11534
11535     if (relocateType == FG_RELOCATE_TRY)
11536     {
11537         bStart = HBtab->ebdTryBeg;
11538         bLast  = HBtab->ebdTryLast;
11539     }
11540     else if (relocateType == FG_RELOCATE_HANDLER)
11541     {
11542         if (HBtab->HasFilter())
11543         {
11544             // The filter and handler funclets must be moved together, and remain contiguous.
11545             bStart  = HBtab->ebdFilter;
11546             bMiddle = HBtab->ebdHndBeg;
11547             bLast   = HBtab->ebdHndLast;
11548         }
11549         else
11550         {
11551             bStart = HBtab->ebdHndBeg;
11552             bLast  = HBtab->ebdHndLast;
11553         }
11554     }
11555
11556     // Our range must contain either all rarely run blocks or all non-rarely run blocks
11557     bool inTheRange = false;
11558     bool validRange = false;
11559
11560     BasicBlock* block;
11561
11562     noway_assert(bStart != nullptr && bLast != nullptr);
11563     if (bStart == fgFirstBB)
11564     {
11565         INDEBUG(reason = "can not relocate first block";)
11566         goto FAILURE;
11567     }
11568
11569 #if !FEATURE_EH_FUNCLETS
11570     // In the funclets case, we still need to set some information on the handler blocks
11571     if (bLast->bbNext == NULL)
11572     {
11573         INDEBUG(reason = "region is already at the end of the method";)
11574         goto FAILURE;
11575     }
11576 #endif // !FEATURE_EH_FUNCLETS
11577
11578     // Walk the block list for this purpose:
11579     // 1. Verify that all the blocks in the range are either all rarely run or not rarely run.
11580     // When creating funclets, we ignore the run rarely flag, as we need to be able to move any blocks
11581     // in the range.
11582     CLANG_FORMAT_COMMENT_ANCHOR;
11583
11584 #if !FEATURE_EH_FUNCLETS
11585     bool isRare;
11586     isRare = bStart->isRunRarely();
11587 #endif // !FEATURE_EH_FUNCLETS
11588     block = fgFirstBB;
11589     while (true)
11590     {
11591         if (block == bStart)
11592         {
11593             noway_assert(inTheRange == false);
11594             inTheRange = true;
11595         }
11596         else if (block == bLast->bbNext)
11597         {
11598             noway_assert(inTheRange == true);
11599             inTheRange = false;
11600             break; // we found the end, so we're done
11601         }
11602
11603         if (inTheRange)
11604         {
11605 #if !FEATURE_EH_FUNCLETS
11606             // Unless all blocks are (not) run rarely we must return false.
11607             if (isRare != block->isRunRarely())
11608             {
11609                 INDEBUG(reason = "this region contains both rarely run and non-rarely run blocks";)
11610                 goto FAILURE;
11611             }
11612 #endif // !FEATURE_EH_FUNCLETS
11613
11614             validRange = true;
11615         }
11616
11617         if (block == nullptr)
11618         {
11619             break;
11620         }
11621
11622         block = block->bbNext;
11623     }
11624     // Ensure that bStart .. bLast defined a valid range
11625     noway_assert((validRange == true) && (inTheRange == false));
11626
11627     bPrev = bStart->bbPrev;
11628     noway_assert(bPrev != nullptr); // Can't move a range that includes the first block of the function.
11629
11630     JITDUMP("Relocating %s range BB%02u..BB%02u (EH#%u) to end of BBlist\n",
11631             (relocateType == FG_RELOCATE_TRY) ? "try" : "handler", bStart->bbNum, bLast->bbNum, regionIndex);
11632
11633 #ifdef DEBUG
11634     if (verbose)
11635     {
11636         fgDispBasicBlocks();
11637         fgDispHandlerTab();
11638     }
11639
11640     if (!FEATURE_EH_FUNCLETS)
11641     {
11642         // This is really expensive, and quickly becomes O(n^n) with funclets
11643         // so only do it once after we've created them (see fgCreateFunclets)
11644         if (expensiveDebugCheckLevel >= 2)
11645         {
11646             fgDebugCheckBBlist();
11647         }
11648     }
11649 #endif // DEBUG
11650
11651 #if FEATURE_EH_FUNCLETS
11652
11653     bStart->bbFlags |= BBF_FUNCLET_BEG; // Mark the start block of the funclet
11654
11655     if (bMiddle != nullptr)
11656     {
11657         bMiddle->bbFlags |= BBF_FUNCLET_BEG; // Also mark the start block of a filter handler as a funclet
11658     }
11659
11660 #endif // FEATURE_EH_FUNCLETS
11661
11662     BasicBlock* bNext;
11663     bNext = bLast->bbNext;
11664
11665     /* Temporarily unlink [bStart .. bLast] from the flow graph */
11666     fgUnlinkRange(bStart, bLast);
11667
11668     BasicBlock* insertAfterBlk;
11669     insertAfterBlk = fgLastBB;
11670
11671 #if FEATURE_EH_FUNCLETS
11672
11673     // There are several cases we need to consider when moving an EH range.
11674     // If moving a range X, we must consider its relationship to every other EH
11675     // range A in the table. Note that each entry in the table represents both
11676     // a protected region and a handler region (possibly including a filter region
11677     // that must live before and adjacent to the handler region), so we must
11678     // consider try and handler regions independently. These are the cases:
11679     // 1. A is completely contained within X (where "completely contained" means
11680     //    that the 'begin' and 'last' parts of A are strictly between the 'begin'
11681     //    and 'end' parts of X, and aren't equal to either, for example, they don't
11682     //    share 'last' blocks). In this case, when we move X, A moves with it, and
11683     //    the EH table doesn't need to change.
11684     // 2. X is completely contained within A. In this case, X gets extracted from A,
11685     //    and the range of A shrinks, but because A is strictly within X, the EH
11686     //    table doesn't need to change.
11687     // 3. A and X have exactly the same range. In this case, A is moving with X and
11688     //    the EH table doesn't need to change.
11689     // 4. A and X share the 'last' block. There are two sub-cases:
11690     //    (a) A is a larger range than X (such that the beginning of A precedes the
11691     //        beginning of X): in this case, we are moving the tail of A. We set the
11692     //        'last' block of A to the the block preceding the beginning block of X.
11693     //    (b) A is a smaller range than X. Thus, we are moving the entirety of A along
11694     //        with X. In this case, nothing in the EH record for A needs to change.
11695     // 5. A and X share the 'beginning' block (but aren't the same range, as in #3).
11696     //    This can never happen here, because we are only moving handler ranges (we don't
11697     //    move try ranges), and handler regions cannot start at the beginning of a try
11698     //    range or handler range and be a subset.
11699     //
11700     // Note that A and X must properly nest for the table to be well-formed. For example,
11701     // the beginning of A can't be strictly within the range of X (that is, the beginning
11702     // of A isn't shared with the beginning of X) and the end of A outside the range.
11703
11704     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
11705     {
11706         if (XTnum != regionIndex) // we don't need to update our 'last' pointer
11707         {
11708             if (HBtab->ebdTryLast == bLast)
11709             {
11710                 // If we moved a set of blocks that were at the end of
11711                 // a different try region then we may need to update ebdTryLast
11712                 for (block = HBtab->ebdTryBeg; block != nullptr; block = block->bbNext)
11713                 {
11714                     if (block == bPrev)
11715                     {
11716                         // We were contained within it, so shrink its region by
11717                         // setting its 'last'
11718                         fgSetTryEnd(HBtab, bPrev);
11719                         break;
11720                     }
11721                     else if (block == HBtab->ebdTryLast->bbNext)
11722                     {
11723                         // bPrev does not come after the TryBeg, thus we are larger, and
11724                         // it is moving with us.
11725                         break;
11726                     }
11727                 }
11728             }
11729             if (HBtab->ebdHndLast == bLast)
11730             {
11731                 // If we moved a set of blocks that were at the end of
11732                 // a different handler region then we must update ebdHndLast
11733                 for (block = HBtab->ebdHndBeg; block != nullptr; block = block->bbNext)
11734                 {
11735                     if (block == bPrev)
11736                     {
11737                         fgSetHndEnd(HBtab, bPrev);
11738                         break;
11739                     }
11740                     else if (block == HBtab->ebdHndLast->bbNext)
11741                     {
11742                         // bPrev does not come after the HndBeg
11743                         break;
11744                     }
11745                 }
11746             }
11747         }
11748     } // end exception table iteration
11749
11750     // Insert the block(s) we are moving after fgLastBlock
11751     fgMoveBlocksAfter(bStart, bLast, insertAfterBlk);
11752
11753     if (fgFirstFuncletBB == nullptr) // The funclet region isn't set yet
11754     {
11755         fgFirstFuncletBB = bStart;
11756     }
11757     else
11758     {
11759         assert(fgFirstFuncletBB !=
11760                insertAfterBlk->bbNext); // We insert at the end, not at the beginning, of the funclet region.
11761     }
11762
11763     // These asserts assume we aren't moving try regions (which we might need to do). Only
11764     // try regions can have fall through into or out of the region.
11765
11766     noway_assert(!bPrev->bbFallsThrough()); // There can be no fall through into a filter or handler region
11767     noway_assert(!bLast->bbFallsThrough()); // There can be no fall through out of a handler region
11768
11769 #ifdef DEBUG
11770     if (verbose)
11771     {
11772         printf("Create funclets: moved region\n");
11773         fgDispHandlerTab();
11774     }
11775
11776     // We have to wait to do this until we've created all the additional regions
11777     // Because this relies on ebdEnclosingTryIndex and ebdEnclosingHndIndex
11778     if (!FEATURE_EH_FUNCLETS)
11779     {
11780         // This is really expensive, and quickly becomes O(n^n) with funclets
11781         // so only do it once after we've created them (see fgCreateFunclets)
11782         if (expensiveDebugCheckLevel >= 2)
11783         {
11784             fgDebugCheckBBlist();
11785         }
11786     }
11787 #endif // DEBUG
11788
11789 #else // FEATURE_EH_FUNCLETS
11790
11791     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
11792     {
11793         if (XTnum == regionIndex)
11794         {
11795             // Don't update our handler's Last info
11796             continue;
11797         }
11798
11799         if (HBtab->ebdTryLast == bLast)
11800         {
11801             // If we moved a set of blocks that were at the end of
11802             // a different try region then we may need to update ebdTryLast
11803             for (block = HBtab->ebdTryBeg; block != NULL; block = block->bbNext)
11804             {
11805                 if (block == bPrev)
11806                 {
11807                     fgSetTryEnd(HBtab, bPrev);
11808                     break;
11809                 }
11810                 else if (block == HBtab->ebdTryLast->bbNext)
11811                 {
11812                     // bPrev does not come after the TryBeg
11813                     break;
11814                 }
11815             }
11816         }
11817         if (HBtab->ebdHndLast == bLast)
11818         {
11819             // If we moved a set of blocks that were at the end of
11820             // a different handler region then we must update ebdHndLast
11821             for (block = HBtab->ebdHndBeg; block != NULL; block = block->bbNext)
11822             {
11823                 if (block == bPrev)
11824                 {
11825                     fgSetHndEnd(HBtab, bPrev);
11826                     break;
11827                 }
11828                 else if (block == HBtab->ebdHndLast->bbNext)
11829                 {
11830                     // bPrev does not come after the HndBeg
11831                     break;
11832                 }
11833             }
11834         }
11835     } // end exception table iteration
11836
11837     // We have decided to insert the block(s) after fgLastBlock
11838     fgMoveBlocksAfter(bStart, bLast, insertAfterBlk);
11839
11840     // If bPrev falls through, we will insert a jump to block
11841     fgConnectFallThrough(bPrev, bStart);
11842
11843     // If bLast falls through, we will insert a jump to bNext
11844     fgConnectFallThrough(bLast, bNext);
11845
11846 #endif // FEATURE_EH_FUNCLETS
11847
11848     goto DONE;
11849
11850 FAILURE:
11851
11852 #ifdef DEBUG
11853     if (verbose)
11854     {
11855         printf("*************** Failed fgRelocateEHRange(BB%02u..BB%02u) because %s\n", bStart->bbNum, bLast->bbNum,
11856                reason);
11857     }
11858 #endif // DEBUG
11859
11860     bLast = nullptr;
11861
11862 DONE:
11863
11864     return bLast;
11865 }
11866
11867 #if FEATURE_EH_FUNCLETS
11868
11869 #if defined(_TARGET_ARM_)
11870
11871 /*****************************************************************************
11872  * We just removed a BBJ_CALLFINALLY/BBJ_ALWAYS pair. If this was the only such pair
11873  * targeting the BBJ_ALWAYS target, then we need to clear the BBF_FINALLY_TARGET bit
11874  * so that target can also be removed. 'block' is the finally target. Since we just
11875  * removed the BBJ_ALWAYS, it better have the BBF_FINALLY_TARGET bit set.
11876  */
11877
11878 void Compiler::fgClearFinallyTargetBit(BasicBlock* block)
11879 {
11880     assert(fgComputePredsDone);
11881     assert((block->bbFlags & BBF_FINALLY_TARGET) != 0);
11882
11883     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
11884     {
11885         if (pred->flBlock->bbJumpKind == BBJ_ALWAYS && pred->flBlock->bbJumpDest == block)
11886         {
11887             BasicBlock* pPrev = pred->flBlock->bbPrev;
11888             if (pPrev != NULL)
11889             {
11890                 if (pPrev->bbJumpKind == BBJ_CALLFINALLY)
11891                 {
11892                     // We found a BBJ_CALLFINALLY / BBJ_ALWAYS that still points to this finally target
11893                     return;
11894                 }
11895             }
11896         }
11897     }
11898
11899     // Didn't find any BBJ_CALLFINALLY / BBJ_ALWAYS that still points here, so clear the bit
11900
11901     block->bbFlags &= ~BBF_FINALLY_TARGET;
11902 }
11903
11904 #endif // defined(_TARGET_ARM_)
11905
11906 /*****************************************************************************
11907  * Is this an intra-handler control flow edge?
11908  *
11909  * 'block' is the head block of a funclet/handler region, or .
11910  * 'predBlock' is a predecessor block of 'block' in the predecessor list.
11911  *
11912  * 'predBlock' can legally only be one of three things:
11913  * 1. in the same handler region (e.g., the source of a back-edge of a loop from
11914  *    'predBlock' to 'block'), including in nested regions within the handler,
11915  * 2. if 'block' begins a handler that is a filter-handler, 'predBlock' must be in the 'filter' region,
11916  * 3. for other handlers, 'predBlock' must be in the 'try' region corresponding to handler (or any
11917  *    region nested in the 'try' region).
11918  *
11919  * Note that on AMD64/ARM64, the BBJ_CALLFINALLY block that calls a finally handler is not
11920  * within the corresponding 'try' region: it is placed in the corresponding 'try' region's
11921  * parent (which might be the main function body). This is how it is represented to the VM
11922  * (with a special "cloned finally" EH table entry).
11923  *
11924  * Return 'true' for case #1, and 'false' otherwise.
11925  */
11926 bool Compiler::fgIsIntraHandlerPred(BasicBlock* predBlock, BasicBlock* block)
11927 {
11928     // Some simple preconditions (as stated above)
11929     assert(!fgFuncletsCreated);
11930     assert(fgGetPredForBlock(block, predBlock) != nullptr);
11931     assert(block->hasHndIndex());
11932
11933     EHblkDsc* xtab = ehGetDsc(block->getHndIndex());
11934
11935 #if FEATURE_EH_CALLFINALLY_THUNKS
11936     if (xtab->HasFinallyHandler())
11937     {
11938         assert((xtab->ebdHndBeg == block) || // The normal case
11939                ((xtab->ebdHndBeg->bbNext == block) &&
11940                 (xtab->ebdHndBeg->bbFlags & BBF_INTERNAL))); // After we've already inserted a header block, and we're
11941                                                              // trying to decide how to split up the predecessor edges.
11942         if (predBlock->bbJumpKind == BBJ_CALLFINALLY)
11943         {
11944             assert(predBlock->bbJumpDest == block);
11945
11946             // A BBJ_CALLFINALLY predecessor of the handler can only come from the corresponding try,
11947             // not from any EH clauses nested in this handler. However, we represent the BBJ_CALLFINALLY
11948             // as being in the 'try' region's parent EH region, which might be the main function body.
11949
11950             unsigned tryIndex = xtab->ebdEnclosingTryIndex;
11951             if (tryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
11952             {
11953                 assert(!predBlock->hasTryIndex());
11954             }
11955             else
11956             {
11957                 assert(predBlock->hasTryIndex());
11958                 assert(tryIndex == predBlock->getTryIndex());
11959                 assert(ehGetDsc(tryIndex)->InTryRegionBBRange(predBlock));
11960             }
11961             return false;
11962         }
11963     }
11964 #endif // FEATURE_EH_CALLFINALLY_THUNKS
11965
11966     assert(predBlock->hasHndIndex() || predBlock->hasTryIndex());
11967
11968     //   We could search the try region looking for predBlock by using bbInTryRegions
11969     // but that does a lexical search for the block, and then assumes funclets
11970     // have been created and does a lexical search of all funclets that were pulled
11971     // out of the parent try region.
11972     //   First, funclets haven't been created yet, and even if they had been, we shouldn't
11973     // have any funclet directly branching to another funclet (they have to return first).
11974     // So we can safely use CheckIsTryRegion instead of bbInTryRegions.
11975     //   Second, I believe the depth of any EH graph will on average be smaller than the
11976     // breadth of the blocks within a try body. Thus it is faster to get our answer by
11977     // looping outward over the region graph. However, I have added asserts, as a
11978     // precaution, to ensure both algorithms agree. The asserts also check that the only
11979     // way to reach the head of a funclet is from the corresponding try body or from
11980     // within the funclet (and *not* any nested funclets).
11981
11982     if (predBlock->hasTryIndex())
11983     {
11984         // Because the EH clauses are listed inside-out, any nested trys will be at a
11985         // lower index than the current try and if there's no enclosing try, tryIndex
11986         // will terminate at NO_ENCLOSING_INDEX
11987
11988         unsigned tryIndex = predBlock->getTryIndex();
11989         while (tryIndex < block->getHndIndex())
11990         {
11991             tryIndex = ehGetEnclosingTryIndex(tryIndex);
11992         }
11993         // tryIndex should enclose predBlock
11994         assert((tryIndex == EHblkDsc::NO_ENCLOSING_INDEX) || ehGetDsc(tryIndex)->InTryRegionBBRange(predBlock));
11995
11996         // At this point tryIndex is either block's handler's corresponding try body
11997         // or some outer try region that contains both predBlock & block or
11998         // NO_ENCLOSING_REGION (because there was no try body that encloses both).
11999         if (tryIndex == block->getHndIndex())
12000         {
12001             assert(xtab->InTryRegionBBRange(predBlock));
12002             assert(!xtab->InHndRegionBBRange(predBlock));
12003             return false;
12004         }
12005         // tryIndex should enclose block (and predBlock as previously asserted)
12006         assert((tryIndex == EHblkDsc::NO_ENCLOSING_INDEX) || ehGetDsc(tryIndex)->InTryRegionBBRange(block));
12007     }
12008     if (xtab->HasFilter())
12009     {
12010         // The block is a handler. Check if the pred block is from its filter. We only need to
12011         // check the end filter flag, as there is only a single filter for any handler, and we
12012         // already know predBlock is a predecessor of block.
12013         if (predBlock->bbJumpKind == BBJ_EHFILTERRET)
12014         {
12015             assert(!xtab->InHndRegionBBRange(predBlock));
12016             return false;
12017         }
12018     }
12019     // It is not in our try region (or filter), so it must be within this handler (or try bodies
12020     // within this handler)
12021     assert(!xtab->InTryRegionBBRange(predBlock));
12022     assert(xtab->InHndRegionBBRange(predBlock));
12023     return true;
12024 }
12025
12026 /*****************************************************************************
12027  * Does this block, first block of a handler region, have any predecessor edges
12028  * that are not from its corresponding try region?
12029  */
12030
12031 bool Compiler::fgAnyIntraHandlerPreds(BasicBlock* block)
12032 {
12033     assert(block->hasHndIndex());
12034     assert(fgFirstBlockOfHandler(block) == block); // this block is the first block of a handler
12035
12036     flowList* pred;
12037
12038     for (pred = block->bbPreds; pred; pred = pred->flNext)
12039     {
12040         BasicBlock* predBlock = pred->flBlock;
12041
12042         if (fgIsIntraHandlerPred(predBlock, block))
12043         {
12044             // We have a predecessor that is not from our try region
12045             return true;
12046         }
12047     }
12048
12049     return false;
12050 }
12051
12052 /*****************************************************************************
12053  * Introduce a new head block of the handler for the prolog to be put in, ahead
12054  * of the current handler head 'block'.
12055  * Note that this code has some similarities to fgCreateLoopPreHeader().
12056  */
12057
12058 void Compiler::fgInsertFuncletPrologBlock(BasicBlock* block)
12059 {
12060 #ifdef DEBUG
12061     if (verbose)
12062     {
12063         printf("\nCreating funclet prolog header for BB%02u\n", block->bbNum);
12064     }
12065 #endif
12066
12067     assert(block->hasHndIndex());
12068     assert(fgFirstBlockOfHandler(block) == block); // this block is the first block of a handler
12069
12070     /* Allocate a new basic block */
12071
12072     BasicBlock* newHead = bbNewBasicBlock(BBJ_NONE);
12073
12074     // In fgComputePreds() we set the BBF_JMP_TARGET and BBF_HAS_LABEL for all of the handler entry points
12075     //
12076     newHead->bbFlags |= (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL);
12077     newHead->inheritWeight(block);
12078     newHead->bbRefs = 0;
12079
12080     fgInsertBBbefore(block, newHead); // insert the new block in the block list
12081     fgExtendEHRegionBefore(block);    // Update the EH table to make the prolog block the first block in the block's EH
12082                                       // block.
12083
12084     // fgExtendEHRegionBefore mucks with the bbRefs without updating the pred list, which we will
12085     // do below for this block. So, undo that change.
12086     assert(newHead->bbRefs > 0);
12087     newHead->bbRefs--;
12088     block->bbRefs++;
12089
12090     // Distribute the pred list between newHead and block. Incoming edges coming from outside
12091     // the handler go to the prolog. Edges coming from with the handler are back-edges, and
12092     // go to the existing 'block'.
12093
12094     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
12095     {
12096         BasicBlock* predBlock = pred->flBlock;
12097         if (!fgIsIntraHandlerPred(predBlock, block))
12098         {
12099             // It's a jump from outside the handler; add it to the newHead preds list and remove
12100             // it from the block preds list.
12101
12102             switch (predBlock->bbJumpKind)
12103             {
12104                 case BBJ_CALLFINALLY:
12105                     noway_assert(predBlock->bbJumpDest == block);
12106                     predBlock->bbJumpDest = newHead;
12107                     fgRemoveRefPred(block, predBlock);
12108                     fgAddRefPred(newHead, predBlock);
12109                     break;
12110
12111                 default:
12112                     // The only way into the handler is via a BBJ_CALLFINALLY (to a finally handler), or
12113                     // via exception handling.
12114                     noway_assert(false);
12115                     break;
12116             }
12117         }
12118     }
12119
12120     assert(nullptr == fgGetPredForBlock(block, newHead));
12121     fgAddRefPred(block, newHead);
12122
12123     assert((newHead->bbFlags & (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL)) ==
12124            (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL));
12125 }
12126
12127 /*****************************************************************************
12128  *
12129  * Every funclet will have a prolog. That prolog will be inserted as the first instructions
12130  * in the first block of the funclet. If the prolog is also the head block of a loop, we
12131  * would end up with the prolog instructions being executed more than once.
12132  * Check for this by searching the predecessor list for loops, and create a new prolog header
12133  * block when needed. We detect a loop by looking for any predecessor that isn't in the
12134  * handler's try region, since the only way to get into a handler is via that try region.
12135  */
12136
12137 void Compiler::fgCreateFuncletPrologBlocks()
12138 {
12139     noway_assert(fgComputePredsDone);
12140     noway_assert(!fgDomsComputed); // this function doesn't maintain the dom sets
12141     assert(!fgFuncletsCreated);
12142
12143     bool      prologBlocksCreated = false;
12144     EHblkDsc* HBtabEnd;
12145     EHblkDsc* HBtab;
12146
12147     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
12148     {
12149         BasicBlock* head = HBtab->ebdHndBeg;
12150
12151         if (fgAnyIntraHandlerPreds(head))
12152         {
12153             // We need to create a new block in which to place the prolog, and split the existing
12154             // head block predecessor edges into those that should point to the prolog, and those
12155             // that shouldn't.
12156             //
12157             // It's arguable that we should just always do this, and not only when we "need to",
12158             // so there aren't two different code paths. However, it's unlikely to be necessary
12159             // for catch handlers because they have an incoming argument (the exception object)
12160             // that needs to get stored or saved, so back-arcs won't normally go to the head. It's
12161             // possible when writing in IL to generate a legal loop (e.g., push an Exception object
12162             // on the stack before jumping back to the catch head), but C# probably won't. This will
12163             // most commonly only be needed for finallys with a do/while loop at the top of the
12164             // finally.
12165             //
12166             // Note that we don't check filters. This might be a bug, but filters always have a filter
12167             // object live on entry, so it's at least unlikely (illegal?) that a loop edge targets the
12168             // filter head.
12169
12170             fgInsertFuncletPrologBlock(head);
12171             prologBlocksCreated = true;
12172         }
12173     }
12174
12175     if (prologBlocksCreated)
12176     {
12177         // If we've modified the graph, reset the 'modified' flag, since the dominators haven't
12178         // been computed.
12179         fgModified = false;
12180
12181 #if DEBUG
12182         if (verbose)
12183         {
12184             JITDUMP("\nAfter fgCreateFuncletPrologBlocks()");
12185             fgDispBasicBlocks();
12186             fgDispHandlerTab();
12187         }
12188
12189         fgVerifyHandlerTab();
12190         fgDebugCheckBBlist();
12191 #endif // DEBUG
12192     }
12193 }
12194
12195 /*****************************************************************************
12196  *
12197  *  Function to create funclets out of all EH catch/finally/fault blocks.
12198  *  We only move filter and handler blocks, not try blocks.
12199  */
12200
12201 void Compiler::fgCreateFunclets()
12202 {
12203     assert(!fgFuncletsCreated);
12204
12205 #ifdef DEBUG
12206     if (verbose)
12207     {
12208         printf("*************** In fgCreateFunclets()\n");
12209     }
12210 #endif
12211
12212     fgCreateFuncletPrologBlocks();
12213
12214     unsigned           XTnum;
12215     EHblkDsc*          HBtab;
12216     const unsigned int funcCnt = ehFuncletCount() + 1;
12217
12218     if (!FitsIn<unsigned short>(funcCnt))
12219     {
12220         IMPL_LIMITATION("Too many funclets");
12221     }
12222
12223     FuncInfoDsc* funcInfo = new (this, CMK_BasicBlock) FuncInfoDsc[funcCnt];
12224
12225     unsigned short funcIdx;
12226
12227     // Setup the root FuncInfoDsc and prepare to start associating
12228     // FuncInfoDsc's with their corresponding EH region
12229     memset((void*)funcInfo, 0, funcCnt * sizeof(FuncInfoDsc));
12230     assert(funcInfo[0].funKind == FUNC_ROOT);
12231     funcIdx = 1;
12232
12233     // Because we iterate from the top to the bottom of the compHndBBtab array, we are iterating
12234     // from most nested (innermost) to least nested (outermost) EH region. It would be reasonable
12235     // to iterate in the opposite order, but the order of funclets shouldn't matter.
12236     //
12237     // We move every handler region to the end of the function: each handler will become a funclet.
12238     //
12239     // Note that fgRelocateEHRange() can add new entries to the EH table. However, they will always
12240     // be added *after* the current index, so our iteration here is not invalidated.
12241     // It *can* invalidate the compHndBBtab pointer itself, though, if it gets reallocated!
12242
12243     for (XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
12244     {
12245         HBtab = ehGetDsc(XTnum); // must re-compute this every loop, since fgRelocateEHRange changes the table
12246         if (HBtab->HasFilter())
12247         {
12248             assert(funcIdx < funcCnt);
12249             funcInfo[funcIdx].funKind    = FUNC_FILTER;
12250             funcInfo[funcIdx].funEHIndex = (unsigned short)XTnum;
12251             funcIdx++;
12252         }
12253         assert(funcIdx < funcCnt);
12254         funcInfo[funcIdx].funKind    = FUNC_HANDLER;
12255         funcInfo[funcIdx].funEHIndex = (unsigned short)XTnum;
12256         HBtab->ebdFuncIndex          = funcIdx;
12257         funcIdx++;
12258         fgRelocateEHRange(XTnum, FG_RELOCATE_HANDLER);
12259     }
12260
12261     // We better have populated all of them by now
12262     assert(funcIdx == funcCnt);
12263
12264     // Publish
12265     compCurrFuncIdx   = 0;
12266     compFuncInfos     = funcInfo;
12267     compFuncInfoCount = (unsigned short)funcCnt;
12268
12269     fgFuncletsCreated = true;
12270
12271 #if DEBUG
12272     if (verbose)
12273     {
12274         JITDUMP("\nAfter fgCreateFunclets()");
12275         fgDispBasicBlocks();
12276         fgDispHandlerTab();
12277     }
12278
12279     fgVerifyHandlerTab();
12280     fgDebugCheckBBlist();
12281 #endif // DEBUG
12282 }
12283
12284 #else // !FEATURE_EH_FUNCLETS
12285
12286 /*****************************************************************************
12287  *
12288  *  Function called to relocate any and all EH regions.
12289  *  Only entire consecutive EH regions will be moved and they will be kept together.
12290  *  Except for the first block, the range can not have any blocks that jump into or out of the region.
12291  */
12292
12293 bool Compiler::fgRelocateEHRegions()
12294 {
12295     bool result = false; // Our return value
12296
12297 #ifdef DEBUG
12298     if (verbose)
12299         printf("*************** In fgRelocateEHRegions()\n");
12300 #endif
12301
12302     if (fgCanRelocateEHRegions)
12303     {
12304         unsigned  XTnum;
12305         EHblkDsc* HBtab;
12306
12307         for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
12308         {
12309             // Nested EH regions cannot be moved.
12310             // Also we don't want to relocate an EH region that has a filter
12311             if ((HBtab->ebdHandlerNestingLevel == 0) && !HBtab->HasFilter())
12312             {
12313                 bool movedTry = false;
12314 #if DEBUG
12315                 bool movedHnd = false;
12316 #endif // DEBUG
12317
12318                 // Only try to move the outermost try region
12319                 if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
12320                 {
12321                     // Move the entire try region if it can be moved
12322                     if (HBtab->ebdTryBeg->isRunRarely())
12323                     {
12324                         BasicBlock* bTryLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_TRY);
12325                         if (bTryLastBB != NULL)
12326                         {
12327                             result   = true;
12328                             movedTry = true;
12329                         }
12330                     }
12331 #if DEBUG
12332                     if (verbose && movedTry)
12333                     {
12334                         printf("\nAfter relocating an EH try region");
12335                         fgDispBasicBlocks();
12336                         fgDispHandlerTab();
12337
12338                         // Make sure that the predecessor lists are accurate
12339                         if (expensiveDebugCheckLevel >= 2)
12340                         {
12341                             fgDebugCheckBBlist();
12342                         }
12343                     }
12344 #endif // DEBUG
12345                 }
12346
12347                 // Currently it is not good to move the rarely run handler regions to the end of the method
12348                 // because fgDetermineFirstColdBlock() must put the start of any handler region in the hot
12349                 // section.
12350                 CLANG_FORMAT_COMMENT_ANCHOR;
12351
12352 #if 0
12353                 // Now try to move the entire handler region if it can be moved.
12354                 // Don't try to move a finally handler unless we already moved the try region.
12355                 if (HBtab->ebdHndBeg->isRunRarely() &&
12356                     !HBtab->ebdHndBeg->hasTryIndex() &&
12357                     (movedTry || !HBtab->HasFinallyHandler()))
12358                 {
12359                     BasicBlock* bHndLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_HANDLER);
12360                     if (bHndLastBB != NULL)
12361                     {
12362                         result   = true;
12363                         movedHnd = true;
12364                     }
12365                 }
12366 #endif // 0
12367
12368 #if DEBUG
12369                 if (verbose && movedHnd)
12370                 {
12371                     printf("\nAfter relocating an EH handler region");
12372                     fgDispBasicBlocks();
12373                     fgDispHandlerTab();
12374
12375                     // Make sure that the predecessor lists are accurate
12376                     if (expensiveDebugCheckLevel >= 2)
12377                     {
12378                         fgDebugCheckBBlist();
12379                     }
12380                 }
12381 #endif // DEBUG
12382             }
12383         }
12384     }
12385
12386 #if DEBUG
12387     fgVerifyHandlerTab();
12388
12389     if (verbose && result)
12390     {
12391         printf("\nAfter fgRelocateEHRegions()");
12392         fgDispBasicBlocks();
12393         fgDispHandlerTab();
12394         // Make sure that the predecessor lists are accurate
12395         fgDebugCheckBBlist();
12396     }
12397 #endif // DEBUG
12398
12399     return result;
12400 }
12401
12402 #endif // !FEATURE_EH_FUNCLETS
12403
12404 bool flowList::setEdgeWeightMinChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop)
12405 {
12406     bool result = false;
12407     if ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin))
12408     {
12409         flEdgeWeightMin = newWeight;
12410         result          = true;
12411     }
12412     else if (slop > 0)
12413     {
12414         // We allow for a small amount of inaccuracy in block weight counts.
12415         if (flEdgeWeightMax < newWeight)
12416         {
12417             // We have already determined that this edge's weight
12418             // is less than newWeight, so we just allow for the slop
12419             if (newWeight <= (flEdgeWeightMax + slop))
12420             {
12421                 result = true;
12422
12423                 if (flEdgeWeightMax != 0)
12424                 {
12425                     // We will raise flEdgeWeightMin and Max towards newWeight
12426                     flEdgeWeightMin = flEdgeWeightMax;
12427                     flEdgeWeightMax = newWeight;
12428                 }
12429
12430                 if (wbUsedSlop != nullptr)
12431                 {
12432                     *wbUsedSlop = true;
12433                 }
12434             }
12435         }
12436         else
12437         {
12438             assert(flEdgeWeightMin > newWeight);
12439
12440             // We have already determined that this edge's weight
12441             // is more than newWeight, so we just allow for the slop
12442             if ((newWeight + slop) >= flEdgeWeightMin)
12443             {
12444                 result = true;
12445
12446                 assert(flEdgeWeightMax != 0);
12447
12448                 // We will lower flEdgeWeightMin towards newWeight
12449                 flEdgeWeightMin = newWeight;
12450
12451                 if (wbUsedSlop != nullptr)
12452                 {
12453                     *wbUsedSlop = true;
12454                 }
12455             }
12456         }
12457
12458         // If we are returning true then we should have adjusted the range so that
12459         // the newWeight is in new range [Min..Max] or fgEdjeWeightMax is zero.
12460         // Also we should have set wbUsedSlop to true.
12461         if (result == true)
12462         {
12463             assert((flEdgeWeightMax == 0) || ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin)));
12464
12465             if (wbUsedSlop != nullptr)
12466             {
12467                 assert(*wbUsedSlop == true);
12468             }
12469         }
12470     }
12471
12472 #if DEBUG
12473     if (result == false)
12474     {
12475         result = false; // break here
12476     }
12477 #endif // DEBUG
12478
12479     return result;
12480 }
12481
12482 bool flowList::setEdgeWeightMaxChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop)
12483 {
12484     bool result = false;
12485     if ((newWeight >= flEdgeWeightMin) && (newWeight <= flEdgeWeightMax))
12486     {
12487         flEdgeWeightMax = newWeight;
12488         result          = true;
12489     }
12490     else if (slop > 0)
12491     {
12492         // We allow for a small amount of inaccuracy in block weight counts.
12493         if (flEdgeWeightMax < newWeight)
12494         {
12495             // We have already determined that this edge's weight
12496             // is less than newWeight, so we just allow for the slop
12497             if (newWeight <= (flEdgeWeightMax + slop))
12498             {
12499                 result = true;
12500
12501                 if (flEdgeWeightMax != 0)
12502                 {
12503                     // We will allow this to raise flEdgeWeightMax towards newWeight
12504                     flEdgeWeightMax = newWeight;
12505                 }
12506
12507                 if (wbUsedSlop != nullptr)
12508                 {
12509                     *wbUsedSlop = true;
12510                 }
12511             }
12512         }
12513         else
12514         {
12515             assert(flEdgeWeightMin > newWeight);
12516
12517             // We have already determined that this edge's weight
12518             // is more than newWeight, so we just allow for the slop
12519             if ((newWeight + slop) >= flEdgeWeightMin)
12520             {
12521                 result = true;
12522
12523                 assert(flEdgeWeightMax != 0);
12524
12525                 // We will allow this to lower flEdgeWeightMin and Max towards newWeight
12526                 flEdgeWeightMax = flEdgeWeightMin;
12527                 flEdgeWeightMin = newWeight;
12528
12529                 if (wbUsedSlop != nullptr)
12530                 {
12531                     *wbUsedSlop = true;
12532                 }
12533             }
12534         }
12535
12536         // If we are returning true then we should have adjusted the range so that
12537         // the newWeight is in new range [Min..Max] or fgEdjeWeightMax is zero
12538         // Also we should have set wbUsedSlop to true, unless it is NULL
12539         if (result == true)
12540         {
12541             assert((flEdgeWeightMax == 0) || ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin)));
12542
12543             assert((wbUsedSlop == nullptr) || (*wbUsedSlop == true));
12544         }
12545     }
12546
12547 #if DEBUG
12548     if (result == false)
12549     {
12550         result = false; // break here
12551     }
12552 #endif // DEBUG
12553
12554     return result;
12555 }
12556
12557 #ifdef DEBUG
12558 void Compiler::fgPrintEdgeWeights()
12559 {
12560     BasicBlock* bSrc;
12561     BasicBlock* bDst;
12562     flowList*   edge;
12563
12564     // Print out all of the edge weights
12565     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12566     {
12567         if (bDst->bbPreds != nullptr)
12568         {
12569             printf("    Edge weights into BB%02u :", bDst->bbNum);
12570             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12571             {
12572                 bSrc = edge->flBlock;
12573                 // This is the control flow edge (bSrc -> bDst)
12574
12575                 printf("BB%02u ", bSrc->bbNum);
12576
12577                 if (edge->flEdgeWeightMin < BB_MAX_WEIGHT)
12578                 {
12579                     printf("(%u", edge->flEdgeWeightMin);
12580                 }
12581                 else
12582                 {
12583                     printf("(MAX");
12584                 }
12585                 if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
12586                 {
12587                     if (edge->flEdgeWeightMax < BB_MAX_WEIGHT)
12588                     {
12589                         printf("..%u", edge->flEdgeWeightMax);
12590                     }
12591                     else
12592                     {
12593                         printf("..MAX");
12594                     }
12595                 }
12596                 printf(")");
12597                 if (edge->flNext != nullptr)
12598                 {
12599                     printf(", ");
12600                 }
12601             }
12602             printf("\n");
12603         }
12604     }
12605 }
12606 #endif // DEBUG
12607
12608 // return true if there is a possibility that the method has a loop (a backedge is present)
12609 bool Compiler::fgMightHaveLoop()
12610 {
12611     // Don't use a BlockSet for this temporary bitset of blocks: we don't want to have to call EnsureBasicBlockEpoch()
12612     // and potentially change the block epoch.
12613
12614     BitVecTraits blockVecTraits(fgBBNumMax + 1, this);
12615     BitVec       BLOCKSET_INIT_NOCOPY(blocksSeen, BitVecOps::MakeEmpty(&blockVecTraits));
12616
12617     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
12618     {
12619         BitVecOps::AddElemD(&blockVecTraits, blocksSeen, block->bbNum);
12620
12621         AllSuccessorIter succsEnd = block->GetAllSuccs(this).end();
12622         for (AllSuccessorIter succs = block->GetAllSuccs(this).begin(); succs != succsEnd; ++succs)
12623         {
12624             BasicBlock* succ = (*succs);
12625             if (BitVecOps::IsMember(&blockVecTraits, blocksSeen, succ->bbNum))
12626             {
12627                 return true;
12628             }
12629         }
12630     }
12631     return false;
12632 }
12633
12634 void Compiler::fgComputeEdgeWeights()
12635 {
12636 #ifdef DEBUG
12637     if (verbose)
12638     {
12639         printf("*************** In fgComputeEdgeWeights()\n");
12640     }
12641 #endif // DEBUG
12642
12643     if (fgIsUsingProfileWeights() == false)
12644     {
12645 #ifdef DEBUG
12646         if (verbose)
12647         {
12648             printf("fgComputeEdgeWeights() we do not have any profile data so we are not using the edge weights\n");
12649         }
12650 #endif // DEBUG
12651         fgHaveValidEdgeWeights = false;
12652         fgCalledCount          = BB_UNITY_WEIGHT;
12653     }
12654
12655 #if DEBUG
12656     if (verbose)
12657     {
12658         fgDispBasicBlocks();
12659         printf("\n");
12660     }
12661 #endif // DEBUG
12662
12663     BasicBlock* bSrc;
12664     BasicBlock* bDst;
12665     flowList*   edge;
12666     unsigned    iterations               = 0;
12667     unsigned    goodEdgeCountCurrent     = 0;
12668     unsigned    goodEdgeCountPrevious    = 0;
12669     bool        inconsistentProfileData  = false;
12670     bool        hasIncompleteEdgeWeights = false;
12671     unsigned    numEdges                 = 0;
12672     bool        usedSlop                 = false;
12673     bool        changed;
12674     bool        modified;
12675
12676     BasicBlock::weight_t returnWeight;
12677     BasicBlock::weight_t slop;
12678
12679     // If we have any blocks that did not have profile derived weight
12680     // we will try to fix their weight up here
12681     //
12682     modified = false;
12683     do // while (changed)
12684     {
12685         changed      = false;
12686         returnWeight = 0;
12687         iterations++;
12688
12689         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12690         {
12691             if (!bDst->hasProfileWeight() && (bDst->bbPreds != nullptr))
12692             {
12693                 BasicBlock* bOnlyNext;
12694
12695                 // This block does not have a profile derived weight
12696                 //
12697                 BasicBlock::weight_t newWeight = BB_MAX_WEIGHT;
12698
12699                 if (bDst->countOfInEdges() == 1)
12700                 {
12701                     // Only one block flows into bDst
12702                     bSrc = bDst->bbPreds->flBlock;
12703
12704                     // Does this block flow into only one other block
12705                     if (bSrc->bbJumpKind == BBJ_NONE)
12706                     {
12707                         bOnlyNext = bSrc->bbNext;
12708                     }
12709                     else if (bSrc->bbJumpKind == BBJ_ALWAYS)
12710                     {
12711                         bOnlyNext = bSrc->bbJumpDest;
12712                     }
12713                     else
12714                     {
12715                         bOnlyNext = nullptr;
12716                     }
12717
12718                     if ((bOnlyNext == bDst) && bSrc->hasProfileWeight())
12719                     {
12720                         // We know the exact weight of bDst
12721                         newWeight = bSrc->bbWeight;
12722                     }
12723                 }
12724
12725                 // Does this block flow into only one other block
12726                 if (bDst->bbJumpKind == BBJ_NONE)
12727                 {
12728                     bOnlyNext = bDst->bbNext;
12729                 }
12730                 else if (bDst->bbJumpKind == BBJ_ALWAYS)
12731                 {
12732                     bOnlyNext = bDst->bbJumpDest;
12733                 }
12734                 else
12735                 {
12736                     bOnlyNext = nullptr;
12737                 }
12738
12739                 if ((bOnlyNext != nullptr) && (bOnlyNext->bbPreds != nullptr))
12740                 {
12741                     // Does only one block flow into bOnlyNext
12742                     if (bOnlyNext->countOfInEdges() == 1)
12743                     {
12744                         noway_assert(bOnlyNext->bbPreds->flBlock == bDst);
12745
12746                         // We know the exact weight of bDst
12747                         newWeight = bOnlyNext->bbWeight;
12748                     }
12749                 }
12750
12751                 if ((newWeight != BB_MAX_WEIGHT) && (bDst->bbWeight != newWeight))
12752                 {
12753                     changed        = true;
12754                     modified       = true;
12755                     bDst->bbWeight = newWeight;
12756                     if (newWeight == 0)
12757                     {
12758                         bDst->bbFlags |= BBF_RUN_RARELY;
12759                     }
12760                     else
12761                     {
12762                         bDst->bbFlags &= ~BBF_RUN_RARELY;
12763                     }
12764                 }
12765             }
12766
12767             // Sum up the weights of all of the return blocks and throw blocks
12768             // This is used when we have a back-edge into block 1
12769             //
12770             if (bDst->hasProfileWeight() && ((bDst->bbJumpKind == BBJ_RETURN) || (bDst->bbJumpKind == BBJ_THROW)))
12771             {
12772                 returnWeight += bDst->bbWeight;
12773             }
12774         }
12775     }
12776     // Generally when we synthesize profile estimates we do it in a way where this algorithm will converge
12777     // but downstream opts that remove conditional branches may create a situation where this is not the case.
12778     // For instance a loop that becomes unreachable creates a sort of 'ring oscillator' (See test b539509)
12779     while (changed && iterations < 10);
12780
12781 #if DEBUG
12782     if (verbose && modified)
12783     {
12784         printf("fgComputeEdgeWeights() adjusted the weight of some blocks\n");
12785         fgDispBasicBlocks();
12786         printf("\n");
12787     }
12788 #endif
12789
12790     // When we are not using profile data we have already setup fgCalledCount
12791     // only set it here if we are using profile data
12792     //
12793     if (fgIsUsingProfileWeights())
12794     {
12795         BasicBlock* firstILBlock = fgFirstBB; // The first block for IL code (i.e. for the IL code at offset 0)
12796
12797         // Do we have an internal block as our first Block?
12798         if (firstILBlock->bbFlags & BBF_INTERNAL)
12799         {
12800             // Skip past any/all BBF_INTERNAL blocks that may have been added before the first real IL block.
12801             //
12802             while (firstILBlock->bbFlags & BBF_INTERNAL)
12803             {
12804                 firstILBlock = firstILBlock->bbNext;
12805             }
12806             // The 'firstILBlock' is now expected to have a profile-derived weight
12807             assert(firstILBlock->hasProfileWeight());
12808         }
12809
12810         // If the first block only has one ref then we use it's weight for fgCalledCount.
12811         // Otherwise we have backedge's into the first block, so instead we use the sum
12812         // of the return block weights for fgCalledCount.
12813         //
12814         // If the profile data has a 0 for the returnWeight
12815         // (i.e. the function never returns because it always throws)
12816         // then just use the first block weight rather than 0.
12817         //
12818         if ((firstILBlock->countOfInEdges() == 1) || (returnWeight == 0))
12819         {
12820             assert(firstILBlock->hasProfileWeight()); // This should always be a profile-derived weight
12821             fgCalledCount = firstILBlock->bbWeight;
12822         }
12823         else
12824         {
12825             fgCalledCount = returnWeight;
12826         }
12827
12828         // If we allocated a scratch block as the first BB then we need
12829         // to set its profile-derived weight to be fgCalledCount
12830         if (fgFirstBBisScratch())
12831         {
12832             fgFirstBB->setBBProfileWeight(fgCalledCount);
12833         }
12834
12835 #if DEBUG
12836         if (verbose)
12837         {
12838             printf("We are using the Profile Weights and fgCalledCount is %d.\n", fgCalledCount);
12839         }
12840 #endif
12841     }
12842
12843     // Now we will compute the initial flEdgeWeightMin and flEdgeWeightMax values
12844     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12845     {
12846         BasicBlock::weight_t bDstWeight = bDst->bbWeight;
12847
12848         // We subtract out the called count so that bDstWeight is
12849         // the sum of all edges that go into this block from this method.
12850         //
12851         if (bDst == fgFirstBB)
12852         {
12853             bDstWeight -= fgCalledCount;
12854         }
12855
12856         for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12857         {
12858             bool assignOK = true;
12859
12860             bSrc = edge->flBlock;
12861             // We are processing the control flow edge (bSrc -> bDst)
12862
12863             numEdges++;
12864
12865             //
12866             // If the bSrc or bDst blocks do not have exact profile weights
12867             // then we must reset any values that they currently have
12868             //
12869
12870             if (!bSrc->hasProfileWeight() || !bDst->hasProfileWeight())
12871             {
12872                 edge->flEdgeWeightMin = BB_ZERO_WEIGHT;
12873                 edge->flEdgeWeightMax = BB_MAX_WEIGHT;
12874             }
12875
12876             slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
12877             switch (bSrc->bbJumpKind)
12878             {
12879                 case BBJ_ALWAYS:
12880                 case BBJ_EHCATCHRET:
12881                 case BBJ_NONE:
12882                 case BBJ_CALLFINALLY:
12883                     // We know the exact edge weight
12884                     assignOK &= edge->setEdgeWeightMinChecked(bSrc->bbWeight, slop, &usedSlop);
12885                     assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, slop, &usedSlop);
12886                     break;
12887
12888                 case BBJ_COND:
12889                 case BBJ_SWITCH:
12890                 case BBJ_EHFINALLYRET:
12891                 case BBJ_EHFILTERRET:
12892                     if (edge->flEdgeWeightMax > bSrc->bbWeight)
12893                     {
12894                         // The maximum edge weight to block can't be greater than the weight of bSrc
12895                         assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, slop, &usedSlop);
12896                     }
12897                     break;
12898
12899                 default:
12900                     // We should never have an edge that starts from one of these jump kinds
12901                     noway_assert(!"Unexpected bbJumpKind");
12902                     break;
12903             }
12904
12905             // The maximum edge weight to block can't be greater than the weight of bDst
12906             if (edge->flEdgeWeightMax > bDstWeight)
12907             {
12908                 assignOK &= edge->setEdgeWeightMaxChecked(bDstWeight, slop, &usedSlop);
12909             }
12910
12911             if (!assignOK)
12912             {
12913                 // Here we have inconsistent profile data
12914                 inconsistentProfileData = true;
12915                 // No point in continuing
12916                 goto EARLY_EXIT;
12917             }
12918         }
12919     }
12920
12921     fgEdgeCount = numEdges;
12922
12923     iterations = 0;
12924
12925     do
12926     {
12927         iterations++;
12928         goodEdgeCountPrevious    = goodEdgeCountCurrent;
12929         goodEdgeCountCurrent     = 0;
12930         hasIncompleteEdgeWeights = false;
12931
12932         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12933         {
12934             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12935             {
12936                 bool assignOK = true;
12937
12938                 // We are processing the control flow edge (bSrc -> bDst)
12939                 bSrc = edge->flBlock;
12940
12941                 slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
12942                 if (bSrc->bbJumpKind == BBJ_COND)
12943                 {
12944                     int       diff;
12945                     flowList* otherEdge;
12946                     if (bSrc->bbNext == bDst)
12947                     {
12948                         otherEdge = fgGetPredForBlock(bSrc->bbJumpDest, bSrc);
12949                     }
12950                     else
12951                     {
12952                         otherEdge = fgGetPredForBlock(bSrc->bbNext, bSrc);
12953                     }
12954                     noway_assert(edge->flEdgeWeightMin <= edge->flEdgeWeightMax);
12955                     noway_assert(otherEdge->flEdgeWeightMin <= otherEdge->flEdgeWeightMax);
12956
12957                     // Adjust edge->flEdgeWeightMin up or adjust otherEdge->flEdgeWeightMax down
12958                     diff = ((int)bSrc->bbWeight) - ((int)edge->flEdgeWeightMin + (int)otherEdge->flEdgeWeightMax);
12959                     if (diff > 0)
12960                     {
12961                         assignOK &= edge->setEdgeWeightMinChecked(edge->flEdgeWeightMin + diff, slop, &usedSlop);
12962                     }
12963                     else if (diff < 0)
12964                     {
12965                         assignOK &=
12966                             otherEdge->setEdgeWeightMaxChecked(otherEdge->flEdgeWeightMax + diff, slop, &usedSlop);
12967                     }
12968
12969                     // Adjust otherEdge->flEdgeWeightMin up or adjust edge->flEdgeWeightMax down
12970                     diff = ((int)bSrc->bbWeight) - ((int)otherEdge->flEdgeWeightMin + (int)edge->flEdgeWeightMax);
12971                     if (diff > 0)
12972                     {
12973                         assignOK &=
12974                             otherEdge->setEdgeWeightMinChecked(otherEdge->flEdgeWeightMin + diff, slop, &usedSlop);
12975                     }
12976                     else if (diff < 0)
12977                     {
12978                         assignOK &= edge->setEdgeWeightMaxChecked(edge->flEdgeWeightMax + diff, slop, &usedSlop);
12979                     }
12980
12981                     if (!assignOK)
12982                     {
12983                         // Here we have inconsistent profile data
12984                         inconsistentProfileData = true;
12985                         // No point in continuing
12986                         goto EARLY_EXIT;
12987                     }
12988 #ifdef DEBUG
12989                     // Now edge->flEdgeWeightMin and otherEdge->flEdgeWeightMax) should add up to bSrc->bbWeight
12990                     diff = ((int)bSrc->bbWeight) - ((int)edge->flEdgeWeightMin + (int)otherEdge->flEdgeWeightMax);
12991                     noway_assert((-((int)slop) <= diff) && (diff <= ((int)slop)));
12992
12993                     // Now otherEdge->flEdgeWeightMin and edge->flEdgeWeightMax) should add up to bSrc->bbWeight
12994                     diff = ((int)bSrc->bbWeight) - ((int)otherEdge->flEdgeWeightMin + (int)edge->flEdgeWeightMax);
12995                     noway_assert((-((int)slop) <= diff) && (diff <= ((int)slop)));
12996 #endif // DEBUG
12997                 }
12998             }
12999         }
13000
13001         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13002         {
13003             BasicBlock::weight_t bDstWeight = bDst->bbWeight;
13004
13005             if (bDstWeight == BB_MAX_WEIGHT)
13006             {
13007                 inconsistentProfileData = true;
13008                 // No point in continuing
13009                 goto EARLY_EXIT;
13010             }
13011             else
13012             {
13013                 // We subtract out the called count so that bDstWeight is
13014                 // the sum of all edges that go into this block from this method.
13015                 //
13016                 if (bDst == fgFirstBB)
13017                 {
13018                     bDstWeight -= fgCalledCount;
13019                 }
13020
13021                 UINT64 minEdgeWeightSum = 0;
13022                 UINT64 maxEdgeWeightSum = 0;
13023
13024                 // Calculate the sums of the minimum and maximum edge weights
13025                 for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13026                 {
13027                     // We are processing the control flow edge (bSrc -> bDst)
13028                     bSrc = edge->flBlock;
13029
13030                     maxEdgeWeightSum += edge->flEdgeWeightMax;
13031                     minEdgeWeightSum += edge->flEdgeWeightMin;
13032                 }
13033
13034                 // maxEdgeWeightSum is the sum of all flEdgeWeightMax values into bDst
13035                 // minEdgeWeightSum is the sum of all flEdgeWeightMin values into bDst
13036
13037                 for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13038                 {
13039                     bool assignOK = true;
13040
13041                     // We are processing the control flow edge (bSrc -> bDst)
13042                     bSrc = edge->flBlock;
13043                     slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
13044
13045                     // otherMaxEdgesWeightSum is the sum of all of the other edges flEdgeWeightMax values
13046                     // This can be used to compute a lower bound for our minimum edge weight
13047                     noway_assert(maxEdgeWeightSum >= edge->flEdgeWeightMax);
13048                     UINT64 otherMaxEdgesWeightSum = maxEdgeWeightSum - edge->flEdgeWeightMax;
13049
13050                     // otherMinEdgesWeightSum is the sum of all of the other edges flEdgeWeightMin values
13051                     // This can be used to compute an upper bound for our maximum edge weight
13052                     noway_assert(minEdgeWeightSum >= edge->flEdgeWeightMin);
13053                     UINT64 otherMinEdgesWeightSum = minEdgeWeightSum - edge->flEdgeWeightMin;
13054
13055                     if (bDstWeight >= otherMaxEdgesWeightSum)
13056                     {
13057                         // minWeightCalc is our minWeight when every other path to bDst takes it's flEdgeWeightMax value
13058                         BasicBlock::weight_t minWeightCalc =
13059                             (BasicBlock::weight_t)(bDstWeight - otherMaxEdgesWeightSum);
13060                         if (minWeightCalc > edge->flEdgeWeightMin)
13061                         {
13062                             assignOK &= edge->setEdgeWeightMinChecked(minWeightCalc, slop, &usedSlop);
13063                         }
13064                     }
13065
13066                     if (bDstWeight >= otherMinEdgesWeightSum)
13067                     {
13068                         // maxWeightCalc is our maxWeight when every other path to bDst takes it's flEdgeWeightMin value
13069                         BasicBlock::weight_t maxWeightCalc =
13070                             (BasicBlock::weight_t)(bDstWeight - otherMinEdgesWeightSum);
13071                         if (maxWeightCalc < edge->flEdgeWeightMax)
13072                         {
13073                             assignOK &= edge->setEdgeWeightMaxChecked(maxWeightCalc, slop, &usedSlop);
13074                         }
13075                     }
13076
13077                     if (!assignOK)
13078                     {
13079                         // Here we have inconsistent profile data
13080                         inconsistentProfileData = true;
13081                         // No point in continuing
13082                         goto EARLY_EXIT;
13083                     }
13084
13085                     // When flEdgeWeightMin equals flEdgeWeightMax we have a "good" edge weight
13086                     if (edge->flEdgeWeightMin == edge->flEdgeWeightMax)
13087                     {
13088                         // Count how many "good" edge weights we have
13089                         // Each time through we should have more "good" weights
13090                         // We exit the while loop when no longer find any new "good" edges
13091                         goodEdgeCountCurrent++;
13092                     }
13093                     else
13094                     {
13095                         // Remember that we have seen at least one "Bad" edge weight
13096                         // so that we will repeat the while loop again
13097                         hasIncompleteEdgeWeights = true;
13098                     }
13099                 }
13100             }
13101         }
13102
13103         if (inconsistentProfileData)
13104         {
13105             hasIncompleteEdgeWeights = true;
13106             break;
13107         }
13108
13109         if (numEdges == goodEdgeCountCurrent)
13110         {
13111             noway_assert(hasIncompleteEdgeWeights == false);
13112             break;
13113         }
13114
13115     } while (hasIncompleteEdgeWeights && (goodEdgeCountCurrent > goodEdgeCountPrevious) && (iterations < 8));
13116
13117 EARLY_EXIT:;
13118
13119 #ifdef DEBUG
13120     if (verbose)
13121     {
13122         if (inconsistentProfileData)
13123         {
13124             printf("fgComputeEdgeWeights() found inconsistent profile data, not using the edge weights\n");
13125         }
13126         else
13127         {
13128             if (hasIncompleteEdgeWeights)
13129             {
13130                 printf("fgComputeEdgeWeights() was able to compute exact edge weights for %3d of the %3d edges, using "
13131                        "%d passes.\n",
13132                        goodEdgeCountCurrent, numEdges, iterations);
13133             }
13134             else
13135             {
13136                 printf("fgComputeEdgeWeights() was able to compute exact edge weights for all of the %3d edges, using "
13137                        "%d passes.\n",
13138                        numEdges, iterations);
13139             }
13140
13141             fgPrintEdgeWeights();
13142         }
13143     }
13144 #endif // DEBUG
13145
13146     fgSlopUsedInEdgeWeights  = usedSlop;
13147     fgRangeUsedInEdgeWeights = false;
13148
13149     // See if any edge weight are expressed in [min..max] form
13150
13151     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13152     {
13153         if (bDst->bbPreds != nullptr)
13154         {
13155             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13156             {
13157                 bSrc = edge->flBlock;
13158                 // This is the control flow edge (bSrc -> bDst)
13159
13160                 if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
13161                 {
13162                     fgRangeUsedInEdgeWeights = true;
13163                     break;
13164                 }
13165             }
13166             if (fgRangeUsedInEdgeWeights)
13167             {
13168                 break;
13169             }
13170         }
13171     }
13172
13173     fgHaveValidEdgeWeights = !inconsistentProfileData;
13174     fgEdgeWeightsComputed  = true;
13175 }
13176
13177 // fgOptimizeBranchToEmptyUnconditional:
13178 //    optimize a jump to an empty block which ends in an unconditional branch.
13179 //  Args:
13180 //      block: source block
13181 //      bDest: destination
13182 //  Returns: true if we changed the code
13183 //
13184 bool Compiler::fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBlock* bDest)
13185 {
13186     bool optimizeJump = true;
13187
13188     assert(bDest->isEmpty());
13189     assert(bDest->bbJumpKind == BBJ_ALWAYS);
13190
13191     // We do not optimize jumps between two different try regions.
13192     // However jumping to a block that is not in any try region is OK
13193     //
13194     if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
13195     {
13196         optimizeJump = false;
13197     }
13198
13199     // Don't optimize a jump to a removed block
13200     if (bDest->bbJumpDest->bbFlags & BBF_REMOVED)
13201     {
13202         optimizeJump = false;
13203     }
13204
13205     // Don't optimize a jump to a cloned finally
13206     if (bDest->bbFlags & BBF_CLONED_FINALLY_BEGIN)
13207     {
13208         optimizeJump = false;
13209     }
13210
13211 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13212     // Don't optimize a jump to a finally target. For BB1->BB2->BB3, where
13213     // BB2 is a finally target, if we changed BB1 to jump directly to BB3,
13214     // it would skip the finally target. BB1 might be a BBJ_ALWAYS block part
13215     // of a BBJ_CALLFINALLY/BBJ_ALWAYS pair, so changing the finally target
13216     // would change the unwind behavior.
13217     if (bDest->bbFlags & BBF_FINALLY_TARGET)
13218     {
13219         optimizeJump = false;
13220     }
13221 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13222
13223     // Must optimize jump if bDest has been removed
13224     //
13225     if (bDest->bbFlags & BBF_REMOVED)
13226     {
13227         optimizeJump = true;
13228     }
13229
13230     // If we are optimizing using real profile weights
13231     // then don't optimize a conditional jump to an unconditional jump
13232     // until after we have computed the edge weights
13233     //
13234     if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed)
13235     {
13236         fgNeedsUpdateFlowGraph = true;
13237         optimizeJump           = false;
13238     }
13239
13240     if (optimizeJump)
13241     {
13242 #ifdef DEBUG
13243         if (verbose)
13244         {
13245             printf("\nOptimizing a jump to an unconditional jump (BB%02u -> BB%02u -> BB%02u)\n", block->bbNum,
13246                    bDest->bbNum, bDest->bbJumpDest->bbNum);
13247         }
13248 #endif // DEBUG
13249
13250         //
13251         // When we optimize a branch to branch we need to update the profile weight
13252         // of bDest by subtracting out the block/edge weight of the path that is being optimized.
13253         //
13254         if (fgHaveValidEdgeWeights && bDest->hasProfileWeight())
13255         {
13256             flowList* edge1 = fgGetPredForBlock(bDest, block);
13257             noway_assert(edge1 != nullptr);
13258
13259             BasicBlock::weight_t edgeWeight;
13260
13261             if (edge1->flEdgeWeightMin != edge1->flEdgeWeightMax)
13262             {
13263                 //
13264                 // We only have an estimate for the edge weight
13265                 //
13266                 edgeWeight = (edge1->flEdgeWeightMin + edge1->flEdgeWeightMax) / 2;
13267                 //
13268                 //  Clear the profile weight flag
13269                 //
13270                 bDest->bbFlags &= ~BBF_PROF_WEIGHT;
13271             }
13272             else
13273             {
13274                 //
13275                 // We only have the exact edge weight
13276                 //
13277                 edgeWeight = edge1->flEdgeWeightMin;
13278             }
13279
13280             //
13281             // Update the bDest->bbWeight
13282             //
13283             if (bDest->bbWeight > edgeWeight)
13284             {
13285                 bDest->bbWeight -= edgeWeight;
13286             }
13287             else
13288             {
13289                 bDest->bbWeight = BB_ZERO_WEIGHT;
13290                 bDest->bbFlags |= BBF_RUN_RARELY; // Set the RarelyRun flag
13291             }
13292
13293             flowList* edge2 = fgGetPredForBlock(bDest->bbJumpDest, bDest);
13294
13295             if (edge2 != nullptr)
13296             {
13297                 //
13298                 // Update the edge2 min/max weights
13299                 //
13300                 if (edge2->flEdgeWeightMin > edge1->flEdgeWeightMin)
13301                 {
13302                     edge2->flEdgeWeightMin -= edge1->flEdgeWeightMin;
13303                 }
13304                 else
13305                 {
13306                     edge2->flEdgeWeightMin = BB_ZERO_WEIGHT;
13307                 }
13308
13309                 if (edge2->flEdgeWeightMax > edge1->flEdgeWeightMin)
13310                 {
13311                     edge2->flEdgeWeightMax -= edge1->flEdgeWeightMin;
13312                 }
13313                 else
13314                 {
13315                     edge2->flEdgeWeightMax = BB_ZERO_WEIGHT;
13316                 }
13317             }
13318         }
13319
13320         // Optimize the JUMP to empty unconditional JUMP to go to the new target
13321         block->bbJumpDest = bDest->bbJumpDest;
13322
13323         fgAddRefPred(bDest->bbJumpDest, block, fgRemoveRefPred(bDest, block));
13324
13325         return true;
13326     }
13327     return false;
13328 }
13329
13330 // fgOptimizeEmptyBlock:
13331 //   Does flow optimization of an empty block (can remove it in some cases)
13332 //
13333 //  Args:
13334 //      block: an empty block
13335 //  Returns: true if we changed the code
13336
13337 bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block)
13338 {
13339     assert(block->isEmpty());
13340
13341     BasicBlock* bPrev = block->bbPrev;
13342
13343     switch (block->bbJumpKind)
13344     {
13345         case BBJ_COND:
13346         case BBJ_SWITCH:
13347         case BBJ_THROW:
13348
13349             /* can never happen */
13350             noway_assert(!"Conditional, switch, or throw block with empty body!");
13351             break;
13352
13353         case BBJ_CALLFINALLY:
13354         case BBJ_RETURN:
13355         case BBJ_EHCATCHRET:
13356         case BBJ_EHFINALLYRET:
13357         case BBJ_EHFILTERRET:
13358
13359             /* leave them as is */
13360             /* some compilers generate multiple returns and put all of them at the end -
13361              * to solve that we need the predecessor list */
13362
13363             break;
13364
13365         case BBJ_ALWAYS:
13366
13367             // A GOTO cannot be to the next block since that
13368             // should have been fixed by the  optimization above
13369             // An exception is made for a jump from Hot to Cold
13370             noway_assert(block->bbJumpDest != block->bbNext || ((bPrev != nullptr) && bPrev->isBBCallAlwaysPair()) ||
13371                          fgInDifferentRegions(block, block->bbNext));
13372
13373             /* Cannot remove the first BB */
13374             if (!bPrev)
13375             {
13376                 break;
13377             }
13378
13379             /* Do not remove a block that jumps to itself - used for while (true){} */
13380             if (block->bbJumpDest == block)
13381             {
13382                 break;
13383             }
13384
13385             /* Empty GOTO can be removed iff bPrev is BBJ_NONE */
13386             if (bPrev->bbJumpKind != BBJ_NONE)
13387             {
13388                 break;
13389             }
13390
13391             // can't allow fall through into cold code
13392             if (block->bbNext == fgFirstColdBlock)
13393             {
13394                 break;
13395             }
13396
13397             /* Can fall through since this is similar with removing
13398              * a BBJ_NONE block, only the successor is different */
13399
13400             __fallthrough;
13401
13402         case BBJ_NONE:
13403
13404             /* special case if this is the first BB */
13405             if (!bPrev)
13406             {
13407                 assert(block == fgFirstBB);
13408             }
13409             else
13410             {
13411                 /* If this block follows a BBJ_CALLFINALLY do not remove it
13412                  * (because we don't know who may jump to it) */
13413                 if (bPrev->bbJumpKind == BBJ_CALLFINALLY)
13414                 {
13415                     break;
13416                 }
13417             }
13418
13419 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13420             /* Don't remove finally targets */
13421             if (block->bbFlags & BBF_FINALLY_TARGET)
13422                 break;
13423 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13424
13425 #if FEATURE_EH_FUNCLETS
13426             /* Don't remove an empty block that is in a different EH region
13427              * from its successor block, if the block is the target of a
13428              * catch return. It is required that the return address of a
13429              * catch be in the correct EH region, for re-raise of thread
13430              * abort exceptions to work. Insert a NOP in the empty block
13431              * to ensure we generate code for the block, if we keep it.
13432              */
13433             {
13434                 BasicBlock* succBlock;
13435
13436                 if (block->bbJumpKind == BBJ_ALWAYS)
13437                 {
13438                     succBlock = block->bbJumpDest;
13439                 }
13440                 else
13441                 {
13442                     succBlock = block->bbNext;
13443                 }
13444
13445                 if ((succBlock != nullptr) && !BasicBlock::sameEHRegion(block, succBlock))
13446                 {
13447                     // The empty block and the block that follows it are in different
13448                     // EH regions. Is this a case where they can't be merged?
13449
13450                     bool okToMerge = true; // assume it's ok
13451                     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
13452                     {
13453                         if (pred->flBlock->bbJumpKind == BBJ_EHCATCHRET)
13454                         {
13455                             assert(pred->flBlock->bbJumpDest == block);
13456                             okToMerge = false; // we can't get rid of the empty block
13457                             break;
13458                         }
13459                     }
13460
13461                     if (!okToMerge)
13462                     {
13463                         // Insert a NOP in the empty block to ensure we generate code
13464                         // for the catchret target in the right EH region.
13465                         GenTree* nop = new (this, GT_NO_OP) GenTree(GT_NO_OP, TYP_VOID);
13466
13467                         if (block->IsLIR())
13468                         {
13469                             LIR::AsRange(block).InsertAtEnd(nop);
13470                         }
13471                         else
13472                         {
13473                             GenTreePtr nopStmt = fgInsertStmtAtEnd(block, nop);
13474                             fgSetStmtSeq(nopStmt);
13475                             gtSetStmtInfo(nopStmt);
13476                         }
13477
13478 #ifdef DEBUG
13479                         if (verbose)
13480                         {
13481                             printf("\nKeeping empty block BB%02u - it is the target of a catch return\n", block->bbNum);
13482                         }
13483 #endif // DEBUG
13484
13485                         break; // go to the next block
13486                     }
13487                 }
13488             }
13489 #endif // FEATURE_EH_FUNCLETS
13490
13491             if (!ehCanDeleteEmptyBlock(block))
13492             {
13493                 // We're not allowed to remove this block due to reasons related to the EH table.
13494                 break;
13495             }
13496
13497             /* special case if this is the last BB */
13498             if (block == fgLastBB)
13499             {
13500                 if (!bPrev)
13501                 {
13502                     break;
13503                 }
13504                 fgLastBB = bPrev;
13505             }
13506
13507             /* Remove the block */
13508             compCurBB = block;
13509             fgRemoveBlock(block, false);
13510             return true;
13511
13512         default:
13513             noway_assert(!"Unexpected bbJumpKind");
13514             break;
13515     }
13516     return false;
13517 }
13518
13519 // fgOptimizeSwitchBranches:
13520 //   Does flow optimization for a switch - bypasses jumps to empty unconditional branches,
13521 //      and transforms degenerate switch cases like those with 1 or 2 targets
13522 //
13523 //  Args:
13524 //      block: BasicBlock that contains the switch
13525 //  Returns: true if we changed the code
13526 //
13527 bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block)
13528 {
13529     assert(block->bbJumpKind == BBJ_SWITCH);
13530
13531     unsigned     jmpCnt = block->bbJumpSwt->bbsCount;
13532     BasicBlock** jmpTab = block->bbJumpSwt->bbsDstTab;
13533     BasicBlock*  bNewDest; // the new jump target for the current switch case
13534     BasicBlock*  bDest;
13535     bool         returnvalue = false;
13536
13537     do
13538     {
13539     REPEAT_SWITCH:;
13540         bDest    = *jmpTab;
13541         bNewDest = bDest;
13542
13543         // Do we have a JUMP to an empty unconditional JUMP block?
13544         if (bDest->isEmpty() && (bDest->bbJumpKind == BBJ_ALWAYS) &&
13545             (bDest != bDest->bbJumpDest)) // special case for self jumps
13546         {
13547             bool optimizeJump = true;
13548
13549             // We do not optimize jumps between two different try regions.
13550             // However jumping to a block that is not in any try region is OK
13551             //
13552             if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
13553             {
13554                 optimizeJump = false;
13555             }
13556
13557             // If we are optimize using real profile weights
13558             // then don't optimize a switch jump to an unconditional jump
13559             // until after we have computed the edge weights
13560             //
13561             if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed)
13562             {
13563                 fgNeedsUpdateFlowGraph = true;
13564                 optimizeJump           = false;
13565             }
13566
13567             if (optimizeJump)
13568             {
13569                 bNewDest = bDest->bbJumpDest;
13570 #ifdef DEBUG
13571                 if (verbose)
13572                 {
13573                     printf("\nOptimizing a switch jump to an empty block with an unconditional jump (BB%02u -> BB%02u "
13574                            "-> BB%02u)\n",
13575                            block->bbNum, bDest->bbNum, bNewDest->bbNum);
13576                 }
13577 #endif // DEBUG
13578             }
13579         }
13580
13581         if (bNewDest != bDest)
13582         {
13583             //
13584             // When we optimize a branch to branch we need to update the profile weight
13585             // of bDest by subtracting out the block/edge weight of the path that is being optimized.
13586             //
13587             if (fgIsUsingProfileWeights() && bDest->hasProfileWeight())
13588             {
13589                 if (fgHaveValidEdgeWeights)
13590                 {
13591                     flowList*            edge                = fgGetPredForBlock(bDest, block);
13592                     BasicBlock::weight_t branchThroughWeight = edge->flEdgeWeightMin;
13593
13594                     if (bDest->bbWeight > branchThroughWeight)
13595                     {
13596                         bDest->bbWeight -= branchThroughWeight;
13597                     }
13598                     else
13599                     {
13600                         bDest->bbWeight = BB_ZERO_WEIGHT;
13601                         bDest->bbFlags |= BBF_RUN_RARELY;
13602                     }
13603                 }
13604             }
13605
13606             // Update the switch jump table
13607             *jmpTab = bNewDest;
13608
13609             // Maintain, if necessary, the set of unique targets of "block."
13610             UpdateSwitchTableTarget(block, bDest, bNewDest);
13611
13612             fgAddRefPred(bNewDest, block, fgRemoveRefPred(bDest, block));
13613
13614             // we optimized a Switch label - goto REPEAT_SWITCH to follow this new jump
13615             returnvalue = true;
13616
13617             goto REPEAT_SWITCH;
13618         }
13619     } while (++jmpTab, --jmpCnt);
13620
13621     GenTreeStmt* switchStmt = nullptr;
13622     LIR::Range*  blockRange = nullptr;
13623
13624     GenTree* switchTree;
13625     if (block->IsLIR())
13626     {
13627         blockRange = &LIR::AsRange(block);
13628         switchTree = blockRange->LastNode();
13629
13630         assert(switchTree->OperGet() == GT_SWITCH_TABLE);
13631     }
13632     else
13633     {
13634         switchStmt = block->lastStmt();
13635         switchTree = switchStmt->gtStmtExpr;
13636
13637         assert(switchTree->OperGet() == GT_SWITCH);
13638     }
13639
13640     noway_assert(switchTree->gtType == TYP_VOID);
13641
13642     // At this point all of the case jump targets have been updated such
13643     // that none of them go to block that is an empty unconditional block
13644     //
13645     jmpTab = block->bbJumpSwt->bbsDstTab;
13646     jmpCnt = block->bbJumpSwt->bbsCount;
13647     // Now check for two trivial switch jumps.
13648     //
13649     if (block->NumSucc(this) == 1)
13650     {
13651         // Use BBJ_ALWAYS for a switch with only a default clause, or with only one unique successor.
13652         BasicBlock* uniqueSucc = jmpTab[0];
13653
13654 #ifdef DEBUG
13655         if (verbose)
13656         {
13657             printf("\nRemoving a switch jump with a single target (BB%02u)\n", block->bbNum);
13658             printf("BEFORE:\n");
13659         }
13660 #endif // DEBUG
13661
13662         if (block->IsLIR())
13663         {
13664             bool               isClosed;
13665             unsigned           sideEffects;
13666             LIR::ReadOnlyRange switchTreeRange = blockRange->GetTreeRange(switchTree, &isClosed, &sideEffects);
13667
13668             // The switch tree should form a contiguous, side-effect free range by construction. See
13669             // Lowering::LowerSwitch for details.
13670             assert(isClosed);
13671             assert((sideEffects & GTF_ALL_EFFECT) == 0);
13672
13673             blockRange->Delete(this, block, std::move(switchTreeRange));
13674         }
13675         else
13676         {
13677             /* check for SIDE_EFFECTS */
13678             if (switchTree->gtFlags & GTF_SIDE_EFFECT)
13679             {
13680                 /* Extract the side effects from the conditional */
13681                 GenTreePtr sideEffList = nullptr;
13682
13683                 gtExtractSideEffList(switchTree, &sideEffList);
13684
13685                 if (sideEffList == nullptr)
13686                 {
13687                     goto NO_SWITCH_SIDE_EFFECT;
13688                 }
13689
13690                 noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
13691
13692 #ifdef DEBUG
13693                 if (verbose)
13694                 {
13695                     printf("\nSwitch expression has side effects! Extracting side effects...\n");
13696                     gtDispTree(switchTree);
13697                     printf("\n");
13698                     gtDispTree(sideEffList);
13699                     printf("\n");
13700                 }
13701 #endif // DEBUG
13702
13703                 /* Replace the conditional statement with the list of side effects */
13704                 noway_assert(sideEffList->gtOper != GT_STMT);
13705                 noway_assert(sideEffList->gtOper != GT_SWITCH);
13706
13707                 switchStmt->gtStmtExpr = sideEffList;
13708
13709                 if (fgStmtListThreaded)
13710                 {
13711                     /* Update the lclvar ref counts */
13712                     compCurBB = block;
13713                     fgUpdateRefCntForExtract(switchTree, sideEffList);
13714
13715                     /* Update ordering, costs, FP levels, etc. */
13716                     gtSetStmtInfo(switchStmt);
13717
13718                     /* Re-link the nodes for this statement */
13719                     fgSetStmtSeq(switchStmt);
13720                 }
13721             }
13722             else
13723             {
13724
13725             NO_SWITCH_SIDE_EFFECT:
13726
13727                 /* conditional has NO side effect - remove it */
13728                 fgRemoveStmt(block, switchStmt);
13729             }
13730         }
13731
13732         // Change the switch jump into a BBJ_ALWAYS
13733         block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0];
13734         block->bbJumpKind = BBJ_ALWAYS;
13735         if (jmpCnt > 1)
13736         {
13737             for (unsigned i = 1; i < jmpCnt; ++i)
13738             {
13739                 (void)fgRemoveRefPred(jmpTab[i], block);
13740             }
13741         }
13742
13743         return true;
13744     }
13745     else if (block->bbJumpSwt->bbsCount == 2 && block->bbJumpSwt->bbsDstTab[1] == block->bbNext)
13746     {
13747         /* Use a BBJ_COND(switchVal==0) for a switch with only one
13748            significant clause besides the default clause, if the
13749            default clause is bbNext */
13750         GenTree* switchVal = switchTree->gtOp.gtOp1;
13751         noway_assert(genActualTypeIsIntOrI(switchVal->TypeGet()));
13752
13753 #ifndef LEGACY_BACKEND
13754         // If we are in LIR, remove the jump table from the block.
13755         if (block->IsLIR())
13756         {
13757             GenTree* jumpTable = switchTree->gtOp.gtOp2;
13758             assert(jumpTable->OperGet() == GT_JMPTABLE);
13759             blockRange->Remove(jumpTable);
13760         }
13761 #endif
13762
13763         // Change the GT_SWITCH(switchVal) into GT_JTRUE(GT_EQ(switchVal==0)).
13764         // Also mark the node as GTF_DONT_CSE as further down JIT is not capable of handling it.
13765         // For example CSE could determine that the expression rooted at GT_EQ is a candidate cse and
13766         // replace it with a COMMA node.  In such a case we will end up with GT_JTRUE node pointing to
13767         // a COMMA node which results in noway asserts in fgMorphSmpOp(), optAssertionGen() and rpPredictTreeRegUse().
13768         // For the same reason fgMorphSmpOp() marks GT_JTRUE nodes with RELOP children as GTF_DONT_CSE.
13769         CLANG_FORMAT_COMMENT_ANCHOR;
13770
13771 #ifdef DEBUG
13772         if (verbose)
13773         {
13774             printf("\nConverting a switch (BB%02u) with only one significant clause besides a default target to a "
13775                    "conditional branch\n",
13776                    block->bbNum);
13777         }
13778 #endif // DEBUG
13779
13780         switchTree->ChangeOper(GT_JTRUE);
13781         GenTree* zeroConstNode = gtNewZeroConNode(genActualType(switchVal->TypeGet()));
13782         GenTree* condNode      = gtNewOperNode(GT_EQ, TYP_INT, switchVal, zeroConstNode);
13783         switchTree->gtOp.gtOp1 = condNode;
13784         switchTree->gtOp.gtOp1->gtFlags |= (GTF_RELOP_JMP_USED | GTF_DONT_CSE);
13785
13786         if (block->IsLIR())
13787         {
13788             blockRange->InsertAfter(switchVal, zeroConstNode, condNode);
13789         }
13790         else
13791         {
13792             // Re-link the nodes for this statement.
13793             fgSetStmtSeq(switchStmt);
13794         }
13795
13796         block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0];
13797         block->bbJumpKind = BBJ_COND;
13798
13799         return true;
13800     }
13801     return returnvalue;
13802 }
13803
13804 // fgBlockEndFavorsTailDuplication:
13805 //     Heuristic function that returns true if this block ends in a statement that looks favorable
13806 //     for tail-duplicating its successor (such as assigning a constant to a local).
13807 //  Args:
13808 //      block: BasicBlock we are considering duplicating the successor of
13809 //  Returns:
13810 //      true if it seems like a good idea
13811 //
13812 bool Compiler::fgBlockEndFavorsTailDuplication(BasicBlock* block)
13813 {
13814     if (block->isRunRarely())
13815     {
13816         return false;
13817     }
13818
13819     if (!block->lastStmt())
13820     {
13821         return false;
13822     }
13823     else
13824     {
13825         // Tail duplication tends to pay off when the last statement
13826         // is an assignment of a constant, arraylength, or a relop.
13827         // This is because these statements produce information about values
13828         // that would otherwise be lost at the upcoming merge point.
13829
13830         GenTreeStmt* lastStmt = block->lastStmt();
13831         GenTree*     tree     = lastStmt->gtStmtExpr;
13832         if (tree->gtOper != GT_ASG)
13833         {
13834             return false;
13835         }
13836
13837         if (tree->OperIsBlkOp())
13838         {
13839             return false;
13840         }
13841
13842         GenTree* op2 = tree->gtOp.gtOp2;
13843         if (op2->gtOper != GT_ARR_LENGTH && !op2->OperIsConst() && ((op2->OperKind() & GTK_RELOP) == 0))
13844         {
13845             return false;
13846         }
13847     }
13848     return true;
13849 }
13850
13851 // fgBlockIsGoodTailDuplicationCandidate:
13852 //     Heuristic function that examines a block (presumably one that is a merge point) to determine
13853 //     if it should be duplicated.
13854 // args:
13855 //     target - the tail block (candidate for duplication)
13856 // returns:
13857 //     true if this block seems like a good candidate for duplication
13858 //
13859 bool Compiler::fgBlockIsGoodTailDuplicationCandidate(BasicBlock* target)
13860 {
13861     GenTreeStmt* stmt = target->FirstNonPhiDef();
13862
13863     // Here we are looking for blocks with a single statement feeding a conditional branch.
13864     // These blocks are small, and when duplicated onto the tail of blocks that end in
13865     // assignments, there is a high probability of the branch completely going away.
13866
13867     // This is by no means the only kind of tail that it is beneficial to duplicate,
13868     // just the only one we recognize for now.
13869
13870     if (stmt != target->lastStmt())
13871     {
13872         return false;
13873     }
13874
13875     if (target->bbJumpKind != BBJ_COND)
13876     {
13877         return false;
13878     }
13879
13880     GenTree* tree = stmt->gtStmtExpr;
13881
13882     if (tree->gtOper != GT_JTRUE)
13883     {
13884         return false;
13885     }
13886
13887     // must be some kind of relational operator
13888     GenTree* cond = tree->gtOp.gtOp1;
13889     if (!(cond->OperKind() & GTK_RELOP))
13890     {
13891         return false;
13892     }
13893
13894     // op1 must be some combinations of casts of local or constant
13895     GenTree* op1 = cond->gtOp.gtOp1;
13896     while (op1->gtOper == GT_CAST)
13897     {
13898         op1 = op1->gtOp.gtOp1;
13899     }
13900     if (!op1->IsLocal() && !op1->OperIsConst())
13901     {
13902         return false;
13903     }
13904
13905     // op2 must be some combinations of casts of local or constant
13906     GenTree* op2 = cond->gtOp.gtOp2;
13907     while (op2->gtOper == GT_CAST)
13908     {
13909         op2 = op2->gtOp.gtOp1;
13910     }
13911     if (!op2->IsLocal() && !op2->OperIsConst())
13912     {
13913         return false;
13914     }
13915
13916     return true;
13917 }
13918
13919 // fgOptimizeUncondBranchToSimpleCond:
13920 //    For a block which has an unconditional branch, look to see if its target block
13921 //    is a good candidate for tail duplication, and if so do that duplication.
13922 //
13923 // Args:
13924 //    block  - block with uncond branch
13925 //    target - block which is target of first block
13926 //
13927 // returns: true if changes were made
13928
13929 bool Compiler::fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* target)
13930 {
13931     assert(block->bbJumpKind == BBJ_ALWAYS);
13932     assert(block->bbJumpDest == target);
13933
13934     // TODO-Review: OK if they are in the same region?
13935     if (compHndBBtabCount > 0)
13936     {
13937         return false;
13938     }
13939
13940     if (!fgBlockIsGoodTailDuplicationCandidate(target))
13941     {
13942         return false;
13943     }
13944
13945     if (!fgBlockEndFavorsTailDuplication(block))
13946     {
13947         return false;
13948     }
13949
13950     // NOTE: we do not currently hit this assert because this function is only called when
13951     // `fgUpdateFlowGraph` has been called with `doTailDuplication` set to true, and the
13952     // backend always calls `fgUpdateFlowGraph` with `doTailDuplication` set to false.
13953     assert(!block->IsLIR());
13954
13955     GenTreeStmt* stmt = target->FirstNonPhiDef();
13956     assert(stmt == target->lastStmt());
13957
13958     // Duplicate the target block at the end of this block
13959
13960     GenTree* cloned = gtCloneExpr(stmt->gtStmtExpr);
13961     noway_assert(cloned);
13962     GenTree* jmpStmt = gtNewStmt(cloned);
13963
13964     block->bbJumpKind = BBJ_COND;
13965     block->bbJumpDest = target->bbJumpDest;
13966     fgAddRefPred(block->bbJumpDest, block);
13967     fgRemoveRefPred(target, block);
13968
13969     // add an unconditional block after this block to jump to the target block's fallthrough block
13970
13971     BasicBlock* next = fgNewBBafter(BBJ_ALWAYS, block, true);
13972
13973     // The new block 'next' will inherit its weight from 'block'
13974     next->inheritWeight(block);
13975     next->bbJumpDest = target->bbNext;
13976     target->bbNext->bbFlags |= BBF_JMP_TARGET;
13977     fgAddRefPred(next, block);
13978     fgAddRefPred(next->bbJumpDest, next);
13979
13980 #ifdef DEBUG
13981     if (verbose)
13982     {
13983         printf("fgOptimizeUncondBranchToSimpleCond(from BB%02u to cond BB%02u), created new uncond BB%02u\n",
13984                block->bbNum, target->bbNum, next->bbNum);
13985     }
13986 #endif // DEBUG
13987
13988     if (fgStmtListThreaded)
13989     {
13990         gtSetStmtInfo(jmpStmt);
13991     }
13992
13993     fgInsertStmtAtEnd(block, jmpStmt);
13994
13995     return true;
13996 }
13997
13998 // fgOptimizeBranchToNext:
13999 //    Optimize a block which has a branch to the following block
14000 // Args:
14001 //    block - block with a branch
14002 //    bNext - block which is both next and the target of the first block
14003 //    bPrev - block which is prior to the first block
14004 //
14005 // returns: true if changes were made
14006 //
14007 bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev)
14008 {
14009     assert(block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS);
14010     assert(block->bbJumpDest == bNext);
14011     assert(block->bbNext == bNext);
14012     assert(block->bbPrev == bPrev);
14013
14014     if (block->bbJumpKind == BBJ_ALWAYS)
14015     {
14016         // We can't remove it if it is a branch from hot => cold
14017         if (!fgInDifferentRegions(block, bNext))
14018         {
14019             // We can't remove if it is marked as BBF_KEEP_BBJ_ALWAYS
14020             if (!(block->bbFlags & BBF_KEEP_BBJ_ALWAYS))
14021             {
14022                 // We can't remove if the BBJ_ALWAYS is part of a BBJ_CALLFINALLY pair
14023                 if ((bPrev == nullptr) || !bPrev->isBBCallAlwaysPair())
14024                 {
14025                     /* the unconditional jump is to the next BB  */
14026                     block->bbJumpKind = BBJ_NONE;
14027                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
14028 #ifdef DEBUG
14029                     if (verbose)
14030                     {
14031                         printf("\nRemoving unconditional jump to next block (BB%02u -> BB%02u) (converted BB%02u to "
14032                                "fall-through)\n",
14033                                block->bbNum, bNext->bbNum, block->bbNum);
14034                     }
14035 #endif // DEBUG
14036                     return true;
14037                 }
14038             }
14039         }
14040     }
14041     else
14042     {
14043         /* remove the conditional statement at the end of block */
14044         noway_assert(block->bbJumpKind == BBJ_COND);
14045         noway_assert(block->bbTreeList);
14046
14047 #ifdef DEBUG
14048         if (verbose)
14049         {
14050             printf("\nRemoving conditional jump to next block (BB%02u -> BB%02u)\n", block->bbNum, bNext->bbNum);
14051         }
14052 #endif // DEBUG
14053
14054         if (block->IsLIR())
14055         {
14056             LIR::Range& blockRange = LIR::AsRange(block);
14057             GenTree*    jmp        = blockRange.LastNode();
14058             assert(jmp->OperIsConditionalJump());
14059
14060             bool               isClosed;
14061             unsigned           sideEffects;
14062             LIR::ReadOnlyRange jmpRange = blockRange.GetTreeRange(jmp, &isClosed, &sideEffects);
14063
14064             // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable
14065             //            diffs compared to the existing backend.
14066             if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0))
14067             {
14068                 // If the jump and its operands form a contiguous, side-effect-free range,
14069                 // remove them.
14070                 blockRange.Delete(this, block, std::move(jmpRange));
14071             }
14072             else
14073             {
14074                 // Otherwise, just remove the jump node itself.
14075                 blockRange.Remove(jmp);
14076             }
14077         }
14078         else
14079         {
14080             GenTreeStmt* cond = block->lastStmt();
14081             noway_assert(cond->gtStmtExpr->gtOper == GT_JTRUE);
14082
14083             /* check for SIDE_EFFECTS */
14084             if (cond->gtStmtExpr->gtFlags & GTF_SIDE_EFFECT)
14085             {
14086                 /* Extract the side effects from the conditional */
14087                 GenTreePtr sideEffList = nullptr;
14088
14089                 gtExtractSideEffList(cond->gtStmtExpr, &sideEffList);
14090
14091                 if (sideEffList == nullptr)
14092                 {
14093                     compCurBB = block;
14094                     fgRemoveStmt(block, cond);
14095                 }
14096                 else
14097                 {
14098                     noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
14099 #ifdef DEBUG
14100                     if (verbose)
14101                     {
14102                         printf("\nConditional has side effects! Extracting side effects...\n");
14103                         gtDispTree(cond);
14104                         printf("\n");
14105                         gtDispTree(sideEffList);
14106                         printf("\n");
14107                     }
14108 #endif // DEBUG
14109
14110                     /* Replace the conditional statement with the list of side effects */
14111                     noway_assert(sideEffList->gtOper != GT_STMT);
14112                     noway_assert(sideEffList->gtOper != GT_JTRUE);
14113
14114                     cond->gtStmtExpr = sideEffList;
14115
14116                     if (fgStmtListThreaded)
14117                     {
14118                         /* Update the lclvar ref counts */
14119                         compCurBB = block;
14120                         fgUpdateRefCntForExtract(cond->gtStmtExpr, sideEffList);
14121
14122                         /* Update ordering, costs, FP levels, etc. */
14123                         gtSetStmtInfo(cond);
14124
14125                         /* Re-link the nodes for this statement */
14126                         fgSetStmtSeq(cond);
14127                     }
14128                 }
14129             }
14130             else
14131             {
14132                 compCurBB = block;
14133                 /* conditional has NO side effect - remove it */
14134                 fgRemoveStmt(block, cond);
14135             }
14136         }
14137
14138         /* Conditional is gone - simply fall into the next block */
14139
14140         block->bbJumpKind = BBJ_NONE;
14141         block->bbFlags &= ~BBF_NEEDS_GCPOLL;
14142
14143         /* Update bbRefs and bbNum - Conditional predecessors to the same
14144          * block are counted twice so we have to remove one of them */
14145
14146         noway_assert(bNext->countOfInEdges() > 1);
14147         fgRemoveRefPred(bNext, block);
14148
14149         return true;
14150     }
14151     return false;
14152 }
14153
14154 /*****************************************************************************
14155  *
14156  *  Function called to optimize an unconditional branch that branches
14157  *  to a conditional branch.
14158  *  Currently we require that the conditional branch jump back to the
14159  *  block that follows the unconditional branch.
14160  *
14161  *  We can improve the code execution and layout by concatenating a copy
14162  *  of the conditional branch block at the end of the conditional branch
14163  *  and reversing the sense of the branch.
14164  *
14165  *  This is only done when the amount of code to be copied is smaller than
14166  *  our calculated threshold in maxDupCostSz.
14167  *
14168  */
14169
14170 bool Compiler::fgOptimizeBranch(BasicBlock* bJump)
14171 {
14172     if (opts.MinOpts())
14173     {
14174         return false;
14175     }
14176
14177     if (bJump->bbJumpKind != BBJ_ALWAYS)
14178     {
14179         return false;
14180     }
14181
14182     if (bJump->bbFlags & BBF_KEEP_BBJ_ALWAYS)
14183     {
14184         return false;
14185     }
14186
14187     // Don't hoist a conditional branch into the scratch block; we'd prefer it stay
14188     // either BBJ_NONE or BBJ_ALWAYS.
14189     if (fgBBisScratch(bJump))
14190     {
14191         return false;
14192     }
14193
14194     BasicBlock* bDest = bJump->bbJumpDest;
14195
14196     if (bDest->bbJumpKind != BBJ_COND)
14197     {
14198         return false;
14199     }
14200
14201     if (bDest->bbJumpDest != bJump->bbNext)
14202     {
14203         return false;
14204     }
14205
14206     // 'bJump' must be in the same try region as the condition, since we're going to insert
14207     // a duplicated condition in 'bJump', and the condition might include exception throwing code.
14208     if (!BasicBlock::sameTryRegion(bJump, bDest))
14209     {
14210         return false;
14211     }
14212
14213     // do not jump into another try region
14214     BasicBlock* bDestNext = bDest->bbNext;
14215     if (bDestNext->hasTryIndex() && !BasicBlock::sameTryRegion(bJump, bDestNext))
14216     {
14217         return false;
14218     }
14219
14220     // This function is only called by fgReorderBlocks, which we do not run in the backend.
14221     // If we wanted to run block reordering in the backend, we would need to be able to
14222     // calculate cost information for LIR on a per-node basis in order for this function
14223     // to work.
14224     assert(!bJump->IsLIR());
14225     assert(!bDest->IsLIR());
14226
14227     GenTreeStmt* stmt;
14228     unsigned     estDupCostSz = 0;
14229     for (stmt = bDest->firstStmt(); stmt; stmt = stmt->gtNextStmt)
14230     {
14231         GenTreePtr expr = stmt->gtStmtExpr;
14232
14233         /* We call gtPrepareCost to measure the cost of duplicating this tree */
14234         gtPrepareCost(expr);
14235
14236         estDupCostSz += expr->gtCostSz;
14237     }
14238
14239     bool                 allProfileWeightsAreValid = false;
14240     BasicBlock::weight_t weightJump                = bJump->bbWeight;
14241     BasicBlock::weight_t weightDest                = bDest->bbWeight;
14242     BasicBlock::weight_t weightNext                = bJump->bbNext->bbWeight;
14243     bool                 rareJump                  = bJump->isRunRarely();
14244     bool                 rareDest                  = bDest->isRunRarely();
14245     bool                 rareNext                  = bJump->bbNext->isRunRarely();
14246
14247     // If we have profile data then we calculate the number of time
14248     // the loop will iterate into loopIterations
14249     if (fgIsUsingProfileWeights())
14250     {
14251         // Only rely upon the profile weight when all three of these blocks
14252         // have either good profile weights or are rarelyRun
14253         //
14254         if ((bJump->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)) &&
14255             (bDest->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)) &&
14256             (bJump->bbNext->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)))
14257         {
14258             allProfileWeightsAreValid = true;
14259
14260             if ((weightJump * 100) < weightDest)
14261             {
14262                 rareJump = true;
14263             }
14264
14265             if ((weightNext * 100) < weightDest)
14266             {
14267                 rareNext = true;
14268             }
14269
14270             if (((weightDest * 100) < weightJump) && ((weightDest * 100) < weightNext))
14271             {
14272                 rareDest = true;
14273             }
14274         }
14275     }
14276
14277     unsigned maxDupCostSz = 6;
14278
14279     //
14280     // Branches between the hot and rarely run regions
14281     // should be minimized.  So we allow a larger size
14282     //
14283     if (rareDest != rareJump)
14284     {
14285         maxDupCostSz += 6;
14286     }
14287
14288     if (rareDest != rareNext)
14289     {
14290         maxDupCostSz += 6;
14291     }
14292
14293     //
14294     // We we are ngen-ing:
14295     // If the uncondional branch is a rarely run block then
14296     // we are willing to have more code expansion since we
14297     // won't be running code from this page
14298     //
14299     if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
14300     {
14301         if (rareJump)
14302         {
14303             maxDupCostSz *= 2;
14304         }
14305     }
14306
14307     // If the compare has too high cost then we don't want to dup
14308
14309     bool costIsTooHigh = (estDupCostSz > maxDupCostSz);
14310
14311 #ifdef DEBUG
14312     if (verbose)
14313     {
14314         printf("\nDuplication of the conditional block BB%02u (always branch from BB%02u) %s, because the cost of "
14315                "duplication (%i) is %s than %i,"
14316                " validProfileWeights = %s\n",
14317                bDest->bbNum, bJump->bbNum, costIsTooHigh ? "not done" : "performed", estDupCostSz,
14318                costIsTooHigh ? "greater" : "less or equal", maxDupCostSz, allProfileWeightsAreValid ? "true" : "false");
14319     }
14320 #endif // DEBUG
14321
14322     if (costIsTooHigh)
14323     {
14324         return false;
14325     }
14326
14327     /* Looks good - duplicate the conditional block */
14328
14329     GenTree* newStmtList     = nullptr; // new stmt list to be added to bJump
14330     GenTree* newStmtLast     = nullptr;
14331     bool     cloneExprFailed = false;
14332
14333     /* Visit all the statements in bDest */
14334
14335     for (GenTree* curStmt = bDest->bbTreeList; curStmt; curStmt = curStmt->gtNext)
14336     {
14337         /* Clone/substitute the expression */
14338
14339         stmt = gtCloneExpr(curStmt)->AsStmt();
14340
14341         // cloneExpr doesn't handle everything
14342
14343         if (stmt == nullptr)
14344         {
14345             cloneExprFailed = true;
14346             break;
14347         }
14348
14349         /* Append the expression to our list */
14350
14351         if (newStmtList != nullptr)
14352         {
14353             newStmtLast->gtNext = stmt;
14354         }
14355         else
14356         {
14357             newStmtList = stmt;
14358         }
14359
14360         stmt->gtPrev = newStmtLast;
14361         newStmtLast  = stmt;
14362     }
14363
14364     if (cloneExprFailed)
14365     {
14366         return false;
14367     }
14368
14369     noway_assert(newStmtLast != nullptr);
14370     noway_assert(stmt != nullptr);
14371     noway_assert(stmt->gtOper == GT_STMT);
14372
14373     if ((newStmtLast == nullptr) || (stmt == nullptr) || (stmt->gtOper != GT_STMT))
14374     {
14375         return false;
14376     }
14377
14378     /* Get to the condition node from the statement tree */
14379
14380     GenTreePtr condTree = stmt->gtStmtExpr;
14381     noway_assert(condTree->gtOper == GT_JTRUE);
14382
14383     if (condTree->gtOper != GT_JTRUE)
14384     {
14385         return false;
14386     }
14387
14388     //
14389     // Set condTree to the operand to the GT_JTRUE
14390     //
14391     condTree = condTree->gtOp.gtOp1;
14392
14393     //
14394     // This condTree has to be a RelOp comparison
14395     //
14396     if (condTree->OperIsCompare() == false)
14397     {
14398         return false;
14399     }
14400
14401     // Bump up the ref-counts of any variables in 'stmt'
14402     fgUpdateRefCntForClone(bJump, stmt->gtStmtExpr);
14403
14404     //
14405     // Find the last statement in the bJump block
14406     //
14407     GenTreeStmt* lastStmt = nullptr;
14408     for (stmt = bJump->firstStmt(); stmt; stmt = stmt->gtNextStmt)
14409     {
14410         lastStmt = stmt;
14411     }
14412     stmt = bJump->firstStmt();
14413
14414     /* Join the two linked lists */
14415     newStmtLast->gtNext = nullptr;
14416
14417     if (lastStmt != nullptr)
14418     {
14419         stmt->gtPrev        = newStmtLast;
14420         lastStmt->gtNext    = newStmtList;
14421         newStmtList->gtPrev = lastStmt;
14422     }
14423     else
14424     {
14425         bJump->bbTreeList   = newStmtList;
14426         newStmtList->gtPrev = newStmtLast;
14427     }
14428
14429     //
14430     // Reverse the sense of the compare
14431     //
14432     gtReverseCond(condTree);
14433
14434     // We need to update the following flags of the bJump block if they were set in the bDest block
14435     bJump->bbFlags |=
14436         (bDest->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_VTABREF));
14437
14438     bJump->bbJumpKind = BBJ_COND;
14439     bJump->bbJumpDest = bDest->bbNext;
14440
14441     /* Mark the jump dest block as being a jump target */
14442     bJump->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
14443
14444     /* Update bbRefs and bbPreds */
14445
14446     // bJump now falls through into the next block
14447     //
14448     fgAddRefPred(bJump->bbNext, bJump);
14449
14450     // bJump no longer jumps to bDest
14451     //
14452     fgRemoveRefPred(bDest, bJump);
14453
14454     // bJump now jumps to bDest->bbNext
14455     //
14456     fgAddRefPred(bDest->bbNext, bJump);
14457
14458     if (weightJump > 0)
14459     {
14460         if (allProfileWeightsAreValid)
14461         {
14462             if (weightDest > weightJump)
14463             {
14464                 bDest->bbWeight = (weightDest - weightJump);
14465             }
14466             else if (!bDest->isRunRarely())
14467             {
14468                 bDest->bbWeight = BB_UNITY_WEIGHT;
14469             }
14470         }
14471         else
14472         {
14473             BasicBlock::weight_t newWeightDest    = 0;
14474             BasicBlock::weight_t unloopWeightDest = 0;
14475
14476             if (weightDest > weightJump)
14477             {
14478                 newWeightDest = (weightDest - weightJump);
14479             }
14480             if (weightDest >= (BB_LOOP_WEIGHT * BB_UNITY_WEIGHT) / 2)
14481             {
14482                 newWeightDest = (weightDest * 2) / (BB_LOOP_WEIGHT * BB_UNITY_WEIGHT);
14483             }
14484             if ((newWeightDest > 0) || (unloopWeightDest > 0))
14485             {
14486                 bDest->bbWeight = Max(newWeightDest, unloopWeightDest);
14487             }
14488         }
14489     }
14490
14491 #if DEBUG
14492     if (verbose)
14493     {
14494         printf("\nAfter this change in fgOptimizeBranch");
14495         fgDispBasicBlocks(verboseTrees);
14496         printf("\n");
14497     }
14498 #endif // DEBUG
14499
14500     return true;
14501 }
14502
14503 /*****************************************************************************
14504  *
14505  *  Function called to optimize switch statements
14506  */
14507
14508 bool Compiler::fgOptimizeSwitchJumps()
14509 {
14510     bool result = false; // Our return value
14511
14512 #if 0
14513     // TODO-CQ: Add switch jump optimizations?
14514     if (!fgHasSwitch)
14515         return false;
14516
14517     if (!fgHaveValidEdgeWeights)
14518         return false;
14519
14520     for (BasicBlock* bSrc = fgFirstBB; bSrc != NULL; bSrc = bSrc->bbNext)
14521     {
14522         if (bSrc->bbJumpKind == BBJ_SWITCH)
14523         {
14524             unsigned        jumpCnt; jumpCnt = bSrc->bbJumpSwt->bbsCount;
14525             BasicBlock**    jumpTab; jumpTab = bSrc->bbJumpSwt->bbsDstTab;
14526
14527             do
14528             {
14529                 BasicBlock*   bDst       = *jumpTab;
14530                 flowList*     edgeToDst  = fgGetPredForBlock(bDst, bSrc);
14531                 double        outRatio   = (double) edgeToDst->flEdgeWeightMin  / (double) bSrc->bbWeight;
14532
14533                 if (outRatio >= 0.60)
14534                 {
14535                     // straighten switch here...
14536                 }
14537             }
14538             while (++jumpTab, --jumpCnt);
14539         }
14540     }
14541 #endif
14542
14543     return result;
14544 }
14545
14546 #ifdef _PREFAST_
14547 #pragma warning(push)
14548 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
14549 #endif
14550 /*****************************************************************************
14551  *
14552  *  Function called to reorder the flowgraph of BasicBlocks such that any
14553  *  rarely run blocks are placed at the end of the block list.
14554  *  If we have profile information we also use that information to reverse
14555  *  all conditional jumps that would benefit.
14556  */
14557
14558 void Compiler::fgReorderBlocks()
14559 {
14560     noway_assert(opts.compDbgCode == false);
14561
14562 #if FEATURE_EH_FUNCLETS
14563     assert(fgFuncletsCreated);
14564 #endif // FEATURE_EH_FUNCLETS
14565
14566     // We can't relocate anything if we only have one block
14567     if (fgFirstBB->bbNext == nullptr)
14568     {
14569         return;
14570     }
14571
14572     bool newRarelyRun      = false;
14573     bool movedBlocks       = false;
14574     bool optimizedSwitches = false;
14575
14576     // First let us expand the set of run rarely blocks
14577     newRarelyRun |= fgExpandRarelyRunBlocks();
14578
14579 #if !FEATURE_EH_FUNCLETS
14580     movedBlocks |= fgRelocateEHRegions();
14581 #endif // !FEATURE_EH_FUNCLETS
14582
14583     //
14584     // If we are using profile weights we can change some
14585     // switch jumps into conditional test and jump
14586     //
14587     if (fgIsUsingProfileWeights())
14588     {
14589         //
14590         // Note that this is currently not yet implemented
14591         //
14592         optimizedSwitches = fgOptimizeSwitchJumps();
14593         if (optimizedSwitches)
14594         {
14595             fgUpdateFlowGraph();
14596         }
14597     }
14598
14599 #ifdef DEBUG
14600     if (verbose)
14601     {
14602         printf("*************** In fgReorderBlocks()\n");
14603
14604         printf("\nInitial BasicBlocks");
14605         fgDispBasicBlocks(verboseTrees);
14606         printf("\n");
14607     }
14608 #endif // DEBUG
14609
14610     BasicBlock* bNext;
14611     BasicBlock* bPrev;
14612     BasicBlock* block;
14613     unsigned    XTnum;
14614     EHblkDsc*   HBtab;
14615
14616     // Iterate over every block, remembering our previous block in bPrev
14617     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
14618     {
14619         //
14620         // Consider relocating the rarely run blocks such that they are at the end of the method.
14621         // We also consider reversing conditional branches so that they become a not taken forwards branch.
14622         //
14623
14624         // If block is marked with a BBF_KEEP_BBJ_ALWAYS flag then we don't move the block
14625         if ((block->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)
14626         {
14627             continue;
14628         }
14629
14630         // Finally and handlers blocks are to be kept contiguous.
14631         // TODO-CQ: Allow reordering within the handler region
14632         if (block->hasHndIndex() == true)
14633         {
14634             continue;
14635         }
14636
14637         bool        reorderBlock   = true; // This is set to false if we decide not to reorder 'block'
14638         bool        isRare         = block->isRunRarely();
14639         BasicBlock* bDest          = nullptr;
14640         bool        forwardBranch  = false;
14641         bool        backwardBranch = false;
14642
14643         // Setup bDest
14644         if ((bPrev->bbJumpKind == BBJ_COND) || (bPrev->bbJumpKind == BBJ_ALWAYS))
14645         {
14646             bDest          = bPrev->bbJumpDest;
14647             forwardBranch  = fgIsForwardBranch(bPrev);
14648             backwardBranch = !forwardBranch;
14649         }
14650
14651         // We will look for bPrev as a non rarely run block followed by block as a rarely run block
14652         //
14653         if (bPrev->isRunRarely())
14654         {
14655             reorderBlock = false;
14656         }
14657
14658         // If the weights of the bPrev, block and bDest were all obtained from a profile run
14659         // then we can use them to decide if it is useful to reverse this conditional branch
14660
14661         BasicBlock::weight_t profHotWeight = -1;
14662
14663         if (bPrev->hasProfileWeight() && block->hasProfileWeight() && ((bDest == nullptr) || bDest->hasProfileWeight()))
14664         {
14665             //
14666             // All blocks have profile information
14667             //
14668             if (forwardBranch)
14669             {
14670                 if (bPrev->bbJumpKind == BBJ_ALWAYS)
14671                 {
14672                     // We can pull up the blocks that the unconditional jump branches to
14673                     // if the weight of bDest is greater or equal to the weight of block
14674                     // also the weight of bDest can't be zero.
14675                     //
14676                     if ((bDest->bbWeight < block->bbWeight) || (bDest->bbWeight == 0))
14677                     {
14678                         reorderBlock = false;
14679                     }
14680                     else
14681                     {
14682                         //
14683                         // If this remains true then we will try to pull up bDest to succeed bPrev
14684                         //
14685                         bool moveDestUp = true;
14686
14687                         if (fgHaveValidEdgeWeights)
14688                         {
14689                             //
14690                             // The edge bPrev -> bDest must have a higher minimum weight
14691                             // than every other edge into bDest
14692                             //
14693                             flowList* edgeFromPrev = fgGetPredForBlock(bDest, bPrev);
14694                             noway_assert(edgeFromPrev != nullptr);
14695
14696                             // Examine all of the other edges into bDest
14697                             for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext)
14698                             {
14699                                 if (edge != edgeFromPrev)
14700                                 {
14701                                     if (edge->flEdgeWeightMax >= edgeFromPrev->flEdgeWeightMin)
14702                                     {
14703                                         moveDestUp = false;
14704                                         break;
14705                                     }
14706                                 }
14707                             }
14708                         }
14709                         else
14710                         {
14711                             //
14712                             // The block bPrev must have a higher weight
14713                             // than every other block that goes into bDest
14714                             //
14715
14716                             // Examine all of the other edges into bDest
14717                             for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext)
14718                             {
14719                                 BasicBlock* bTemp = edge->flBlock;
14720
14721                                 if ((bTemp != bPrev) && (bTemp->bbWeight >= bPrev->bbWeight))
14722                                 {
14723                                     moveDestUp = false;
14724                                     break;
14725                                 }
14726                             }
14727                         }
14728
14729                         // Are we still good to move bDest up to bPrev?
14730                         if (moveDestUp)
14731                         {
14732                             //
14733                             // We will consider all blocks that have less weight than profHotWeight to be
14734                             // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest
14735                             //
14736                             profHotWeight = bDest->bbWeight - 1;
14737                         }
14738                         else
14739                         {
14740                             if (block->isRunRarely())
14741                             {
14742                                 // We will move any rarely run blocks blocks
14743                                 profHotWeight = 0;
14744                             }
14745                             else
14746                             {
14747                                 // We will move all blocks that have a weight less or equal to our fall through block
14748                                 profHotWeight = block->bbWeight + 1;
14749                             }
14750                             // But we won't try to connect with bDest
14751                             bDest = nullptr;
14752                         }
14753                     }
14754                 }
14755                 else // (bPrev->bbJumpKind == BBJ_COND)
14756                 {
14757                     noway_assert(bPrev->bbJumpKind == BBJ_COND);
14758                     //
14759                     // We will reverse branch if the taken-jump to bDest ratio (i.e. 'takenRatio')
14760                     // is more than 51%
14761                     //
14762                     // We will setup profHotWeight to be maximum bbWeight that a block
14763                     // could have for us not to want to reverse the conditional branch
14764                     //
14765                     // We will consider all blocks that have less weight than profHotWeight to be
14766                     // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest
14767                     //
14768                     if (fgHaveValidEdgeWeights)
14769                     {
14770                         // We have valid edge weights, however even with valid edge weights
14771                         // we may have a minimum and maximum range for each edges value
14772                         //
14773                         // We will check that the min weight of the bPrev to bDest edge
14774                         //  is more than twice the max weight of the bPrev to block edge.
14775                         //
14776                         //                  bPrev -->   [BB04, weight 31]
14777                         //                                     |         \
14778                         //          edgeToBlock -------------> O          \
14779                         //          [min=8,max=10]             V           \
14780                         //                  block -->   [BB05, weight 10]   \
14781                         //                                                   \
14782                         //          edgeToDest ----------------------------> O
14783                         //          [min=21,max=23]                          |
14784                         //                                                   V
14785                         //                  bDest --------------->   [BB08, weight 21]
14786                         //
14787                         flowList* edgeToDest  = fgGetPredForBlock(bDest, bPrev);
14788                         flowList* edgeToBlock = fgGetPredForBlock(block, bPrev);
14789                         noway_assert(edgeToDest != nullptr);
14790                         noway_assert(edgeToBlock != nullptr);
14791                         //
14792                         // Calculate the taken ratio
14793                         //   A takenRation of 0.10 means taken 10% of the time, not taken 90% of the time
14794                         //   A takenRation of 0.50 means taken 50% of the time, not taken 50% of the time
14795                         //   A takenRation of 0.90 means taken 90% of the time, not taken 10% of the time
14796                         //
14797                         double takenCount =
14798                             ((double)edgeToDest->flEdgeWeightMin + (double)edgeToDest->flEdgeWeightMax) / 2.0;
14799                         double notTakenCount =
14800                             ((double)edgeToBlock->flEdgeWeightMin + (double)edgeToBlock->flEdgeWeightMax) / 2.0;
14801                         double totalCount = takenCount + notTakenCount;
14802                         double takenRatio = takenCount / totalCount;
14803
14804                         // If the takenRatio is greater or equal to 51% then we will reverse the branch
14805                         if (takenRatio < 0.51)
14806                         {
14807                             reorderBlock = false;
14808                         }
14809                         else
14810                         {
14811                             // set profHotWeight
14812                             profHotWeight = (edgeToBlock->flEdgeWeightMin + edgeToBlock->flEdgeWeightMax) / 2 - 1;
14813                         }
14814                     }
14815                     else
14816                     {
14817                         // We don't have valid edge weight so we will be more conservative
14818                         // We could have bPrev, block or bDest as part of a loop and thus have extra weight
14819                         //
14820                         // We will do two checks:
14821                         //   1. Check that the weight of bDest is at least two times more than block
14822                         //   2. Check that the weight of bPrev is at least three times more than block
14823                         //
14824                         //                  bPrev -->   [BB04, weight 31]
14825                         //                                     |         \
14826                         //                                     V          \
14827                         //                  block -->   [BB05, weight 10]  \
14828                         //                                                  \
14829                         //                                                  |
14830                         //                                                  V
14831                         //                  bDest --------------->   [BB08, weight 21]
14832                         //
14833                         //  For this case weightDest is calculated as (21+1)/2  or 11
14834                         //            and weightPrev is calculated as (31+2)/3  also 11
14835                         //
14836                         //  Generally both weightDest and weightPrev should calculate
14837                         //  the same value unless bPrev or bDest are part of a loop
14838                         //
14839                         BasicBlock::weight_t weightDest =
14840                             bDest->isMaxBBWeight() ? bDest->bbWeight : (bDest->bbWeight + 1) / 2;
14841                         BasicBlock::weight_t weightPrev =
14842                             bPrev->isMaxBBWeight() ? bPrev->bbWeight : (bPrev->bbWeight + 2) / 3;
14843
14844                         // select the lower of weightDest and weightPrev
14845                         profHotWeight = (weightDest < weightPrev) ? weightDest : weightPrev;
14846
14847                         // if the weight of block is greater (or equal) to profHotWeight then we don't reverse the cond
14848                         if (block->bbWeight >= profHotWeight)
14849                         {
14850                             reorderBlock = false;
14851                         }
14852                     }
14853                 }
14854             }
14855             else // not a forwardBranch
14856             {
14857                 if (bPrev->bbFallsThrough())
14858                 {
14859                     goto CHECK_FOR_RARE;
14860                 }
14861
14862                 // Here we should pull up the highest weight block remaining
14863                 // and place it here since bPrev does not fall through.
14864
14865                 BasicBlock::weight_t highestWeight           = 0;
14866                 BasicBlock*          candidateBlock          = nullptr;
14867                 BasicBlock*          lastNonFallThroughBlock = bPrev;
14868                 BasicBlock*          bTmp                    = bPrev->bbNext;
14869
14870                 while (bTmp != nullptr)
14871                 {
14872                     // Don't try to split a Call/Always pair
14873                     //
14874                     if (bTmp->isBBCallAlwaysPair())
14875                     {
14876                         // Move bTmp forward
14877                         bTmp = bTmp->bbNext;
14878                     }
14879
14880                     //
14881                     // Check for loop exit condition
14882                     //
14883                     if (bTmp == nullptr)
14884                     {
14885                         break;
14886                     }
14887
14888                     //
14889                     // if its weight is the highest one we've seen and
14890                     //  the EH regions allow for us to place bTmp after bPrev
14891                     //
14892                     if ((bTmp->bbWeight > highestWeight) && fgEhAllowsMoveBlock(bPrev, bTmp))
14893                     {
14894                         // When we have a current candidateBlock that is a conditional (or unconditional) jump
14895                         // to bTmp (which is a higher weighted block) then it is better to keep out current
14896                         // candidateBlock and have it fall into bTmp
14897                         //
14898                         if ((candidateBlock == nullptr) ||
14899                             ((candidateBlock->bbJumpKind != BBJ_COND) && (candidateBlock->bbJumpKind != BBJ_ALWAYS)) ||
14900                             (candidateBlock->bbJumpDest != bTmp))
14901                         {
14902                             // otherwise we have a new candidateBlock
14903                             //
14904                             highestWeight  = bTmp->bbWeight;
14905                             candidateBlock = lastNonFallThroughBlock->bbNext;
14906                         }
14907                     }
14908
14909                     if ((bTmp->bbFallsThrough() == false) || (bTmp->bbWeight == 0))
14910                     {
14911                         lastNonFallThroughBlock = bTmp;
14912                     }
14913
14914                     bTmp = bTmp->bbNext;
14915                 }
14916
14917                 // If we didn't find a suitable block then skip this
14918                 if (highestWeight == 0)
14919                 {
14920                     reorderBlock = false;
14921                 }
14922                 else
14923                 {
14924                     noway_assert(candidateBlock != nullptr);
14925
14926                     // If the candidateBlock is the same a block then skip this
14927                     if (candidateBlock == block)
14928                     {
14929                         reorderBlock = false;
14930                     }
14931                     else
14932                     {
14933                         // Set bDest to the block that we want to come after bPrev
14934                         bDest = candidateBlock;
14935
14936                         // set profHotWeight
14937                         profHotWeight = highestWeight - 1;
14938                     }
14939                 }
14940             }
14941         }
14942         else // we don't have good profile info (or we are falling through)
14943         {
14944
14945         CHECK_FOR_RARE:;
14946
14947             /* We only want to reorder when we have a rarely run   */
14948             /* block right after a normal block,                   */
14949             /* (bPrev is known to be a normal block at this point) */
14950             if (!isRare)
14951             {
14952                 reorderBlock = false;
14953             }
14954             else
14955             {
14956                 /* If the jump target bDest is also a rarely run block then we don't want to do the reversal */
14957                 if (bDest && bDest->isRunRarely())
14958                 {
14959                     reorderBlock = false; /* Both block and bDest are rarely run */
14960                 }
14961                 else
14962                 {
14963                     // We will move any rarely run blocks blocks
14964                     profHotWeight = 0;
14965                 }
14966             }
14967         }
14968
14969         if (reorderBlock == false)
14970         {
14971             //
14972             // Check for an unconditional branch to a conditional branch
14973             // which also branches back to our next block
14974             //
14975             if (fgOptimizeBranch(bPrev))
14976             {
14977                 noway_assert(bPrev->bbJumpKind == BBJ_COND);
14978             }
14979             continue;
14980         }
14981
14982         //  Now we need to determine which blocks should be moved
14983         //
14984         //  We consider one of two choices:
14985         //
14986         //  1. Moving the fall-through blocks (or rarely run blocks) down to
14987         //     later in the method and hopefully connecting the jump dest block
14988         //     so that it becomes the fall through block
14989         //
14990         //  And when bDest in not NULL, we also consider:
14991         //
14992         //  2. Moving the bDest block (or blocks) up to bPrev
14993         //     so that it could be used as a fall through block
14994         //
14995         //  We will prefer option #1 if we are able to connect the jump dest
14996         //  block as the fall though block otherwise will we try to use option #2
14997         //
14998
14999         //
15000         //  Consider option #1: relocating blocks starting at 'block'
15001         //    to later in flowgraph
15002         //
15003         // We set bStart to the first block that will be relocated
15004         // and bEnd to the last block that will be relocated
15005
15006         BasicBlock* bStart   = block;
15007         BasicBlock* bEnd     = bStart;
15008         bNext                = bEnd->bbNext;
15009         bool connected_bDest = false;
15010
15011         if ((backwardBranch && !isRare) ||
15012             ((block->bbFlags & BBF_DONT_REMOVE) != 0)) // Don't choose option #1 when block is the start of a try region
15013         {
15014             bStart = nullptr;
15015             bEnd   = nullptr;
15016         }
15017         else
15018         {
15019             while (true)
15020             {
15021                 // Don't try to split a Call/Always pair
15022                 //
15023                 if (bEnd->isBBCallAlwaysPair())
15024                 {
15025                     // Move bEnd and bNext forward
15026                     bEnd  = bNext;
15027                     bNext = bNext->bbNext;
15028                 }
15029
15030                 //
15031                 // Check for loop exit condition
15032                 //
15033                 if (bNext == nullptr)
15034                 {
15035                     break;
15036                 }
15037
15038 #if FEATURE_EH_FUNCLETS
15039                 // Check if we've reached the funclets region, at the end of the function
15040                 if (fgFirstFuncletBB == bEnd->bbNext)
15041                 {
15042                     break;
15043                 }
15044 #endif // FEATURE_EH_FUNCLETS
15045
15046                 if (bNext == bDest)
15047                 {
15048                     connected_bDest = true;
15049                     break;
15050                 }
15051
15052                 // All the blocks must have the same try index
15053                 // and must not have the BBF_DONT_REMOVE flag set
15054
15055                 if (!BasicBlock::sameTryRegion(bStart, bNext) || ((bNext->bbFlags & BBF_DONT_REMOVE) != 0))
15056                 {
15057                     // exit the loop, bEnd is now set to the
15058                     // last block that we want to relocate
15059                     break;
15060                 }
15061
15062                 // If we are relocating rarely run blocks..
15063                 if (isRare)
15064                 {
15065                     // ... then all blocks must be rarely run
15066                     if (!bNext->isRunRarely())
15067                     {
15068                         // exit the loop, bEnd is now set to the
15069                         // last block that we want to relocate
15070                         break;
15071                     }
15072                 }
15073                 else
15074                 {
15075                     // If we are moving blocks that are hot then all
15076                     // of the blocks moved must be less than profHotWeight */
15077                     if (bNext->bbWeight >= profHotWeight)
15078                     {
15079                         // exit the loop, bEnd is now set to the
15080                         // last block that we would relocate
15081                         break;
15082                     }
15083                 }
15084
15085                 // Move bEnd and bNext forward
15086                 bEnd  = bNext;
15087                 bNext = bNext->bbNext;
15088             }
15089
15090             // Set connected_bDest to true if moving blocks [bStart .. bEnd]
15091             //  connects with the the jump dest of bPrev (i.e bDest) and
15092             // thus allows bPrev fall through instead of jump.
15093             if (bNext == bDest)
15094             {
15095                 connected_bDest = true;
15096             }
15097         }
15098
15099         //  Now consider option #2: Moving the jump dest block (or blocks)
15100         //    up to bPrev
15101         //
15102         // The variables bStart2, bEnd2 and bPrev2 are used for option #2
15103         //
15104         // We will setup bStart2 to the first block that will be relocated
15105         // and bEnd2 to the last block that will be relocated
15106         // and bPrev2 to be the lexical pred of bDest
15107         //
15108         // If after this calculation bStart2 is NULL we cannot use option #2,
15109         // otherwise bStart2, bEnd2 and bPrev2 are all non-NULL and we will use option #2
15110
15111         BasicBlock* bStart2 = nullptr;
15112         BasicBlock* bEnd2   = nullptr;
15113         BasicBlock* bPrev2  = nullptr;
15114
15115         // If option #1 didn't connect bDest and bDest isn't NULL
15116         if ((connected_bDest == false) && (bDest != nullptr) &&
15117             //  The jump target cannot be moved if it has the BBF_DONT_REMOVE flag set
15118             ((bDest->bbFlags & BBF_DONT_REMOVE) == 0))
15119         {
15120             // We will consider option #2: relocating blocks starting at 'bDest' to succeed bPrev
15121             //
15122             // setup bPrev2 to be the lexical pred of bDest
15123
15124             bPrev2 = block;
15125             while (bPrev2 != nullptr)
15126             {
15127                 if (bPrev2->bbNext == bDest)
15128                 {
15129                     break;
15130                 }
15131
15132                 bPrev2 = bPrev2->bbNext;
15133             }
15134
15135             if ((bPrev2 != nullptr) && fgEhAllowsMoveBlock(bPrev, bDest))
15136             {
15137                 // We have decided that relocating bDest to be after bPrev is best
15138                 // Set bStart2 to the first block that will be relocated
15139                 // and bEnd2 to the last block that will be relocated
15140                 //
15141                 // Assigning to bStart2 selects option #2
15142                 //
15143                 bStart2 = bDest;
15144                 bEnd2   = bStart2;
15145                 bNext   = bEnd2->bbNext;
15146
15147                 while (true)
15148                 {
15149                     // Don't try to split a Call/Always pair
15150                     //
15151                     if (bEnd2->isBBCallAlwaysPair())
15152                     {
15153                         noway_assert(bNext->bbJumpKind == BBJ_ALWAYS);
15154                         // Move bEnd2 and bNext forward
15155                         bEnd2 = bNext;
15156                         bNext = bNext->bbNext;
15157                     }
15158
15159                     // Check for the Loop exit conditions
15160
15161                     if (bNext == nullptr)
15162                     {
15163                         break;
15164                     }
15165
15166                     if (bEnd2->bbFallsThrough() == false)
15167                     {
15168                         break;
15169                     }
15170
15171                     // If we are relocating rarely run blocks..
15172                     // All the blocks must have the same try index,
15173                     // and must not have the BBF_DONT_REMOVE flag set
15174
15175                     if (!BasicBlock::sameTryRegion(bStart2, bNext) || ((bNext->bbFlags & BBF_DONT_REMOVE) != 0))
15176                     {
15177                         // exit the loop, bEnd2 is now set to the
15178                         // last block that we want to relocate
15179                         break;
15180                     }
15181
15182                     if (isRare)
15183                     {
15184                         /* ... then all blocks must not be rarely run */
15185                         if (bNext->isRunRarely())
15186                         {
15187                             // exit the loop, bEnd2 is now set to the
15188                             // last block that we want to relocate
15189                             break;
15190                         }
15191                     }
15192                     else
15193                     {
15194                         // If we are relocating hot blocks
15195                         // all blocks moved must be greater than profHotWeight
15196                         if (bNext->bbWeight <= profHotWeight)
15197                         {
15198                             // exit the loop, bEnd2 is now set to the
15199                             // last block that we want to relocate
15200                             break;
15201                         }
15202                     }
15203
15204                     // Move bEnd2 and bNext forward
15205                     bEnd2 = bNext;
15206                     bNext = bNext->bbNext;
15207                 }
15208             }
15209         }
15210
15211         // If we are using option #1 then ...
15212         if (bStart2 == nullptr)
15213         {
15214             // Don't use option #1 for a backwards branch
15215             if (bStart == nullptr)
15216             {
15217                 continue;
15218             }
15219
15220             // .... Don't move a set of blocks that are already at the end of the main method
15221             if (bEnd == fgLastBBInMainFunction())
15222             {
15223                 continue;
15224             }
15225         }
15226
15227 #ifdef DEBUG
15228         if (verbose)
15229         {
15230             if (bDest != nullptr)
15231             {
15232                 if (bPrev->bbJumpKind == BBJ_COND)
15233                 {
15234                     printf("Decided to reverse conditional branch at block BB%02u branch to BB%02u ", bPrev->bbNum,
15235                            bDest->bbNum);
15236                 }
15237                 else if (bPrev->bbJumpKind == BBJ_ALWAYS)
15238                 {
15239                     printf("Decided to straighten unconditional branch at block BB%02u branch to BB%02u ", bPrev->bbNum,
15240                            bDest->bbNum);
15241                 }
15242                 else
15243                 {
15244                     printf("Decided to place hot code after BB%02u, placed BB%02u after this block ", bPrev->bbNum,
15245                            bDest->bbNum);
15246                 }
15247
15248                 if (profHotWeight > 0)
15249                 {
15250                     printf("because of IBC profile data\n");
15251                 }
15252                 else
15253                 {
15254                     if (bPrev->bbFallsThrough())
15255                     {
15256                         printf("since it falls into a rarely run block\n");
15257                     }
15258                     else
15259                     {
15260                         printf("since it is succeeded by a rarely run block\n");
15261                     }
15262                 }
15263             }
15264             else
15265             {
15266                 printf("Decided to relocate block(s) after block BB%02u since they are %s block(s)\n", bPrev->bbNum,
15267                        block->isRunRarely() ? "rarely run" : "uncommonly run");
15268             }
15269         }
15270 #endif // DEBUG
15271
15272         // We will set insertAfterBlk to the block the precedes our insertion range
15273         // We will set bStartPrev to be the block that precedes the set of blocks that we are moving
15274         BasicBlock* insertAfterBlk;
15275         BasicBlock* bStartPrev;
15276
15277         if (bStart2 != nullptr)
15278         {
15279             // Option #2: relocating blocks starting at 'bDest' to follow bPrev
15280
15281             // Update bStart and bEnd so that we can use these two for all later operations
15282             bStart = bStart2;
15283             bEnd   = bEnd2;
15284
15285             // Set bStartPrev to be the block that comes before bStart
15286             bStartPrev = bPrev2;
15287
15288             // We will move [bStart..bEnd] to immediately after bPrev
15289             insertAfterBlk = bPrev;
15290         }
15291         else
15292         {
15293             // option #1: Moving the fall-through blocks (or rarely run blocks) down to later in the method
15294
15295             // Set bStartPrev to be the block that come before bStart
15296             bStartPrev = bPrev;
15297
15298             // We will move [bStart..bEnd] but we will pick the insert location later
15299             insertAfterBlk = nullptr;
15300         }
15301
15302         // We are going to move [bStart..bEnd] so they can't be NULL
15303         noway_assert(bStart != nullptr);
15304         noway_assert(bEnd != nullptr);
15305
15306         // bEnd can't be a BBJ_CALLFINALLY unless it is a RETLESS call
15307         noway_assert((bEnd->bbJumpKind != BBJ_CALLFINALLY) || (bEnd->bbFlags & BBF_RETLESS_CALL));
15308
15309         // bStartPrev must be set to the block that precedes bStart
15310         noway_assert(bStartPrev->bbNext == bStart);
15311
15312         // Since we will be unlinking [bStart..bEnd],
15313         // we need to compute and remember if bStart is in each of
15314         // the try and handler regions
15315         //
15316         bool* fStartIsInTry = nullptr;
15317         bool* fStartIsInHnd = nullptr;
15318
15319         if (compHndBBtabCount > 0)
15320         {
15321             fStartIsInTry = new (this, CMK_Unknown) bool[compHndBBtabCount];
15322             fStartIsInHnd = new (this, CMK_Unknown) bool[compHndBBtabCount];
15323
15324             for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
15325             {
15326                 fStartIsInTry[XTnum] = HBtab->InTryRegionBBRange(bStart);
15327                 fStartIsInHnd[XTnum] = HBtab->InHndRegionBBRange(bStart);
15328             }
15329         }
15330
15331         /* Temporarily unlink [bStart..bEnd] from the flow graph */
15332         fgUnlinkRange(bStart, bEnd);
15333
15334         if (insertAfterBlk == nullptr)
15335         {
15336             // Find new location for the unlinked block(s)
15337             // Set insertAfterBlk to the block which will precede the insertion point
15338
15339             if (!bStart->hasTryIndex() && isRare)
15340             {
15341                 // We'll just insert the blocks at the end of the method. If the method
15342                 // has funclets, we will insert at the end of the main method but before
15343                 // any of the funclets. Note that we create funclets before we call
15344                 // fgReorderBlocks().
15345
15346                 insertAfterBlk = fgLastBBInMainFunction();
15347                 noway_assert(insertAfterBlk != bPrev);
15348             }
15349             else
15350             {
15351                 BasicBlock* startBlk;
15352                 BasicBlock* lastBlk;
15353                 EHblkDsc*   ehDsc = ehInitTryBlockRange(bStart, &startBlk, &lastBlk);
15354
15355                 BasicBlock* endBlk;
15356
15357                 /* Setup startBlk and endBlk as the range to search */
15358
15359                 if (ehDsc != nullptr)
15360                 {
15361                     endBlk = lastBlk->bbNext;
15362
15363                     /*
15364                        Multiple (nested) try regions might start from the same BB.
15365                        For example,
15366
15367                        try3   try2   try1
15368                        |---   |---   |---   BB01
15369                        |      |      |      BB02
15370                        |      |      |---   BB03
15371                        |      |             BB04
15372                        |      |------------ BB05
15373                        |                    BB06
15374                        |------------------- BB07
15375
15376                        Now if we want to insert in try2 region, we will start with startBlk=BB01.
15377                        The following loop will allow us to start from startBlk==BB04.
15378                     */
15379                     while (!BasicBlock::sameTryRegion(startBlk, bStart) && (startBlk != endBlk))
15380                     {
15381                         startBlk = startBlk->bbNext;
15382                     }
15383
15384                     // startBlk cannot equal endBlk as it must come before endBlk
15385                     if (startBlk == endBlk)
15386                     {
15387                         goto CANNOT_MOVE;
15388                     }
15389
15390                     // we also can't start searching the try region at bStart
15391                     if (startBlk == bStart)
15392                     {
15393                         // if bEnd is the last block in the method or
15394                         // or if bEnd->bbNext is in a different try region
15395                         // then we cannot move the blocks
15396                         //
15397                         if ((bEnd->bbNext == nullptr) || !BasicBlock::sameTryRegion(startBlk, bEnd->bbNext))
15398                         {
15399                             goto CANNOT_MOVE;
15400                         }
15401
15402                         startBlk = bEnd->bbNext;
15403
15404                         // Check that the new startBlk still comes before endBlk
15405
15406                         // startBlk cannot equal endBlk as it must come before endBlk
15407                         if (startBlk == endBlk)
15408                         {
15409                             goto CANNOT_MOVE;
15410                         }
15411
15412                         BasicBlock* tmpBlk = startBlk;
15413                         while ((tmpBlk != endBlk) && (tmpBlk != nullptr))
15414                         {
15415                             tmpBlk = tmpBlk->bbNext;
15416                         }
15417
15418                         // when tmpBlk is NULL that means startBlk is after endBlk
15419                         // so there is no way to move bStart..bEnd within the try region
15420                         if (tmpBlk == nullptr)
15421                         {
15422                             goto CANNOT_MOVE;
15423                         }
15424                     }
15425                 }
15426                 else
15427                 {
15428                     noway_assert(isRare == false);
15429
15430                     /* We'll search through the entire main method */
15431                     startBlk = fgFirstBB;
15432                     endBlk   = fgEndBBAfterMainFunction();
15433                 }
15434
15435                 // Calculate nearBlk and jumpBlk and then call fgFindInsertPoint()
15436                 // to find our insertion block
15437                 //
15438                 {
15439                     // If the set of blocks that we are moving ends with a BBJ_ALWAYS to
15440                     // another [rarely run] block that comes after bPrev (forward branch)
15441                     // then we can set up nearBlk to eliminate this jump sometimes
15442                     //
15443                     BasicBlock* nearBlk = nullptr;
15444                     BasicBlock* jumpBlk = nullptr;
15445
15446                     if ((bEnd->bbJumpKind == BBJ_ALWAYS) && (!isRare || bEnd->bbJumpDest->isRunRarely()) &&
15447                         fgIsForwardBranch(bEnd, bPrev))
15448                     {
15449                         // Set nearBlk to be the block in [startBlk..endBlk]
15450                         // such that nearBlk->bbNext == bEnd->JumpDest
15451                         // if no such block exists then set nearBlk to NULL
15452                         nearBlk = startBlk;
15453                         jumpBlk = bEnd;
15454                         do
15455                         {
15456                             // We do not want to set nearBlk to bPrev
15457                             // since then we will not move [bStart..bEnd]
15458                             //
15459                             if (nearBlk != bPrev)
15460                             {
15461                                 // Check if nearBlk satisfies our requirement
15462                                 if (nearBlk->bbNext == bEnd->bbJumpDest)
15463                                 {
15464                                     break;
15465                                 }
15466                             }
15467
15468                             // Did we reach the endBlk?
15469                             if (nearBlk == endBlk)
15470                             {
15471                                 nearBlk = nullptr;
15472                                 break;
15473                             }
15474
15475                             // advance nearBlk to the next block
15476                             nearBlk = nearBlk->bbNext;
15477
15478                         } while (nearBlk != nullptr);
15479                     }
15480
15481                     // if nearBlk is NULL then we set nearBlk to be the
15482                     // first block that we want to insert after.
15483                     if (nearBlk == nullptr)
15484                     {
15485                         if (bDest != nullptr)
15486                         {
15487                             // we want to insert after bDest
15488                             nearBlk = bDest;
15489                         }
15490                         else
15491                         {
15492                             // we want to insert after bPrev
15493                             nearBlk = bPrev;
15494                         }
15495                     }
15496
15497                     /* Set insertAfterBlk to the block which we will insert after. */
15498
15499                     insertAfterBlk =
15500                         fgFindInsertPoint(bStart->bbTryIndex,
15501                                           true, // Insert in the try region.
15502                                           startBlk, endBlk, nearBlk, jumpBlk, bStart->bbWeight == BB_ZERO_WEIGHT);
15503                 }
15504
15505                 /* See if insertAfterBlk is the same as where we started, */
15506                 /*  or if we could not find any insertion point     */
15507
15508                 if ((insertAfterBlk == bPrev) || (insertAfterBlk == nullptr))
15509                 {
15510                 CANNOT_MOVE:;
15511                     /* We couldn't move the blocks, so put everything back */
15512                     /* relink [bStart .. bEnd] into the flow graph */
15513
15514                     bPrev->setNext(bStart);
15515                     if (bEnd->bbNext)
15516                     {
15517                         bEnd->bbNext->bbPrev = bEnd;
15518                     }
15519 #ifdef DEBUG
15520                     if (verbose)
15521                     {
15522                         if (bStart != bEnd)
15523                         {
15524                             printf("Could not relocate blocks (BB%02u .. BB%02u)\n", bStart->bbNum, bEnd->bbNum);
15525                         }
15526                         else
15527                         {
15528                             printf("Could not relocate block BB%02u\n", bStart->bbNum);
15529                         }
15530                     }
15531 #endif // DEBUG
15532                     continue;
15533                 }
15534             }
15535         }
15536
15537         noway_assert(insertAfterBlk != nullptr);
15538         noway_assert(bStartPrev != nullptr);
15539         noway_assert(bStartPrev != insertAfterBlk);
15540
15541 #ifdef DEBUG
15542         movedBlocks = true;
15543
15544         if (verbose)
15545         {
15546             const char* msg;
15547             if (bStart2 != nullptr)
15548             {
15549                 msg = "hot";
15550             }
15551             else
15552             {
15553                 if (isRare)
15554                 {
15555                     msg = "rarely run";
15556                 }
15557                 else
15558                 {
15559                     msg = "uncommon";
15560                 }
15561             }
15562
15563             printf("Relocated %s ", msg);
15564             if (bStart != bEnd)
15565             {
15566                 printf("blocks (BB%02u .. BB%02u)", bStart->bbNum, bEnd->bbNum);
15567             }
15568             else
15569             {
15570                 printf("block BB%02u", bStart->bbNum);
15571             }
15572
15573             if (bPrev->bbJumpKind == BBJ_COND)
15574             {
15575                 printf(" by reversing conditional jump at BB%02u\n", bPrev->bbNum);
15576             }
15577             else
15578             {
15579                 printf("\n", bPrev->bbNum);
15580             }
15581         }
15582 #endif // DEBUG
15583
15584         if (bPrev->bbJumpKind == BBJ_COND)
15585         {
15586             /* Reverse the bPrev jump condition */
15587             GenTree* condTest = bPrev->lastStmt();
15588
15589             condTest = condTest->gtStmt.gtStmtExpr;
15590             noway_assert(condTest->gtOper == GT_JTRUE);
15591
15592             condTest->gtOp.gtOp1 = gtReverseCond(condTest->gtOp.gtOp1);
15593
15594             if (bStart2 == nullptr)
15595             {
15596                 /* Set the new jump dest for bPrev to the rarely run or uncommon block(s) */
15597                 bPrev->bbJumpDest = bStart;
15598                 bStart->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
15599             }
15600             else
15601             {
15602                 noway_assert(insertAfterBlk == bPrev);
15603                 noway_assert(insertAfterBlk->bbNext == block);
15604
15605                 /* Set the new jump dest for bPrev to the rarely run or uncommon block(s) */
15606                 bPrev->bbJumpDest = block;
15607                 block->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
15608             }
15609         }
15610
15611         // If we are moving blocks that are at the end of a try or handler
15612         // we will need to shorten ebdTryLast or ebdHndLast
15613         //
15614         ehUpdateLastBlocks(bEnd, bStartPrev);
15615
15616         // If we are moving blocks into the end of a try region or handler region
15617         // we will need to extend ebdTryLast or ebdHndLast so the blocks that we
15618         // are moving are part of this try or handler region.
15619         //
15620         for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
15621         {
15622             // Are we moving blocks to the end of a try region?
15623             if (HBtab->ebdTryLast == insertAfterBlk)
15624             {
15625                 if (fStartIsInTry[XTnum])
15626                 {
15627                     // bStart..bEnd is in the try, so extend the try region
15628                     fgSetTryEnd(HBtab, bEnd);
15629                 }
15630             }
15631
15632             // Are we moving blocks to the end of a handler region?
15633             if (HBtab->ebdHndLast == insertAfterBlk)
15634             {
15635                 if (fStartIsInHnd[XTnum])
15636                 {
15637                     // bStart..bEnd is in the handler, so extend the handler region
15638                     fgSetHndEnd(HBtab, bEnd);
15639                 }
15640             }
15641         }
15642
15643         /* We have decided to insert the block(s) after 'insertAfterBlk' */
15644         fgMoveBlocksAfter(bStart, bEnd, insertAfterBlk);
15645
15646         if (bDest)
15647         {
15648             /* We may need to insert an unconditional branch after bPrev to bDest */
15649             fgConnectFallThrough(bPrev, bDest);
15650         }
15651         else
15652         {
15653             /* If bPrev falls through, we must insert a jump to block */
15654             fgConnectFallThrough(bPrev, block);
15655         }
15656
15657         BasicBlock* bSkip = bEnd->bbNext;
15658
15659         /* If bEnd falls through, we must insert a jump to bNext */
15660         fgConnectFallThrough(bEnd, bNext);
15661
15662         if (bStart2 == nullptr)
15663         {
15664             /* If insertAfterBlk falls through, we are forced to     */
15665             /* add a jump around the block(s) we just inserted */
15666             fgConnectFallThrough(insertAfterBlk, bSkip);
15667         }
15668         else
15669         {
15670             /* We may need to insert an unconditional branch after bPrev2 to bStart */
15671             fgConnectFallThrough(bPrev2, bStart);
15672         }
15673
15674 #if DEBUG
15675         if (verbose)
15676         {
15677             printf("\nAfter this change in fgReorderBlocks");
15678             fgDispBasicBlocks(verboseTrees);
15679             printf("\n");
15680         }
15681         fgVerifyHandlerTab();
15682
15683         // Make sure that the predecessor lists are accurate
15684         if (expensiveDebugCheckLevel >= 2)
15685         {
15686             fgDebugCheckBBlist();
15687         }
15688 #endif // DEBUG
15689
15690         // Set our iteration point 'block' to be the new bPrev->bbNext
15691         //  It will be used as the next bPrev
15692         block = bPrev->bbNext;
15693
15694     } // end of for loop(bPrev,block)
15695
15696     bool changed = movedBlocks || newRarelyRun || optimizedSwitches;
15697
15698     if (changed)
15699     {
15700         fgNeedsUpdateFlowGraph = true;
15701 #if DEBUG
15702         // Make sure that the predecessor lists are accurate
15703         if (expensiveDebugCheckLevel >= 2)
15704         {
15705             fgDebugCheckBBlist();
15706         }
15707 #endif // DEBUG
15708     }
15709 }
15710 #ifdef _PREFAST_
15711 #pragma warning(pop)
15712 #endif
15713
15714 /*-------------------------------------------------------------------------
15715  *
15716  * Walk the basic blocks list to determine the first block to place in the
15717  * cold section.  This would be the first of a series of rarely executed blocks
15718  * such that no succeeding blocks are in a try region or an exception handler
15719  * or are rarely executed.
15720  */
15721
15722 void Compiler::fgDetermineFirstColdBlock()
15723 {
15724 #ifdef DEBUG
15725     if (verbose)
15726     {
15727         printf("\n*************** In fgDetermineFirstColdBlock()\n");
15728     }
15729 #endif // DEBUG
15730
15731     // Since we may need to create a new transistion block
15732     // we assert that it is OK to create new blocks.
15733     //
15734     assert(fgSafeBasicBlockCreation);
15735
15736     fgFirstColdBlock = nullptr;
15737
15738 #if FEATURE_STACK_FP_X87
15739     if (compMayHaveTransitionBlocks)
15740     {
15741         opts.compProcedureSplitting = false;
15742
15743         // See comment above declaration of compMayHaveTransitionBlocks for comments on this
15744         JITDUMP("Turning off procedure splitting for this method, as it may end up having FP transition blocks\n");
15745     }
15746 #endif // FEATURE_STACK_FP_X87
15747
15748     if (!opts.compProcedureSplitting)
15749     {
15750         JITDUMP("No procedure splitting will be done for this method\n");
15751         return;
15752     }
15753
15754 #ifdef DEBUG
15755     if ((compHndBBtabCount > 0) && !opts.compProcedureSplittingEH)
15756     {
15757         JITDUMP("No procedure splitting will be done for this method with EH (by request)\n");
15758         return;
15759     }
15760 #endif // DEBUG
15761
15762 #if FEATURE_EH_FUNCLETS
15763     // TODO-CQ: handle hot/cold splitting in functions with EH (including synchronized methods
15764     // that create EH in methods without explicit EH clauses).
15765
15766     if (compHndBBtabCount > 0)
15767     {
15768         JITDUMP("No procedure splitting will be done for this method with EH (implementation limitation)\n");
15769         return;
15770     }
15771 #endif // FEATURE_EH_FUNCLETS
15772
15773     BasicBlock* firstColdBlock       = nullptr;
15774     BasicBlock* prevToFirstColdBlock = nullptr;
15775     BasicBlock* block;
15776     BasicBlock* lblk;
15777
15778     for (lblk = nullptr, block = fgFirstBB; block != nullptr; lblk = block, block = block->bbNext)
15779     {
15780         bool blockMustBeInHotSection = false;
15781
15782 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
15783         if (bbIsHandlerBeg(block))
15784         {
15785             blockMustBeInHotSection = true;
15786         }
15787 #endif // HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
15788
15789         // Do we have a candidate for the first cold block?
15790         if (firstColdBlock != nullptr)
15791         {
15792             // We have a candidate for first cold block
15793
15794             // Is this a hot block?
15795             if (blockMustBeInHotSection || (block->isRunRarely() == false))
15796             {
15797                 // We have to restart the search for the first cold block
15798                 firstColdBlock       = nullptr;
15799                 prevToFirstColdBlock = nullptr;
15800             }
15801         }
15802         else // (firstColdBlock == NULL)
15803         {
15804             // We don't have a candidate for first cold block
15805
15806             // Is this a cold block?
15807             if (!blockMustBeInHotSection && (block->isRunRarely() == true))
15808             {
15809                 //
15810                 // If the last block that was hot was a BBJ_COND
15811                 // then we will have to add an unconditional jump
15812                 // so the code size for block needs be large
15813                 // enough to make it worth our while
15814                 //
15815                 if ((lblk == nullptr) || (lblk->bbJumpKind != BBJ_COND) || (fgGetCodeEstimate(block) >= 8))
15816                 {
15817                     // This block is now a candidate for first cold block
15818                     // Also remember the predecessor to this block
15819                     firstColdBlock       = block;
15820                     prevToFirstColdBlock = lblk;
15821                 }
15822             }
15823         }
15824     }
15825
15826     if (firstColdBlock == fgFirstBB)
15827     {
15828         // If the first block is Cold then we can't move any blocks
15829         // into the cold section
15830
15831         firstColdBlock = nullptr;
15832     }
15833
15834     if (firstColdBlock != nullptr)
15835     {
15836         noway_assert(prevToFirstColdBlock != nullptr);
15837
15838         if (prevToFirstColdBlock == nullptr)
15839         {
15840             return; // To keep Prefast happy
15841         }
15842
15843         // If we only have one cold block
15844         // then it may not be worth it to move it
15845         // into the Cold section as a jump to the
15846         // Cold section is 5 bytes in size.
15847         //
15848         if (firstColdBlock->bbNext == nullptr)
15849         {
15850             // If the size of the cold block is 7 or less
15851             // then we will keep it in the Hot section.
15852             //
15853             if (fgGetCodeEstimate(firstColdBlock) < 8)
15854             {
15855                 firstColdBlock = nullptr;
15856                 goto EXIT;
15857             }
15858         }
15859
15860         // When the last Hot block fall through into the Cold section
15861         // we may need to add a jump
15862         //
15863         if (prevToFirstColdBlock->bbFallsThrough())
15864         {
15865             switch (prevToFirstColdBlock->bbJumpKind)
15866             {
15867                 default:
15868                     noway_assert(!"Unhandled jumpkind in fgDetermineFirstColdBlock()");
15869
15870                 case BBJ_CALLFINALLY:
15871                     // A BBJ_CALLFINALLY that falls through is always followed
15872                     // by an empty BBJ_ALWAYS.
15873                     //
15874                     assert(prevToFirstColdBlock->isBBCallAlwaysPair());
15875                     firstColdBlock =
15876                         firstColdBlock->bbNext; // Note that this assignment could make firstColdBlock == nullptr
15877                     break;
15878
15879                 case BBJ_COND:
15880                     //
15881                     // This is a slightly more complicated case, because we will
15882                     // probably need to insert a block to jump to the cold section.
15883                     //
15884                     if (firstColdBlock->isEmpty() && (firstColdBlock->bbJumpKind == BBJ_ALWAYS))
15885                     {
15886                         // We can just use this block as the transitionBlock
15887                         firstColdBlock = firstColdBlock->bbNext;
15888                         // Note that this assignment could make firstColdBlock == NULL
15889                     }
15890                     else
15891                     {
15892                         BasicBlock* transitionBlock = fgNewBBafter(BBJ_ALWAYS, prevToFirstColdBlock, true);
15893                         transitionBlock->bbJumpDest = firstColdBlock;
15894                         transitionBlock->inheritWeight(firstColdBlock);
15895
15896                         noway_assert(fgComputePredsDone);
15897
15898                         // Update the predecessor list for firstColdBlock
15899                         fgReplacePred(firstColdBlock, prevToFirstColdBlock, transitionBlock);
15900
15901                         // Add prevToFirstColdBlock as a predecessor for transitionBlock
15902                         fgAddRefPred(transitionBlock, prevToFirstColdBlock);
15903                     }
15904                     break;
15905
15906                 case BBJ_NONE:
15907                     // If the block preceding the first cold block is BBJ_NONE,
15908                     // convert it to BBJ_ALWAYS to force an explicit jump.
15909
15910                     prevToFirstColdBlock->bbJumpDest = firstColdBlock;
15911                     prevToFirstColdBlock->bbJumpKind = BBJ_ALWAYS;
15912                     break;
15913             }
15914         }
15915     }
15916
15917     if (firstColdBlock != nullptr)
15918     {
15919         firstColdBlock->bbFlags |= BBF_JMP_TARGET;
15920
15921         for (block = firstColdBlock; block; block = block->bbNext)
15922         {
15923             block->bbFlags |= BBF_COLD;
15924         }
15925     }
15926
15927 EXIT:;
15928
15929 #ifdef DEBUG
15930     if (verbose)
15931     {
15932         if (firstColdBlock)
15933         {
15934             printf("fgFirstColdBlock is BB%02u.\n", firstColdBlock->bbNum);
15935         }
15936         else
15937         {
15938             printf("fgFirstColdBlock is NULL.\n");
15939         }
15940
15941         fgDispBasicBlocks();
15942     }
15943
15944     fgVerifyHandlerTab();
15945 #endif // DEBUG
15946
15947     fgFirstColdBlock = firstColdBlock;
15948 }
15949
15950 #ifdef _PREFAST_
15951 #pragma warning(push)
15952 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
15953 #endif
15954 /*****************************************************************************
15955  *
15956  *  Function called to "comb" the basic block list.
15957  *  Removes any empty blocks, unreachable blocks and redundant jumps.
15958  *  Most of those appear after dead store removal and folding of conditionals.
15959  *
15960  *  Returns: true if the flowgraph has been modified
15961  *
15962  *  It also compacts basic blocks
15963  *   (consecutive basic blocks that should in fact be one).
15964  *
15965  *  NOTE:
15966  *    Debuggable code and Min Optimization JIT also introduces basic blocks
15967  *    but we do not optimize those!
15968  */
15969
15970 bool Compiler::fgUpdateFlowGraph(bool doTailDuplication)
15971 {
15972 #ifdef DEBUG
15973     if (verbose)
15974     {
15975         printf("\n*************** In fgUpdateFlowGraph()");
15976     }
15977 #endif // DEBUG
15978
15979     /* This should never be called for debuggable code */
15980
15981     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
15982
15983 #ifdef DEBUG
15984     if (verbose)
15985     {
15986         printf("\nBefore updating the flow graph:\n");
15987         fgDispBasicBlocks(verboseTrees);
15988         printf("\n");
15989     }
15990 #endif // DEBUG
15991
15992     /* Walk all the basic blocks - look for unconditional jumps, empty blocks, blocks to compact, etc...
15993      *
15994      * OBSERVATION:
15995      *      Once a block is removed the predecessors are not accurate (assuming they were at the beginning)
15996      *      For now we will only use the information in bbRefs because it is easier to be updated
15997      */
15998
15999     bool modified = false;
16000     bool change;
16001     do
16002     {
16003         change = false;
16004
16005         BasicBlock* block;           // the current block
16006         BasicBlock* bPrev = nullptr; // the previous non-worthless block
16007         BasicBlock* bNext;           // the successor of the current block
16008         BasicBlock* bDest;           // the jump target of the current block
16009
16010         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
16011         {
16012             /*  Some blocks may be already marked removed by other optimizations
16013              *  (e.g worthless loop removal), without being explicitly removed
16014              *  from the list.
16015              */
16016
16017             if (block->bbFlags & BBF_REMOVED)
16018             {
16019                 if (bPrev)
16020                 {
16021                     bPrev->setNext(block->bbNext);
16022                 }
16023                 else
16024                 {
16025                     /* WEIRD first basic block is removed - should have an assert here */
16026                     noway_assert(!"First basic block marked as BBF_REMOVED???");
16027
16028                     fgFirstBB = block->bbNext;
16029                 }
16030                 continue;
16031             }
16032
16033         /*  We jump to the REPEAT label if we performed a change involving the current block
16034          *  This is in case there are other optimizations that can show up
16035          *  (e.g. - compact 3 blocks in a row)
16036          *  If nothing happens, we then finish the iteration and move to the next block
16037          */
16038
16039         REPEAT:;
16040
16041             bNext = block->bbNext;
16042             bDest = nullptr;
16043
16044             if (block->bbJumpKind == BBJ_ALWAYS)
16045             {
16046                 bDest = block->bbJumpDest;
16047                 if (doTailDuplication && fgOptimizeUncondBranchToSimpleCond(block, bDest))
16048                 {
16049                     change   = true;
16050                     modified = true;
16051                     bDest    = block->bbJumpDest;
16052                     bNext    = block->bbNext;
16053                 }
16054             }
16055
16056             // Remove JUMPS to the following block
16057             // and optimize any JUMPS to JUMPS
16058
16059             if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
16060             {
16061                 bDest = block->bbJumpDest;
16062                 if (bDest == bNext)
16063                 {
16064                     if (fgOptimizeBranchToNext(block, bNext, bPrev))
16065                     {
16066                         change   = true;
16067                         modified = true;
16068                         bDest    = nullptr;
16069                     }
16070                 }
16071             }
16072
16073             if (bDest != nullptr)
16074             {
16075                 // Do we have a JUMP to an empty unconditional JUMP block?
16076                 if (bDest->isEmpty() && (bDest->bbJumpKind == BBJ_ALWAYS) &&
16077                     (bDest != bDest->bbJumpDest)) // special case for self jumps
16078                 {
16079                     if (fgOptimizeBranchToEmptyUnconditional(block, bDest))
16080                     {
16081                         change   = true;
16082                         modified = true;
16083                         goto REPEAT;
16084                     }
16085                 }
16086
16087                 // Check for a conditional branch that just skips over an empty BBJ_ALWAYS block
16088
16089                 if ((block->bbJumpKind == BBJ_COND) &&   // block is a BBJ_COND block
16090                     (bNext != nullptr) &&                // block is not the last block
16091                     (bNext->bbRefs == 1) &&              // No other block jumps to bNext
16092                     (bNext->bbNext == bDest) &&          // The block after bNext is the BBJ_COND jump dest
16093                     (bNext->bbJumpKind == BBJ_ALWAYS) && // The next block is a BBJ_ALWAYS block
16094                     bNext->isEmpty() &&                  // and it is an an empty block
16095                     (bNext != bNext->bbJumpDest) &&      // special case for self jumps
16096                     (bDest != fgFirstColdBlock))
16097                 {
16098                     bool optimizeJump = true;
16099
16100                     // We do not optimize jumps between two different try regions.
16101                     // However jumping to a block that is not in any try region is OK
16102                     //
16103                     if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
16104                     {
16105                         optimizeJump = false;
16106                     }
16107
16108                     // Also consider bNext's try region
16109                     //
16110                     if (bNext->hasTryIndex() && !BasicBlock::sameTryRegion(block, bNext))
16111                     {
16112                         optimizeJump = false;
16113                     }
16114
16115                     // If we are optimizing using real profile weights
16116                     // then don't optimize a conditional jump to an unconditional jump
16117                     // until after we have computed the edge weights
16118                     //
16119                     if (fgIsUsingProfileWeights())
16120                     {
16121                         // if block and bdest are in different hot/cold regions we can't do this this optimization
16122                         // because we can't allow fall-through into the cold region.
16123                         if (!fgEdgeWeightsComputed || fgInDifferentRegions(block, bDest))
16124                         {
16125                             fgNeedsUpdateFlowGraph = true;
16126                             optimizeJump           = false;
16127                         }
16128                     }
16129
16130                     if (optimizeJump)
16131                     {
16132 #ifdef DEBUG
16133                         if (verbose)
16134                         {
16135                             printf("\nReversing a conditional jump around an unconditional jump (BB%02u -> BB%02u -> "
16136                                    "BB%02u)\n",
16137                                    block->bbNum, bDest->bbNum, bNext->bbJumpDest->bbNum);
16138                         }
16139 #endif // DEBUG
16140                         /* Reverse the jump condition */
16141
16142                         GenTree* test = block->lastNode();
16143                         noway_assert(test->OperIsConditionalJump());
16144
16145                         if (test->OperGet() == GT_JTRUE)
16146                         {
16147                             GenTree* cond = gtReverseCond(test->gtOp.gtOp1);
16148                             assert(cond == test->gtOp.gtOp1); // Ensure `gtReverseCond` did not create a new node.
16149                             test->gtOp.gtOp1 = cond;
16150                         }
16151                         else
16152                         {
16153                             gtReverseCond(test);
16154                         }
16155
16156                         // Optimize the Conditional JUMP to go to the new target
16157                         block->bbJumpDest = bNext->bbJumpDest;
16158
16159                         fgAddRefPred(bNext->bbJumpDest, block, fgRemoveRefPred(bNext->bbJumpDest, bNext));
16160
16161                         /*
16162                           Unlink bNext from the BasicBlock list; note that we can
16163                           do this even though other blocks could jump to it - the
16164                           reason is that elsewhere in this function we always
16165                           redirect jumps to jumps to jump to the final label,
16166                           so even if another block jumps to bNext it won't matter
16167                           once we're done since any such jump will be redirected
16168                           to the final target by the time we're done here.
16169                         */
16170
16171                         fgRemoveRefPred(bNext, block);
16172                         fgUnlinkBlock(bNext);
16173
16174                         /* Mark the block as removed */
16175                         bNext->bbFlags |= BBF_REMOVED;
16176
16177                         // If this is the first Cold basic block update fgFirstColdBlock
16178                         if (bNext == fgFirstColdBlock)
16179                         {
16180                             fgFirstColdBlock = bNext->bbNext;
16181                         }
16182
16183                         //
16184                         // If we removed the end of a try region or handler region
16185                         // we will need to update ebdTryLast or ebdHndLast.
16186                         //
16187
16188                         EHblkDsc* HBtab;
16189                         EHblkDsc* HBtabEnd;
16190
16191                         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd;
16192                              HBtab++)
16193                         {
16194                             if ((HBtab->ebdTryLast == bNext) || (HBtab->ebdHndLast == bNext))
16195                             {
16196                                 fgSkipRmvdBlocks(HBtab);
16197                             }
16198                         }
16199
16200                         // we optimized this JUMP - goto REPEAT to catch similar cases
16201                         change   = true;
16202                         modified = true;
16203
16204 #ifdef DEBUG
16205                         if (verbose)
16206                         {
16207                             printf("\nAfter reversing the jump:\n");
16208                             fgDispBasicBlocks(verboseTrees);
16209                         }
16210 #endif // DEBUG
16211
16212                         /*
16213                            For a rare special case we cannot jump to REPEAT
16214                            as jumping to REPEAT will cause us to delete 'block'
16215                            because it currently appears to be unreachable.  As
16216                            it is a self loop that only has a single bbRef (itself)
16217                            However since the unlinked bNext has additional bbRefs
16218                            (that we will later connect to 'block'), it is not really
16219                            unreachable.
16220                         */
16221                         if ((bNext->bbRefs > 0) && (bNext->bbJumpDest == block) && (block->bbRefs == 1))
16222                         {
16223                             continue;
16224                         }
16225
16226                         goto REPEAT;
16227                     }
16228                 }
16229             }
16230
16231             //
16232             // Update the switch jump table such that it follows jumps to jumps:
16233             //
16234             if (block->bbJumpKind == BBJ_SWITCH)
16235             {
16236                 if (fgOptimizeSwitchBranches(block))
16237                 {
16238                     change   = true;
16239                     modified = true;
16240                     goto REPEAT;
16241                 }
16242             }
16243
16244             noway_assert(!(block->bbFlags & BBF_REMOVED));
16245
16246             /* COMPACT blocks if possible */
16247
16248             if (fgCanCompactBlocks(block, bNext))
16249             {
16250                 fgCompactBlocks(block, bNext);
16251
16252                 /* we compacted two blocks - goto REPEAT to catch similar cases */
16253                 change   = true;
16254                 modified = true;
16255                 goto REPEAT;
16256             }
16257
16258             /* Remove unreachable or empty blocks - do not consider blocks marked BBF_DONT_REMOVE or genReturnBB block
16259              * These include first and last block of a TRY, exception handlers and RANGE_CHECK_FAIL THROW blocks */
16260
16261             if ((block->bbFlags & BBF_DONT_REMOVE) == BBF_DONT_REMOVE || block == genReturnBB)
16262             {
16263                 bPrev = block;
16264                 continue;
16265             }
16266
16267 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16268             // Don't remove the BBJ_ALWAYS block of a BBJ_CALLFINALLY/BBJ_ALWAYS pair.
16269             if (block->countOfInEdges() == 0 && bPrev->bbJumpKind == BBJ_CALLFINALLY)
16270             {
16271                 assert(bPrev->isBBCallAlwaysPair());
16272                 noway_assert(!(bPrev->bbFlags & BBF_RETLESS_CALL));
16273                 noway_assert(block->bbJumpKind == BBJ_ALWAYS);
16274                 bPrev = block;
16275                 continue;
16276             }
16277 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16278
16279             noway_assert(!block->bbCatchTyp);
16280             noway_assert(!(block->bbFlags & BBF_TRY_BEG));
16281
16282             /* Remove unreachable blocks
16283              *
16284              * We'll look for blocks that have countOfInEdges() = 0 (blocks may become
16285              * unreachable due to a BBJ_ALWAYS introduced by conditional folding for example)
16286              */
16287
16288             if (block->countOfInEdges() == 0)
16289             {
16290                 /* no references -> unreachable - remove it */
16291                 /* For now do not update the bbNum, do it at the end */
16292
16293                 fgRemoveBlock(block, true);
16294
16295                 change   = true;
16296                 modified = true;
16297
16298                 /* we removed the current block - the rest of the optimizations won't have a target
16299                  * continue with the next one */
16300
16301                 continue;
16302             }
16303             else if (block->countOfInEdges() == 1)
16304             {
16305                 switch (block->bbJumpKind)
16306                 {
16307                     case BBJ_COND:
16308                     case BBJ_ALWAYS:
16309                         if (block->bbJumpDest == block)
16310                         {
16311                             fgRemoveBlock(block, true);
16312
16313                             change   = true;
16314                             modified = true;
16315
16316                             /* we removed the current block - the rest of the optimizations
16317                              * won't have a target so continue with the next block */
16318
16319                             continue;
16320                         }
16321                         break;
16322
16323                     default:
16324                         break;
16325                 }
16326             }
16327
16328             noway_assert(!(block->bbFlags & BBF_REMOVED));
16329
16330             /* Remove EMPTY blocks */
16331
16332             if (block->isEmpty())
16333             {
16334                 assert(bPrev == block->bbPrev);
16335                 if (fgOptimizeEmptyBlock(block))
16336                 {
16337                     change   = true;
16338                     modified = true;
16339                 }
16340
16341                 /* Have we removed the block? */
16342
16343                 if (block->bbFlags & BBF_REMOVED)
16344                 {
16345                     /* block was removed - no change to bPrev */
16346                     continue;
16347                 }
16348             }
16349
16350             /* Set the predecessor of the last reachable block
16351              * If we removed the current block, the predecessor remains unchanged
16352              * otherwise, since the current block is ok, it becomes the predecessor */
16353
16354             noway_assert(!(block->bbFlags & BBF_REMOVED));
16355
16356             bPrev = block;
16357         }
16358     } while (change);
16359
16360     fgNeedsUpdateFlowGraph = false;
16361
16362 #ifdef DEBUG
16363     if (verbose && modified)
16364     {
16365         printf("\nAfter updating the flow graph:\n");
16366         fgDispBasicBlocks(verboseTrees);
16367         fgDispHandlerTab();
16368     }
16369
16370     if (compRationalIRForm)
16371     {
16372         for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
16373         {
16374             LIR::AsRange(block).CheckLIR(this);
16375         }
16376     }
16377
16378     fgVerifyHandlerTab();
16379     // Make sure that the predecessor lists are accurate
16380     fgDebugCheckBBlist();
16381     fgDebugCheckUpdate();
16382 #endif // DEBUG
16383
16384     return modified;
16385 }
16386 #ifdef _PREFAST_
16387 #pragma warning(pop)
16388 #endif
16389
16390 /*****************************************************************************
16391  *  Check that the flow graph is really updated
16392  */
16393
16394 #ifdef DEBUG
16395
16396 void Compiler::fgDebugCheckUpdate()
16397 {
16398     if (!compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))
16399     {
16400         return;
16401     }
16402
16403     /* We check for these conditions:
16404      * no unreachable blocks  -> no blocks have countOfInEdges() = 0
16405      * no empty blocks        -> no blocks have bbTreeList = 0
16406      * no un-imported blocks  -> no blocks have BBF_IMPORTED not set (this is
16407      *                           kind of redundand with the above, but to make sure)
16408      * no un-compacted blocks -> BBJ_NONE followed by block with no jumps to it (countOfInEdges() = 1)
16409      */
16410
16411     BasicBlock* prev;
16412     BasicBlock* block;
16413     for (prev = nullptr, block = fgFirstBB; block != nullptr; prev = block, block = block->bbNext)
16414     {
16415         /* no unreachable blocks */
16416
16417         if ((block->countOfInEdges() == 0) && !(block->bbFlags & BBF_DONT_REMOVE)
16418 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16419             // With funclets, we never get rid of the BBJ_ALWAYS part of a BBJ_CALLFINALLY/BBJ_ALWAYS pair,
16420             // even if we can prove that the finally block never returns.
16421             && (prev == NULL || block->bbJumpKind != BBJ_ALWAYS || !prev->isBBCallAlwaysPair())
16422 #endif // FEATURE_EH_FUNCLETS
16423                 )
16424         {
16425             noway_assert(!"Unreachable block not removed!");
16426         }
16427
16428         /* no empty blocks */
16429
16430         if (block->isEmpty() && !(block->bbFlags & BBF_DONT_REMOVE))
16431         {
16432             switch (block->bbJumpKind)
16433             {
16434                 case BBJ_CALLFINALLY:
16435                 case BBJ_EHFINALLYRET:
16436                 case BBJ_EHFILTERRET:
16437                 case BBJ_RETURN:
16438                 /* for BBJ_ALWAYS is probably just a GOTO, but will have to be treated */
16439                 case BBJ_ALWAYS:
16440                 case BBJ_EHCATCHRET:
16441                     /* These jump kinds are allowed to have empty tree lists */
16442                     break;
16443
16444                 default:
16445                     /* it may be the case that the block had more than one reference to it
16446                      * so we couldn't remove it */
16447
16448                     if (block->countOfInEdges() == 0)
16449                     {
16450                         noway_assert(!"Empty block not removed!");
16451                     }
16452                     break;
16453             }
16454         }
16455
16456         /* no un-imported blocks */
16457
16458         if (!(block->bbFlags & BBF_IMPORTED))
16459         {
16460             /* internal blocks do not count */
16461
16462             if (!(block->bbFlags & BBF_INTERNAL))
16463             {
16464                 noway_assert(!"Non IMPORTED block not removed!");
16465             }
16466         }
16467
16468         bool prevIsCallAlwaysPair = ((prev != nullptr) && prev->isBBCallAlwaysPair());
16469
16470         // Check for an unnecessary jumps to the next block
16471         bool doAssertOnJumpToNextBlock = false; // unless we have a BBJ_COND or BBJ_ALWAYS we can not assert
16472
16473         if (block->bbJumpKind == BBJ_COND)
16474         {
16475             // A conditional branch should never jump to the next block
16476             // as it can be folded into a BBJ_NONE;
16477             doAssertOnJumpToNextBlock = true;
16478         }
16479         else if (block->bbJumpKind == BBJ_ALWAYS)
16480         {
16481             // Generally we will want to assert if a BBJ_ALWAYS branches to the next block
16482             doAssertOnJumpToNextBlock = true;
16483
16484             // If the BBF_KEEP_BBJ_ALWAYS flag is set we allow it to jump to the next block
16485             if (block->bbFlags & BBF_KEEP_BBJ_ALWAYS)
16486             {
16487                 doAssertOnJumpToNextBlock = false;
16488             }
16489
16490             // A call/always pair is also allowed to jump to the next block
16491             if (prevIsCallAlwaysPair)
16492             {
16493                 doAssertOnJumpToNextBlock = false;
16494             }
16495
16496             // We are allowed to have a branch from a hot 'block' to a cold 'bbNext'
16497             //
16498             if ((block->bbNext != nullptr) && fgInDifferentRegions(block, block->bbNext))
16499             {
16500                 doAssertOnJumpToNextBlock = false;
16501             }
16502         }
16503
16504         if (doAssertOnJumpToNextBlock)
16505         {
16506             if (block->bbJumpDest == block->bbNext)
16507             {
16508                 noway_assert(!"Unnecessary jump to the next block!");
16509             }
16510         }
16511
16512         /* Make sure BBF_KEEP_BBJ_ALWAYS is set correctly */
16513
16514         if ((block->bbJumpKind == BBJ_ALWAYS) && prevIsCallAlwaysPair)
16515         {
16516             noway_assert(block->bbFlags & BBF_KEEP_BBJ_ALWAYS);
16517         }
16518
16519         /* For a BBJ_CALLFINALLY block we make sure that we are followed by */
16520         /* an BBJ_ALWAYS block with BBF_INTERNAL set */
16521         /* or that it's a BBF_RETLESS_CALL */
16522         if (block->bbJumpKind == BBJ_CALLFINALLY)
16523         {
16524             assert((block->bbFlags & BBF_RETLESS_CALL) || block->isBBCallAlwaysPair());
16525         }
16526
16527         /* no un-compacted blocks */
16528
16529         if (fgCanCompactBlocks(block, block->bbNext))
16530         {
16531             noway_assert(!"Found un-compacted blocks!");
16532         }
16533     }
16534 }
16535
16536 #endif // DEBUG
16537
16538 /*****************************************************************************
16539  * We've inserted a new block before 'block' that should be part of the same EH region as 'block'.
16540  * Update the EH table to make this so. Also, set the new block to have the right EH region data
16541  * (copy the bbTryIndex, bbHndIndex, and bbCatchTyp from 'block' to the new predecessor, and clear
16542  * 'bbCatchTyp' from 'block').
16543  */
16544 void Compiler::fgExtendEHRegionBefore(BasicBlock* block)
16545 {
16546     assert(block->bbPrev != nullptr);
16547
16548     BasicBlock* bPrev = block->bbPrev;
16549
16550     bPrev->copyEHRegion(block);
16551
16552     // The first block (and only the first block) of a handler has bbCatchTyp set
16553     bPrev->bbCatchTyp = block->bbCatchTyp;
16554     block->bbCatchTyp = BBCT_NONE;
16555
16556     EHblkDsc* HBtab;
16557     EHblkDsc* HBtabEnd;
16558
16559     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
16560     {
16561         /* Multiple pointers in EHblkDsc can point to same block. We can not early out after the first match. */
16562         if (HBtab->ebdTryBeg == block)
16563         {
16564 #ifdef DEBUG
16565             if (verbose)
16566             {
16567                 printf("EH#%u: New first block of try: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
16568             }
16569 #endif // DEBUG
16570             HBtab->ebdTryBeg = bPrev;
16571             bPrev->bbFlags |= BBF_TRY_BEG | BBF_DONT_REMOVE | BBF_HAS_LABEL;
16572             // clear the TryBeg flag unless it begins another try region
16573             if (!bbIsTryBeg(block))
16574             {
16575                 block->bbFlags &= ~BBF_TRY_BEG;
16576             }
16577         }
16578
16579         if (HBtab->ebdHndBeg == block)
16580         {
16581 #ifdef DEBUG
16582             if (verbose)
16583             {
16584                 printf("EH#%u: New first block of handler: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
16585             }
16586 #endif // DEBUG
16587
16588             // The first block of a handler has an artificial extra refcount. Transfer that to the new block.
16589             assert(block->bbRefs > 0);
16590             block->bbRefs--;
16591
16592             HBtab->ebdHndBeg = bPrev;
16593             bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL;
16594             bPrev->bbRefs++;
16595
16596             // If this is a handler for a filter, the last block of the filter will end with
16597             // a BBJ_EJFILTERRET block that has a bbJumpDest that jumps to the first block of
16598             // it's handler.  So we need to update it to keep things in sync.
16599             //
16600             if (HBtab->HasFilter())
16601             {
16602                 BasicBlock* bFilterLast = HBtab->BBFilterLast();
16603                 assert(bFilterLast != nullptr);
16604                 assert(bFilterLast->bbJumpKind == BBJ_EHFILTERRET);
16605                 assert(bFilterLast->bbJumpDest == block);
16606 #ifdef DEBUG
16607                 if (verbose)
16608                 {
16609                     printf("EH#%u: Updating bbJumpDest for filter ret block: BB%02u => BB%02u\n", ehGetIndex(HBtab),
16610                            bFilterLast->bbNum, bPrev->bbNum);
16611                 }
16612 #endif // DEBUG
16613                 // Change the bbJumpDest for bFilterLast from the old first 'block' to the new first 'bPrev'
16614                 bFilterLast->bbJumpDest = bPrev;
16615             }
16616         }
16617
16618         if (HBtab->HasFilter() && (HBtab->ebdFilter == block))
16619         {
16620 #ifdef DEBUG
16621             if (verbose)
16622             {
16623                 printf("EH#%u: New first block of filter: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
16624             }
16625 #endif // DEBUG
16626
16627             // The first block of a filter has an artificial extra refcount. Transfer that to the new block.
16628             assert(block->bbRefs > 0);
16629             block->bbRefs--;
16630
16631             HBtab->ebdFilter = bPrev;
16632             bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL;
16633             bPrev->bbRefs++;
16634         }
16635     }
16636 }
16637
16638 /*****************************************************************************
16639  * We've inserted a new block after 'block' that should be part of the same EH region as 'block'.
16640  * Update the EH table to make this so. Also, set the new block to have the right EH region data.
16641  */
16642
16643 void Compiler::fgExtendEHRegionAfter(BasicBlock* block)
16644 {
16645     BasicBlock* newBlk = block->bbNext;
16646     assert(newBlk != nullptr);
16647
16648     newBlk->copyEHRegion(block);
16649     newBlk->bbCatchTyp =
16650         BBCT_NONE; // Only the first block of a catch has this set, and 'newBlk' can't be the first block of a catch.
16651
16652     // TODO-Throughput: if the block is not in an EH region, then we don't need to walk the EH table looking for 'last'
16653     // block pointers to update.
16654     ehUpdateLastBlocks(block, newBlk);
16655 }
16656
16657 /*****************************************************************************
16658  *
16659  * Insert a BasicBlock before the given block.
16660  */
16661
16662 BasicBlock* Compiler::fgNewBBbefore(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion)
16663 {
16664     // Create a new BasicBlock and chain it in
16665
16666     BasicBlock* newBlk = bbNewBasicBlock(jumpKind);
16667     newBlk->bbFlags |= BBF_INTERNAL;
16668
16669     fgInsertBBbefore(block, newBlk);
16670
16671     newBlk->bbRefs = 0;
16672
16673     if (newBlk->bbFallsThrough() && block->isRunRarely())
16674     {
16675         newBlk->bbSetRunRarely();
16676     }
16677
16678     if (extendRegion)
16679     {
16680         fgExtendEHRegionBefore(block);
16681     }
16682     else
16683     {
16684         // When extendRegion is false the caller is responsible for setting these two values
16685         newBlk->setTryIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
16686         newBlk->setHndIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
16687     }
16688
16689     // We assume that if the block we are inserting before is in the cold region, then this new
16690     // block will also be in the cold region.
16691     newBlk->bbFlags |= (block->bbFlags & BBF_COLD);
16692
16693     return newBlk;
16694 }
16695
16696 /*****************************************************************************
16697  *
16698  * Insert a BasicBlock after the given block.
16699  */
16700
16701 BasicBlock* Compiler::fgNewBBafter(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion)
16702 {
16703     // Create a new BasicBlock and chain it in
16704
16705     BasicBlock* newBlk = bbNewBasicBlock(jumpKind);
16706     newBlk->bbFlags |= BBF_INTERNAL;
16707
16708     fgInsertBBafter(block, newBlk);
16709
16710     newBlk->bbRefs = 0;
16711
16712     if (block->bbFallsThrough() && block->isRunRarely())
16713     {
16714         newBlk->bbSetRunRarely();
16715     }
16716
16717     if (extendRegion)
16718     {
16719         fgExtendEHRegionAfter(block);
16720     }
16721     else
16722     {
16723         // When extendRegion is false the caller is responsible for setting these two values
16724         newBlk->setTryIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
16725         newBlk->setHndIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
16726     }
16727
16728     // If the new block is in the cold region (because the block we are inserting after
16729     // is in the cold region), mark it as such.
16730     newBlk->bbFlags |= (block->bbFlags & BBF_COLD);
16731
16732     return newBlk;
16733 }
16734
16735 /*****************************************************************************
16736  *  Inserts basic block before existing basic block.
16737  *
16738  *  If insertBeforeBlk is in the funclet region, then newBlk will be in the funclet region.
16739  *  (If insertBeforeBlk is the first block of the funclet region, then 'newBlk' will be the
16740  *  new first block of the funclet region.)
16741  */
16742 void Compiler::fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk)
16743 {
16744     if (insertBeforeBlk->bbPrev)
16745     {
16746         fgInsertBBafter(insertBeforeBlk->bbPrev, newBlk);
16747     }
16748     else
16749     {
16750         newBlk->setNext(fgFirstBB);
16751
16752         fgFirstBB      = newBlk;
16753         newBlk->bbPrev = nullptr;
16754     }
16755
16756 #if FEATURE_EH_FUNCLETS
16757
16758     /* Update fgFirstFuncletBB if insertBeforeBlk is the first block of the funclet region. */
16759
16760     if (fgFirstFuncletBB == insertBeforeBlk)
16761     {
16762         fgFirstFuncletBB = newBlk;
16763     }
16764
16765 #endif // FEATURE_EH_FUNCLETS
16766 }
16767
16768 /*****************************************************************************
16769  *  Inserts basic block after existing basic block.
16770  *
16771  *  If insertBeforeBlk is in the funclet region, then newBlk will be in the funclet region.
16772  *  (It can't be used to insert a block as the first block of the funclet region).
16773  */
16774 void Compiler::fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk)
16775 {
16776     newBlk->bbNext = insertAfterBlk->bbNext;
16777
16778     if (insertAfterBlk->bbNext)
16779     {
16780         insertAfterBlk->bbNext->bbPrev = newBlk;
16781     }
16782
16783     insertAfterBlk->bbNext = newBlk;
16784     newBlk->bbPrev         = insertAfterBlk;
16785
16786     if (fgLastBB == insertAfterBlk)
16787     {
16788         fgLastBB = newBlk;
16789         assert(fgLastBB->bbNext == nullptr);
16790     }
16791 }
16792
16793 // We have two edges (bAlt => bCur) and (bCur => bNext).
16794 //
16795 // Returns true if the weight of (bAlt => bCur)
16796 //  is greater than the weight of (bCur => bNext).
16797 // We compare the edge weights if we have valid edge weights
16798 //  otherwise we compare blocks weights.
16799 //
16800 bool Compiler::fgIsBetterFallThrough(BasicBlock* bCur, BasicBlock* bAlt)
16801 {
16802     // bCur can't be NULL and must be a fall through bbJumpKind
16803     noway_assert(bCur != nullptr);
16804     noway_assert(bCur->bbFallsThrough());
16805     noway_assert(bAlt != nullptr);
16806
16807     // We only handle the cases when bAlt is a BBJ_ALWAYS or a BBJ_COND
16808     if ((bAlt->bbJumpKind != BBJ_ALWAYS) && (bAlt->bbJumpKind != BBJ_COND))
16809     {
16810         return false;
16811     }
16812
16813     // if bAlt doesn't jump to bCur it can't be a better fall through than bCur
16814     if (bAlt->bbJumpDest != bCur)
16815     {
16816         return false;
16817     }
16818
16819     // Currently bNext is the fall through for bCur
16820     BasicBlock* bNext = bCur->bbNext;
16821     noway_assert(bNext != nullptr);
16822
16823     // We will set result to true if bAlt is a better fall through than bCur
16824     bool result;
16825     if (fgHaveValidEdgeWeights)
16826     {
16827         // We will compare the edge weight for our two choices
16828         flowList* edgeFromAlt = fgGetPredForBlock(bCur, bAlt);
16829         flowList* edgeFromCur = fgGetPredForBlock(bNext, bCur);
16830         noway_assert(edgeFromCur != nullptr);
16831         noway_assert(edgeFromAlt != nullptr);
16832
16833         result = (edgeFromAlt->flEdgeWeightMin > edgeFromCur->flEdgeWeightMax);
16834     }
16835     else
16836     {
16837         if (bAlt->bbJumpKind == BBJ_ALWAYS)
16838         {
16839             // Our result is true if bAlt's weight is more than bCur's weight
16840             result = (bAlt->bbWeight > bCur->bbWeight);
16841         }
16842         else
16843         {
16844             noway_assert(bAlt->bbJumpKind == BBJ_COND);
16845             // Our result is true if bAlt's weight is more than twice bCur's weight
16846             result = (bAlt->bbWeight > (2 * bCur->bbWeight));
16847         }
16848     }
16849     return result;
16850 }
16851
16852 //------------------------------------------------------------------------
16853 // fgCheckEHCanInsertAfterBlock: Determine if a block can be inserted after
16854 // 'blk' and legally be put in the EH region specified by 'regionIndex'. This
16855 // can be true if the most nested region the block is in is already 'regionIndex',
16856 // as we'll just extend the most nested region (and any region ending at the same block).
16857 // It can also be true if it is the end of (a set of) EH regions, such that
16858 // inserting the block and properly extending some EH regions (if necessary)
16859 // puts the block in the correct region. We only consider the case of extending
16860 // an EH region after 'blk' (that is, to include 'blk' and the newly insert block);
16861 // we don't consider inserting a block as the the first block of an EH region following 'blk'.
16862 //
16863 // Consider this example:
16864 //
16865 //      try3   try2   try1
16866 //      |---   |      |      BB01
16867 //      |      |---   |      BB02
16868 //      |      |      |---   BB03
16869 //      |      |      |      BB04
16870 //      |      |---   |---   BB05
16871 //      |                    BB06
16872 //      |-----------------   BB07
16873 //
16874 // Passing BB05 and try1/try2/try3 as the region to insert into (as well as putInTryRegion==true)
16875 // will all return 'true'. Here are the cases:
16876 // 1. Insert into try1: the most nested EH region BB05 is in is already try1, so we can insert after
16877 //    it and extend try1 (and try2).
16878 // 2. Insert into try2: we can extend try2, but leave try1 alone.
16879 // 3. Insert into try3: we can leave try1 and try2 alone, and put the new block just in try3. Note that
16880 //    in this case, after we "loop outwards" in the EH nesting, we get to a place where we're in the middle
16881 //    of the try3 region, not at the end of it.
16882 // In all cases, it is possible to put a block after BB05 and put it in any of these three 'try' regions legally.
16883 //
16884 // Filters are ignored; if 'blk' is in a filter, the answer will be false.
16885 //
16886 // Arguments:
16887 //    blk - the BasicBlock we are checking to see if we can insert after.
16888 //    regionIndex - the EH region we want to insert a block into. regionIndex is
16889 //          in the range [0..compHndBBtabCount]; 0 means "main method".
16890 //    putInTryRegion - 'true' if the new block should be inserted in the 'try' region of 'regionIndex'.
16891 //          For regionIndex 0 (the "main method"), this should be 'true'.
16892 //
16893 // Return Value:
16894 //    'true' if a block can be inserted after 'blk' and put in EH region 'regionIndex', else 'false'.
16895 //
16896 bool Compiler::fgCheckEHCanInsertAfterBlock(BasicBlock* blk, unsigned regionIndex, bool putInTryRegion)
16897 {
16898     assert(blk != nullptr);
16899     assert(regionIndex <= compHndBBtabCount);
16900
16901     if (regionIndex == 0)
16902     {
16903         assert(putInTryRegion);
16904     }
16905
16906     bool     inTryRegion;
16907     unsigned nestedRegionIndex = ehGetMostNestedRegionIndex(blk, &inTryRegion);
16908
16909     bool insertOK = true;
16910     for (;;)
16911     {
16912         if (nestedRegionIndex == regionIndex)
16913         {
16914             // This block is in the region we want to be in. We can insert here if it's the right type of region.
16915             // (If we want to be in the 'try' region, but the block is in the handler region, then inserting a
16916             // new block after 'blk' can't put it in the 'try' region, and vice-versa, since we only consider
16917             // extending regions after, not prepending to regions.)
16918             // This check will be 'true' if we are trying to put something in the main function (as putInTryRegion
16919             // must be 'true' if regionIndex is zero, and inTryRegion will also be 'true' if nestedRegionIndex is zero).
16920             insertOK = (putInTryRegion == inTryRegion);
16921             break;
16922         }
16923         else if (nestedRegionIndex == 0)
16924         {
16925             // The block is in the main function, but we want to put something in a nested region. We can't do that.
16926             insertOK = false;
16927             break;
16928         }
16929
16930         assert(nestedRegionIndex > 0);
16931         EHblkDsc* ehDsc = ehGetDsc(nestedRegionIndex - 1); // ehGetDsc uses [0..compHndBBtabCount) form.
16932
16933         if (inTryRegion)
16934         {
16935             if (blk != ehDsc->ebdTryLast)
16936             {
16937                 // Not the last block? Then it must be somewhere else within the try region, so we can't insert here.
16938                 insertOK = false;
16939                 break; // exit the 'for' loop
16940             }
16941         }
16942         else
16943         {
16944             // We ignore filters.
16945             if (blk != ehDsc->ebdHndLast)
16946             {
16947                 // Not the last block? Then it must be somewhere else within the handler region, so we can't insert
16948                 // here.
16949                 insertOK = false;
16950                 break; // exit the 'for' loop
16951             }
16952         }
16953
16954         // Things look good for this region; check the enclosing regions, if any.
16955
16956         nestedRegionIndex =
16957             ehGetEnclosingRegionIndex(nestedRegionIndex - 1,
16958                                       &inTryRegion); // ehGetEnclosingRegionIndex uses [0..compHndBBtabCount) form.
16959
16960         // Convert to [0..compHndBBtabCount] form.
16961         nestedRegionIndex = (nestedRegionIndex == EHblkDsc::NO_ENCLOSING_INDEX) ? 0 : nestedRegionIndex + 1;
16962     } // end of for(;;)
16963
16964     return insertOK;
16965 }
16966
16967 //------------------------------------------------------------------------
16968 // Finds the block closest to endBlk in the range [startBlk..endBlk) after which a block can be
16969 // inserted easily. Note that endBlk cannot be returned; its predecessor is the last block that can
16970 // be returned. The new block will be put in an EH region described by the arguments regionIndex,
16971 // putInTryRegion, startBlk, and endBlk (explained below), so it must be legal to place to put the
16972 // new block after the insertion location block, give it the specified EH region index, and not break
16973 // EH nesting rules. This function is careful to choose a block in the correct EH region. However,
16974 // it assumes that the new block can ALWAYS be placed at the end (just before endBlk). That means
16975 // that the caller must ensure that is true.
16976 //
16977 // Below are the possible cases for the arguments to this method:
16978 //      1. putInTryRegion == true and regionIndex > 0:
16979 //         Search in the try region indicated by regionIndex.
16980 //      2. putInTryRegion == false and regionIndex > 0:
16981 //         a. If startBlk is the first block of a filter and endBlk is the block after the end of the
16982 //            filter (that is, the startBlk and endBlk match a filter bounds exactly), then choose a
16983 //            location within this filter region. (Note that, due to IL rules, filters do not have any
16984 //            EH nested within them.) Otherwise, filters are skipped.
16985 //         b. Else, search in the handler region indicated by regionIndex.
16986 //      3. regionIndex = 0:
16987 //         Search in the entire main method, excluding all EH regions. In this case, putInTryRegion must be true.
16988 //
16989 // This method makes sure to find an insertion point which would not cause the inserted block to
16990 // be put inside any inner try/filter/handler regions.
16991 //
16992 // The actual insertion occurs after the returned block. Note that the returned insertion point might
16993 // be the last block of a more nested EH region, because the new block will be inserted after the insertion
16994 // point, and will not extend the more nested EH region. For example:
16995 //
16996 //      try3   try2   try1
16997 //      |---   |      |      BB01
16998 //      |      |---   |      BB02
16999 //      |      |      |---   BB03
17000 //      |      |      |      BB04
17001 //      |      |---   |---   BB05
17002 //      |                    BB06
17003 //      |-----------------   BB07
17004 //
17005 // for regionIndex==try3, putInTryRegion==true, we might return BB05, even though BB05 will have a try index
17006 // for try1 (the most nested 'try' region the block is in). That's because when we insert after BB05, the new
17007 // block will be in the correct, desired EH region, since try1 and try2 regions will not be extended to include
17008 // the inserted block. Furthermore, for regionIndex==try2, putInTryRegion==true, we can also return BB05. In this
17009 // case, when the new block is inserted, the try1 region remains the same, but we need extend region 'try2' to
17010 // include the inserted block. (We also need to check all parent regions as well, just in case any parent regions
17011 // also end on the same block, in which case we would also need to extend the parent regions. This is standard
17012 // procedure when inserting a block at the end of an EH region.)
17013 //
17014 // If nearBlk is non-nullptr then we return the closest block after nearBlk that will work best.
17015 //
17016 // We try to find a block in the appropriate region that is not a fallthrough block, so we can insert after it
17017 // without the need to insert a jump around the inserted block.
17018 //
17019 // Note that regionIndex is numbered the same as BasicBlock::bbTryIndex and BasicBlock::bbHndIndex, that is, "0" is
17020 // "main method" and otherwise is +1 from normal, so we can call, e.g., ehGetDsc(tryIndex - 1).
17021 //
17022 // Arguments:
17023 //    regionIndex - the region index where the new block will be inserted. Zero means entire method;
17024 //          non-zero means either a "try" or a "handler" region, depending on what putInTryRegion says.
17025 //    putInTryRegion - 'true' to put the block in the 'try' region corresponding to 'regionIndex', 'false'
17026 //          to put the block in the handler region. Should be 'true' if regionIndex==0.
17027 //    startBlk - start block of range to search.
17028 //    endBlk - end block of range to search (don't include this block in the range). Can be nullptr to indicate
17029 //          the end of the function.
17030 //    nearBlk - If non-nullptr, try to find an insertion location closely after this block. If nullptr, we insert
17031 //          at the best location found towards the end of the acceptable block range.
17032 //    jumpBlk - When nearBlk is set, this can be set to the block which jumps to bNext->bbNext (TODO: need to review
17033 //    this?)
17034 //    runRarely - true if the block being inserted is expected to be rarely run. This helps determine
17035 //          the best place to put the new block, by putting in a place that has the same 'rarely run' characteristic.
17036 //
17037 // Return Value:
17038 //    A block with the desired characteristics, so the new block will be inserted after this one.
17039 //    If there is no suitable location, return nullptr. This should basically never happen.
17040
17041 BasicBlock* Compiler::fgFindInsertPoint(unsigned    regionIndex,
17042                                         bool        putInTryRegion,
17043                                         BasicBlock* startBlk,
17044                                         BasicBlock* endBlk,
17045                                         BasicBlock* nearBlk,
17046                                         BasicBlock* jumpBlk,
17047                                         bool        runRarely)
17048 {
17049     noway_assert(startBlk != nullptr);
17050     noway_assert(startBlk != endBlk);
17051     noway_assert((regionIndex == 0 && putInTryRegion) || // Search in the main method
17052                  (putInTryRegion && regionIndex > 0 &&
17053                   startBlk->bbTryIndex == regionIndex) || // Search in the specified try     region
17054                  (!putInTryRegion && regionIndex > 0 &&
17055                   startBlk->bbHndIndex == regionIndex)); // Search in the specified handler region
17056
17057 #ifdef DEBUG
17058     // Assert that startBlk precedes endBlk in the block list.
17059     // We don't want to use bbNum to assert this condition, as we cannot depend on the block numbers being
17060     // sequential at all times.
17061     for (BasicBlock* b = startBlk; b != endBlk; b = b->bbNext)
17062     {
17063         assert(b != nullptr); // We reached the end of the block list, but never found endBlk.
17064     }
17065 #endif // DEBUG
17066
17067     JITDUMP("fgFindInsertPoint(regionIndex=%u, putInTryRegion=%s, startBlk=BB%02u, endBlk=BB%02u, nearBlk=BB%02u, "
17068             "jumpBlk=BB%02u, runRarely=%s)\n",
17069             regionIndex, dspBool(putInTryRegion), startBlk->bbNum, (endBlk == nullptr) ? 0 : endBlk->bbNum,
17070             (nearBlk == nullptr) ? 0 : nearBlk->bbNum, (jumpBlk == nullptr) ? 0 : jumpBlk->bbNum, dspBool(runRarely));
17071
17072     bool        reachedNear = false; // Have we reached 'nearBlk' in our search? If not, we'll keep searching.
17073     bool        inFilter    = false; // Are we in a filter region that we need to skip?
17074     BasicBlock* bestBlk =
17075         nullptr; // Set to the best insertion point we've found so far that meets all the EH requirements.
17076     BasicBlock* goodBlk =
17077         nullptr; // Set to an acceptable insertion point that we'll use if we don't find a 'best' option.
17078     BasicBlock* blk;
17079
17080     if (nearBlk != nullptr)
17081     {
17082         // Does the nearBlk precede the startBlk?
17083         for (blk = nearBlk; blk != nullptr; blk = blk->bbNext)
17084         {
17085             if (blk == startBlk)
17086             {
17087                 reachedNear = true;
17088                 break;
17089             }
17090             else if (blk == endBlk)
17091             {
17092                 break;
17093             }
17094         }
17095     }
17096
17097     for (blk = startBlk; blk != endBlk; blk = blk->bbNext)
17098     {
17099         // The only way (blk == nullptr) could be true is if the caller passed an endBlk that preceded startBlk in the
17100         // block list, or if endBlk isn't in the block list at all. In DEBUG, we'll instead hit the similar
17101         // well-formedness assert earlier in this function.
17102         noway_assert(blk != nullptr);
17103
17104         if (blk == nearBlk)
17105         {
17106             reachedNear = true;
17107         }
17108
17109         if (blk->bbCatchTyp == BBCT_FILTER)
17110         {
17111             // Record the fact that we entered a filter region, so we don't insert into filters...
17112             // Unless the caller actually wanted the block inserted in this exact filter region.
17113             // Detect this by the fact that startBlk and endBlk point to the filter begin and end.
17114             if (putInTryRegion || (blk != startBlk) || (startBlk != ehGetDsc(regionIndex - 1)->ebdFilter) ||
17115                 (endBlk != ehGetDsc(regionIndex - 1)->ebdHndBeg))
17116             {
17117                 inFilter = true;
17118             }
17119         }
17120         else if (blk->bbCatchTyp == BBCT_FILTER_HANDLER)
17121         {
17122             // Record the fact that we exited a filter region.
17123             inFilter = false;
17124         }
17125
17126         // Don't insert a block inside this filter region.
17127         if (inFilter)
17128         {
17129             continue;
17130         }
17131
17132         // Note that the new block will be inserted AFTER "blk". We check to make sure that doing so
17133         // would put the block in the correct EH region. We make an assumption here that you can
17134         // ALWAYS insert the new block before "endBlk" (that is, at the end of the search range)
17135         // and be in the correct EH region. This is must be guaranteed by the caller (as it is by
17136         // fgNewBBinRegion(), which passes the search range as an exact EH region block range).
17137         // Because of this assumption, we only check the EH information for blocks before the last block.
17138         if (blk->bbNext != endBlk)
17139         {
17140             // We are in the middle of the search range. We can't insert the new block in
17141             // an inner try or handler region. We can, however, set the insertion
17142             // point to the last block of an EH try/handler region, if the enclosing
17143             // region is the region we wish to insert in. (Since multiple regions can
17144             // end at the same block, we need to search outwards, checking that the
17145             // block is the last block of every EH region out to the region we want
17146             // to insert in.) This is especially useful for putting a call-to-finally
17147             // block on AMD64 immediately after its corresponding 'try' block, so in the
17148             // common case, we'll just fall through to it. For example:
17149             //
17150             //      BB01
17151             //      BB02 -- first block of try
17152             //      BB03
17153             //      BB04 -- last block of try
17154             //      BB05 -- first block of finally
17155             //      BB06
17156             //      BB07 -- last block of handler
17157             //      BB08
17158             //
17159             // Assume there is only one try/finally, so BB01 and BB08 are in the "main function".
17160             // For AMD64 call-to-finally, we'll want to insert the BBJ_CALLFINALLY in
17161             // the main function, immediately after BB04. This allows us to do that.
17162
17163             if (!fgCheckEHCanInsertAfterBlock(blk, regionIndex, putInTryRegion))
17164             {
17165                 // Can't insert here.
17166                 continue;
17167             }
17168         }
17169
17170         // Look for an insert location:
17171         // 1. We want blocks that don't end with a fall through,
17172         // 2. Also, when blk equals nearBlk we may want to insert here.
17173         if (!blk->bbFallsThrough() || (blk == nearBlk))
17174         {
17175             bool updateBestBlk = true; // We will probably update the bestBlk
17176
17177             // If blk falls through then we must decide whether to use the nearBlk
17178             // hint
17179             if (blk->bbFallsThrough())
17180             {
17181                 noway_assert(blk == nearBlk);
17182                 if (jumpBlk != nullptr)
17183                 {
17184                     updateBestBlk = fgIsBetterFallThrough(blk, jumpBlk);
17185                 }
17186                 else
17187                 {
17188                     updateBestBlk = false;
17189                 }
17190             }
17191
17192             // If we already have a best block, see if the 'runRarely' flags influences
17193             // our choice. If we want a runRarely insertion point, and the existing best
17194             // block is run rarely but the current block isn't run rarely, then don't
17195             // update the best block.
17196             // TODO-CQ: We should also handle the reverse case, where runRarely is false (we
17197             // want a non-rarely-run block), but bestBlock->isRunRarely() is true. In that
17198             // case, we should update the block, also. Probably what we want is:
17199             //    (bestBlk->isRunRarely() != runRarely) && (blk->isRunRarely() == runRarely)
17200             if (updateBestBlk && (bestBlk != nullptr) && runRarely && bestBlk->isRunRarely() && !blk->isRunRarely())
17201             {
17202                 updateBestBlk = false;
17203             }
17204
17205             if (updateBestBlk)
17206             {
17207                 // We found a 'best' insertion location, so save it away.
17208                 bestBlk = blk;
17209
17210                 // If we've reached nearBlk, we've satisfied all the criteria,
17211                 // so we're done.
17212                 if (reachedNear)
17213                 {
17214                     goto DONE;
17215                 }
17216
17217                 // If we haven't reached nearBlk, keep looking for a 'best' location, just
17218                 // in case we'll find one at or after nearBlk. If no nearBlk was specified,
17219                 // we prefer inserting towards the end of the given range, so keep looking
17220                 // for more acceptable insertion locations.
17221             }
17222         }
17223
17224         // No need to update goodBlk after we have set bestBlk, but we could still find a better
17225         // bestBlk, so keep looking.
17226         if (bestBlk != nullptr)
17227         {
17228             continue;
17229         }
17230
17231         // Set the current block as a "good enough" insertion point, if it meets certain criteria.
17232         // We'll return this block if we don't find a "best" block in the search range. The block
17233         // can't be a BBJ_CALLFINALLY of a BBJ_CALLFINALLY/BBJ_ALWAYS pair (since we don't want
17234         // to insert anything between these two blocks). Otherwise, we can use it. However,
17235         // if we'd previously chosen a BBJ_COND block, then we'd prefer the "good" block to be
17236         // something else. We keep updating it until we've reached the 'nearBlk', to push it as
17237         // close to endBlk as possible.
17238         if (!blk->isBBCallAlwaysPair())
17239         {
17240             if (goodBlk == nullptr)
17241             {
17242                 goodBlk = blk;
17243             }
17244             else if ((goodBlk->bbJumpKind == BBJ_COND) || (blk->bbJumpKind != BBJ_COND))
17245             {
17246                 if ((blk == nearBlk) || !reachedNear)
17247                 {
17248                     goodBlk = blk;
17249                 }
17250             }
17251         }
17252     }
17253
17254     // If we didn't find a non-fall_through block, then insert at the last good block.
17255
17256     if (bestBlk == nullptr)
17257     {
17258         bestBlk = goodBlk;
17259     }
17260
17261 DONE:;
17262
17263     return bestBlk;
17264 }
17265
17266 //------------------------------------------------------------------------
17267 // Creates a new BasicBlock and inserts it in a specific EH region, given by 'tryIndex', 'hndIndex', and 'putInFilter'.
17268 //
17269 // If 'putInFilter' it true, then the block is inserted in the filter region given by 'hndIndex'. In this case, tryIndex
17270 // must be a less nested EH region (that is, tryIndex > hndIndex).
17271 //
17272 // Otherwise, the block is inserted in either the try region or the handler region, depending on which one is the inner
17273 // region. In other words, if the try region indicated by tryIndex is nested in the handler region indicated by
17274 // hndIndex,
17275 // then the new BB will be created in the try region. Vice versa.
17276 //
17277 // Note that tryIndex and hndIndex are numbered the same as BasicBlock::bbTryIndex and BasicBlock::bbHndIndex, that is,
17278 // "0" is "main method" and otherwise is +1 from normal, so we can call, e.g., ehGetDsc(tryIndex - 1).
17279 //
17280 // To be more specific, this function will create a new BB in one of the following 5 regions (if putInFilter is false):
17281 // 1. When tryIndex = 0 and hndIndex = 0:
17282 //    The new BB will be created in the method region.
17283 // 2. When tryIndex != 0 and hndIndex = 0:
17284 //    The new BB will be created in the try region indicated by tryIndex.
17285 // 3. When tryIndex == 0 and hndIndex != 0:
17286 //    The new BB will be created in the handler region indicated by hndIndex.
17287 // 4. When tryIndex != 0 and hndIndex != 0 and tryIndex < hndIndex:
17288 //    In this case, the try region is nested inside the handler region. Therefore, the new BB will be created
17289 //    in the try region indicated by tryIndex.
17290 // 5. When tryIndex != 0 and hndIndex != 0 and tryIndex > hndIndex:
17291 //    In this case, the handler region is nested inside the try region. Therefore, the new BB will be created
17292 //    in the handler region indicated by hndIndex.
17293 //
17294 // Note that if tryIndex != 0 and hndIndex != 0 then tryIndex must not be equal to hndIndex (this makes sense because
17295 // if they are equal, you are asking to put the new block in both the try and handler, which is impossible).
17296 //
17297 // The BasicBlock will not be inserted inside an EH region that is more nested than the requested tryIndex/hndIndex
17298 // region (so the function is careful to skip more nested EH regions when searching for a place to put the new block).
17299 //
17300 // This function cannot be used to insert a block as the first block of any region. It always inserts a block after
17301 // an existing block in the given region.
17302 //
17303 // If nearBlk is nullptr, or the block is run rarely, then the new block is assumed to be run rarely.
17304 //
17305 // Arguments:
17306 //    jumpKind - the jump kind of the new block to create.
17307 //    tryIndex - the try region to insert the new block in, described above. This must be a number in the range
17308 //               [0..compHndBBtabCount].
17309 //    hndIndex - the handler region to insert the new block in, described above. This must be a number in the range
17310 //               [0..compHndBBtabCount].
17311 //    nearBlk  - insert the new block closely after this block, if possible. If nullptr, put the new block anywhere
17312 //               in the requested region.
17313 //    putInFilter - put the new block in the filter region given by hndIndex, as described above.
17314 //    runRarely - 'true' if the new block is run rarely.
17315 //    insertAtEnd - 'true' if the block should be inserted at the end of the region. Note: this is currently only
17316 //                  implemented when inserting into the main function (not into any EH region).
17317 //
17318 // Return Value:
17319 //    The new block.
17320
17321 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind,
17322                                       unsigned    tryIndex,
17323                                       unsigned    hndIndex,
17324                                       BasicBlock* nearBlk,
17325                                       bool        putInFilter /* = false */,
17326                                       bool        runRarely /* = false */,
17327                                       bool        insertAtEnd /* = false */)
17328 {
17329     assert(tryIndex <= compHndBBtabCount);
17330     assert(hndIndex <= compHndBBtabCount);
17331
17332     /* afterBlk is the block which will precede the newBB */
17333     BasicBlock* afterBlk;
17334
17335     // start and end limit for inserting the block
17336     BasicBlock* startBlk = nullptr;
17337     BasicBlock* endBlk   = nullptr;
17338
17339     bool     putInTryRegion = true;
17340     unsigned regionIndex    = 0;
17341
17342     // First, figure out which region (the "try" region or the "handler" region) to put the newBB in.
17343     if ((tryIndex == 0) && (hndIndex == 0))
17344     {
17345         assert(!putInFilter);
17346
17347         endBlk = fgEndBBAfterMainFunction(); // don't put new BB in funclet region
17348
17349         if (insertAtEnd || (nearBlk == nullptr))
17350         {
17351             /* We'll just insert the block at the end of the method, before the funclets */
17352
17353             afterBlk = fgLastBBInMainFunction();
17354             goto _FoundAfterBlk;
17355         }
17356         else
17357         {
17358             // We'll search through the entire method
17359             startBlk = fgFirstBB;
17360         }
17361
17362         noway_assert(regionIndex == 0);
17363     }
17364     else
17365     {
17366         noway_assert(tryIndex > 0 || hndIndex > 0);
17367         PREFIX_ASSUME(tryIndex <= compHndBBtabCount);
17368         PREFIX_ASSUME(hndIndex <= compHndBBtabCount);
17369
17370         // Decide which region to put in, the "try" region or the "handler" region.
17371         if (tryIndex == 0)
17372         {
17373             noway_assert(hndIndex > 0);
17374             putInTryRegion = false;
17375         }
17376         else if (hndIndex == 0)
17377         {
17378             noway_assert(tryIndex > 0);
17379             noway_assert(putInTryRegion);
17380             assert(!putInFilter);
17381         }
17382         else
17383         {
17384             noway_assert(tryIndex > 0 && hndIndex > 0 && tryIndex != hndIndex);
17385             putInTryRegion = (tryIndex < hndIndex);
17386         }
17387
17388         if (putInTryRegion)
17389         {
17390             // Try region is the inner region.
17391             // In other words, try region must be nested inside the handler region.
17392             noway_assert(hndIndex == 0 || bbInHandlerRegions(hndIndex - 1, ehGetDsc(tryIndex - 1)->ebdTryBeg));
17393             assert(!putInFilter);
17394         }
17395         else
17396         {
17397             // Handler region is the inner region.
17398             // In other words, handler region must be nested inside the try region.
17399             noway_assert(tryIndex == 0 || bbInTryRegions(tryIndex - 1, ehGetDsc(hndIndex - 1)->ebdHndBeg));
17400         }
17401
17402         // Figure out the start and end block range to search for an insertion location. Pick the beginning and
17403         // ending blocks of the target EH region (the 'endBlk' is one past the last block of the EH region, to make
17404         // loop iteration easier). Note that, after funclets have been created (for FEATURE_EH_FUNCLETS),
17405         // this linear block range will not include blocks of handlers for try/handler clauses nested within
17406         // this EH region, as those blocks have been extracted as funclets. That is ok, though, because we don't
17407         // want to insert a block in any nested EH region.
17408
17409         if (putInTryRegion)
17410         {
17411             // We will put the newBB in the try region.
17412             EHblkDsc* ehDsc = ehGetDsc(tryIndex - 1);
17413             startBlk        = ehDsc->ebdTryBeg;
17414             endBlk          = ehDsc->ebdTryLast->bbNext;
17415             regionIndex     = tryIndex;
17416         }
17417         else if (putInFilter)
17418         {
17419             // We will put the newBB in the filter region.
17420             EHblkDsc* ehDsc = ehGetDsc(hndIndex - 1);
17421             startBlk        = ehDsc->ebdFilter;
17422             endBlk          = ehDsc->ebdHndBeg;
17423             regionIndex     = hndIndex;
17424         }
17425         else
17426         {
17427             // We will put the newBB in the handler region.
17428             EHblkDsc* ehDsc = ehGetDsc(hndIndex - 1);
17429             startBlk        = ehDsc->ebdHndBeg;
17430             endBlk          = ehDsc->ebdHndLast->bbNext;
17431             regionIndex     = hndIndex;
17432         }
17433
17434         noway_assert(regionIndex > 0);
17435     }
17436
17437     // Now find the insertion point.
17438     afterBlk = fgFindInsertPoint(regionIndex, putInTryRegion, startBlk, endBlk, nearBlk, nullptr, runRarely);
17439
17440 _FoundAfterBlk:;
17441
17442     /* We have decided to insert the block after 'afterBlk'. */
17443     noway_assert(afterBlk != nullptr);
17444
17445     JITDUMP("fgNewBBinRegion(jumpKind=%u, tryIndex=%u, hndIndex=%u, putInFilter=%s, runRarely=%s, insertAtEnd=%s): "
17446             "inserting after BB%02u\n",
17447             jumpKind, tryIndex, hndIndex, dspBool(putInFilter), dspBool(runRarely), dspBool(insertAtEnd),
17448             afterBlk->bbNum);
17449
17450     return fgNewBBinRegionWorker(jumpKind, afterBlk, regionIndex, putInTryRegion);
17451 }
17452
17453 //------------------------------------------------------------------------
17454 // Creates a new BasicBlock and inserts it in the same EH region as 'srcBlk'.
17455 //
17456 // See the implementation of fgNewBBinRegion() used by this one for more notes.
17457 //
17458 // Arguments:
17459 //    jumpKind - the jump kind of the new block to create.
17460 //    srcBlk   - insert the new block in the same EH region as this block, and closely after it if possible.
17461 //
17462 // Return Value:
17463 //    The new block.
17464
17465 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind,
17466                                       BasicBlock* srcBlk,
17467                                       bool        runRarely /* = false */,
17468                                       bool        insertAtEnd /* = false */)
17469 {
17470     assert(srcBlk != nullptr);
17471
17472     const unsigned tryIndex    = srcBlk->bbTryIndex;
17473     const unsigned hndIndex    = srcBlk->bbHndIndex;
17474     bool           putInFilter = false;
17475
17476     // Check to see if we need to put the new block in a filter. We do if srcBlk is in a filter.
17477     // This can only be true if there is a handler index, and the handler region is more nested than the
17478     // try region (if any). This is because no EH regions can be nested within a filter.
17479     if (BasicBlock::ehIndexMaybeMoreNested(hndIndex, tryIndex))
17480     {
17481         assert(hndIndex != 0); // If hndIndex is more nested, we must be in some handler!
17482         putInFilter = ehGetDsc(hndIndex - 1)->InFilterRegionBBRange(srcBlk);
17483     }
17484
17485     return fgNewBBinRegion(jumpKind, tryIndex, hndIndex, srcBlk, putInFilter, runRarely, insertAtEnd);
17486 }
17487
17488 //------------------------------------------------------------------------
17489 // Creates a new BasicBlock and inserts it at the end of the function.
17490 //
17491 // See the implementation of fgNewBBinRegion() used by this one for more notes.
17492 //
17493 // Arguments:
17494 //    jumpKind - the jump kind of the new block to create.
17495 //
17496 // Return Value:
17497 //    The new block.
17498
17499 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind)
17500 {
17501     return fgNewBBinRegion(jumpKind, 0, 0, nullptr, /* putInFilter */ false, /* runRarely */ false,
17502                            /* insertAtEnd */ true);
17503 }
17504
17505 //------------------------------------------------------------------------
17506 // Creates a new BasicBlock, and inserts it after 'afterBlk'.
17507 //
17508 // The block cannot be inserted into a more nested try/handler region than that specified by 'regionIndex'.
17509 // (It is given exactly 'regionIndex'.) Thus, the parameters must be passed to ensure proper EH nesting
17510 // rules are followed.
17511 //
17512 // Arguments:
17513 //    jumpKind - the jump kind of the new block to create.
17514 //    afterBlk - insert the new block after this one.
17515 //    regionIndex - the block will be put in this EH region.
17516 //    putInTryRegion - If true, put the new block in the 'try' region corresponding to 'regionIndex', and
17517 //          set its handler index to the most nested handler region enclosing that 'try' region.
17518 //          Otherwise, put the block in the handler region specified by 'regionIndex', and set its 'try'
17519 //          index to the most nested 'try' region enclosing that handler region.
17520 //
17521 // Return Value:
17522 //    The new block.
17523
17524 BasicBlock* Compiler::fgNewBBinRegionWorker(BBjumpKinds jumpKind,
17525                                             BasicBlock* afterBlk,
17526                                             unsigned    regionIndex,
17527                                             bool        putInTryRegion)
17528 {
17529     /* Insert the new block */
17530     BasicBlock* afterBlkNext = afterBlk->bbNext;
17531     (void)afterBlkNext; // prevent "unused variable" error from GCC
17532     BasicBlock* newBlk = fgNewBBafter(jumpKind, afterBlk, false);
17533
17534     if (putInTryRegion)
17535     {
17536         noway_assert(regionIndex <= MAX_XCPTN_INDEX);
17537         newBlk->bbTryIndex = (unsigned short)regionIndex;
17538         newBlk->bbHndIndex = bbFindInnermostHandlerRegionContainingTryRegion(regionIndex);
17539     }
17540     else
17541     {
17542         newBlk->bbTryIndex = bbFindInnermostTryRegionContainingHandlerRegion(regionIndex);
17543         noway_assert(regionIndex <= MAX_XCPTN_INDEX);
17544         newBlk->bbHndIndex = (unsigned short)regionIndex;
17545     }
17546
17547     // We're going to compare for equal try regions (to handle the case of 'mutually protect'
17548     // regions). We need to save off the current try region, otherwise we might change it
17549     // before it gets compared later, thereby making future comparisons fail.
17550
17551     BasicBlock* newTryBeg;
17552     BasicBlock* newTryLast;
17553     (void)ehInitTryBlockRange(newBlk, &newTryBeg, &newTryLast);
17554
17555     unsigned  XTnum;
17556     EHblkDsc* HBtab;
17557
17558     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
17559     {
17560         // Is afterBlk at the end of a try region?
17561         if (HBtab->ebdTryLast == afterBlk)
17562         {
17563             noway_assert(afterBlkNext == newBlk->bbNext);
17564
17565             bool extendTryRegion = false;
17566             if (newBlk->hasTryIndex())
17567             {
17568                 // We're adding a block after the last block of some try region. Do
17569                 // we extend the try region to include the block, or not?
17570                 // If the try region is exactly the same as the try region
17571                 // associated with the new block (based on the block's try index,
17572                 // which represents the innermost try the block is a part of), then
17573                 // we extend it.
17574                 // If the try region is a "parent" try region -- an enclosing try region
17575                 // that has the same last block as the new block's try region -- then
17576                 // we also extend. For example:
17577                 //      try { // 1
17578                 //          ...
17579                 //          try { // 2
17580                 //          ...
17581                 //      } /* 2 */ } /* 1 */
17582                 // This example is meant to indicate that both try regions 1 and 2 end at
17583                 // the same block, and we're extending 2. Thus, we must also extend 1. If we
17584                 // only extended 2, we would break proper nesting. (Dev11 bug 137967)
17585
17586                 extendTryRegion = HBtab->ebdIsSameTry(newTryBeg, newTryLast) || bbInTryRegions(XTnum, newBlk);
17587             }
17588
17589             // Does newBlk extend this try region?
17590             if (extendTryRegion)
17591             {
17592                 // Yes, newBlk extends this try region
17593
17594                 // newBlk is the now the new try last block
17595                 fgSetTryEnd(HBtab, newBlk);
17596             }
17597         }
17598
17599         // Is afterBlk at the end of a handler region?
17600         if (HBtab->ebdHndLast == afterBlk)
17601         {
17602             noway_assert(afterBlkNext == newBlk->bbNext);
17603
17604             // Does newBlk extend this handler region?
17605             bool extendHndRegion = false;
17606             if (newBlk->hasHndIndex())
17607             {
17608                 // We're adding a block after the last block of some handler region. Do
17609                 // we extend the handler region to include the block, or not?
17610                 // If the handler region is exactly the same as the handler region
17611                 // associated with the new block (based on the block's handler index,
17612                 // which represents the innermost handler the block is a part of), then
17613                 // we extend it.
17614                 // If the handler region is a "parent" handler region -- an enclosing
17615                 // handler region that has the same last block as the new block's handler
17616                 // region -- then we also extend. For example:
17617                 //      catch { // 1
17618                 //          ...
17619                 //          catch { // 2
17620                 //          ...
17621                 //      } /* 2 */ } /* 1 */
17622                 // This example is meant to indicate that both handler regions 1 and 2 end at
17623                 // the same block, and we're extending 2. Thus, we must also extend 1. If we
17624                 // only extended 2, we would break proper nesting. (Dev11 bug 372051)
17625
17626                 extendHndRegion = bbInHandlerRegions(XTnum, newBlk);
17627             }
17628
17629             if (extendHndRegion)
17630             {
17631                 // Yes, newBlk extends this handler region
17632
17633                 // newBlk is now the last block of the handler.
17634                 fgSetHndEnd(HBtab, newBlk);
17635             }
17636         }
17637     }
17638
17639     /* If afterBlk falls through, we insert a jump around newBlk */
17640     fgConnectFallThrough(afterBlk, newBlk->bbNext);
17641
17642 #ifdef DEBUG
17643     fgVerifyHandlerTab();
17644 #endif
17645
17646     return newBlk;
17647 }
17648
17649 /*****************************************************************************
17650  */
17651
17652 /* static */
17653 unsigned Compiler::acdHelper(SpecialCodeKind codeKind)
17654 {
17655     switch (codeKind)
17656     {
17657         case SCK_RNGCHK_FAIL:
17658             return CORINFO_HELP_RNGCHKFAIL;
17659         case SCK_ARG_EXCPN:
17660             return CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
17661         case SCK_ARG_RNG_EXCPN:
17662             return CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
17663         case SCK_DIV_BY_ZERO:
17664             return CORINFO_HELP_THROWDIVZERO;
17665         case SCK_ARITH_EXCPN:
17666             return CORINFO_HELP_OVERFLOW;
17667         default:
17668             assert(!"Bad codeKind");
17669             return 0;
17670     }
17671 }
17672
17673 /*****************************************************************************
17674  *
17675  *  Find/create an added code entry associated with the given block and with
17676  *  the given kind.
17677  */
17678
17679 BasicBlock* Compiler::fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, SpecialCodeKind kind, unsigned stkDepth)
17680 {
17681     // Record that the code will call a THROW_HELPER
17682     // so on Windows Amd64 we can allocate the 4 outgoing
17683     // arg slots on the stack frame if there are no other calls.
17684     compUsesThrowHelper = true;
17685
17686     // For debuggable code, genJumpToThrowHlpBlk() will generate the 'throw'
17687     // code inline. It has to be kept consistent with fgAddCodeRef()
17688     if (opts.compDbgCode)
17689     {
17690         return nullptr;
17691     }
17692
17693     const static BBjumpKinds jumpKinds[] = {
17694         BBJ_NONE,   // SCK_NONE
17695         BBJ_THROW,  // SCK_RNGCHK_FAIL
17696         BBJ_ALWAYS, // SCK_PAUSE_EXEC
17697         BBJ_THROW,  // SCK_DIV_BY_ZERO
17698         BBJ_THROW,  // SCK_ARITH_EXCP, SCK_OVERFLOW
17699         BBJ_THROW,  // SCK_ARG_EXCPN
17700         BBJ_THROW,  // SCK_ARG_RNG_EXCPN
17701     };
17702
17703     noway_assert(sizeof(jumpKinds) == SCK_COUNT); // sanity check
17704
17705     /* First look for an existing entry that matches what we're looking for */
17706
17707     AddCodeDsc* add = fgFindExcptnTarget(kind, refData);
17708
17709     if (add) // found it
17710     {
17711 #ifdef _TARGET_X86_
17712         // If different range checks happen at different stack levels,
17713         // they can't all jump to the same "call @rngChkFailed" AND have
17714         // frameless methods, as the rngChkFailed may need to unwind the
17715         // stack, and we have to be able to report the stack level.
17716         //
17717         // The following check forces most methods that reference an
17718         // array element in a parameter list to have an EBP frame,
17719         // this restriction could be removed with more careful code
17720         // generation for BBJ_THROW (i.e. range check failed).
17721         //
17722         // For Linux/x86, we possibly need to insert stack alignment adjustment
17723         // before the first stack argument pushed for every call. But we
17724         // don't know what the stack alignment adjustment will be when
17725         // we morph a tree that calls fgAddCodeRef(), so the stack depth
17726         // number will be incorrect. For now, simply force all functions with
17727         // these helpers to have EBP frames. It might be possible to make
17728         // this less conservative. E.g., for top-level (not nested) calls
17729         // without stack args, the stack pointer hasn't changed and stack
17730         // depth will be known to be zero. Or, figure out a way to update
17731         // or generate all required helpers after all stack alignment
17732         // has been added, and the stack level at each call to fgAddCodeRef()
17733         // is known, or can be recalculated.
17734         CLANG_FORMAT_COMMENT_ANCHOR;
17735
17736 #if defined(UNIX_X86_ABI)
17737         codeGen->setFrameRequired(true);
17738 #else  // !defined(UNIX_X86_ABI)
17739         if (add->acdStkLvl != stkDepth)
17740         {
17741             codeGen->setFrameRequired(true);
17742         }
17743 #endif // !defined(UNIX_X86_ABI)
17744 #endif // _TARGET_X86_
17745
17746         return add->acdDstBlk;
17747     }
17748
17749     /* We have to allocate a new entry and prepend it to the list */
17750
17751     add            = new (this, CMK_Unknown) AddCodeDsc;
17752     add->acdData   = refData;
17753     add->acdKind   = kind;
17754     add->acdStkLvl = (unsigned short)stkDepth;
17755     noway_assert(add->acdStkLvl == stkDepth);
17756     add->acdNext  = fgAddCodeList;
17757     fgAddCodeList = add;
17758
17759     /* Create the target basic block */
17760
17761     BasicBlock* newBlk;
17762
17763     newBlk = add->acdDstBlk = fgNewBBinRegion(jumpKinds[kind], srcBlk, /* runRarely */ true, /* insertAtEnd */ true);
17764
17765     add->acdDstBlk->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
17766
17767 #ifdef DEBUG
17768     if (verbose)
17769     {
17770         const char* msgWhere = "";
17771         if (!srcBlk->hasTryIndex() && !srcBlk->hasHndIndex())
17772         {
17773             msgWhere = "non-EH region";
17774         }
17775         else if (!srcBlk->hasTryIndex())
17776         {
17777             msgWhere = "handler";
17778         }
17779         else if (!srcBlk->hasHndIndex())
17780         {
17781             msgWhere = "try";
17782         }
17783         else if (srcBlk->getTryIndex() < srcBlk->getHndIndex())
17784         {
17785             msgWhere = "try";
17786         }
17787         else
17788         {
17789             msgWhere = "handler";
17790         }
17791
17792         const char* msg;
17793         switch (kind)
17794         {
17795             case SCK_RNGCHK_FAIL:
17796                 msg = " for RNGCHK_FAIL";
17797                 break;
17798             case SCK_PAUSE_EXEC:
17799                 msg = " for PAUSE_EXEC";
17800                 break;
17801             case SCK_DIV_BY_ZERO:
17802                 msg = " for DIV_BY_ZERO";
17803                 break;
17804             case SCK_OVERFLOW:
17805                 msg = " for OVERFLOW";
17806                 break;
17807             case SCK_ARG_EXCPN:
17808                 msg = " for ARG_EXCPN";
17809                 break;
17810             case SCK_ARG_RNG_EXCPN:
17811                 msg = " for ARG_RNG_EXCPN";
17812                 break;
17813             default:
17814                 msg = " for ??";
17815                 break;
17816         }
17817
17818         printf("\nfgAddCodeRef -"
17819                " Add BB in %s%s, new block BB%02u [%08p], stkDepth is %d\n",
17820                msgWhere, msg, add->acdDstBlk->bbNum, dspPtr(add->acdDstBlk), stkDepth);
17821     }
17822 #endif // DEBUG
17823
17824 #ifdef DEBUG
17825     newBlk->bbTgtStkDepth = stkDepth;
17826 #endif // DEBUG
17827
17828     /* Mark the block as added by the compiler and not removable by future flow
17829        graph optimizations. Note that no bbJumpDest points to these blocks. */
17830
17831     newBlk->bbFlags |= BBF_IMPORTED;
17832     newBlk->bbFlags |= BBF_DONT_REMOVE;
17833
17834     /* Remember that we're adding a new basic block */
17835
17836     fgAddCodeModf      = true;
17837     fgRngChkThrowAdded = true;
17838
17839     /* Now figure out what code to insert */
17840
17841     GenTreeCall* tree;
17842     int          helper = CORINFO_HELP_UNDEF;
17843
17844     switch (kind)
17845     {
17846         case SCK_RNGCHK_FAIL:
17847             helper = CORINFO_HELP_RNGCHKFAIL;
17848             break;
17849
17850         case SCK_DIV_BY_ZERO:
17851             helper = CORINFO_HELP_THROWDIVZERO;
17852             break;
17853
17854         case SCK_ARITH_EXCPN:
17855             helper = CORINFO_HELP_OVERFLOW;
17856             noway_assert(SCK_OVERFLOW == SCK_ARITH_EXCPN);
17857             break;
17858
17859         case SCK_ARG_EXCPN:
17860             helper = CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
17861             break;
17862
17863         case SCK_ARG_RNG_EXCPN:
17864             helper = CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
17865             break;
17866
17867         // case SCK_PAUSE_EXEC:
17868         //     noway_assert(!"add code to pause exec");
17869
17870         default:
17871             noway_assert(!"unexpected code addition kind");
17872             return nullptr;
17873     }
17874
17875     noway_assert(helper != CORINFO_HELP_UNDEF);
17876
17877     // Add the appropriate helper call.
17878     tree = gtNewHelperCallNode(helper, TYP_VOID, GTF_EXCEPT);
17879
17880     // There are no args here but fgMorphArgs has side effects
17881     // such as setting the outgoing arg area (which is necessary
17882     // on AMD if there are any calls).
17883     tree = fgMorphArgs(tree);
17884
17885     // Store the tree in the new basic block.
17886     assert(!srcBlk->isEmpty());
17887     if (!srcBlk->IsLIR())
17888     {
17889         fgInsertStmtAtEnd(newBlk, fgNewStmtFromTree(tree));
17890     }
17891     else
17892     {
17893         LIR::AsRange(newBlk).InsertAtEnd(LIR::SeqTree(this, tree));
17894     }
17895
17896     return add->acdDstBlk;
17897 }
17898
17899 /*****************************************************************************
17900  * Finds the block to jump to, to throw a given kind of exception
17901  * We maintain a cache of one AddCodeDsc for each kind, to make searching fast.
17902  * Note : Each block uses the same (maybe shared) block as the jump target for
17903  * a given type of exception
17904  */
17905
17906 Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData)
17907 {
17908     if (!(fgExcptnTargetCache[kind] && // Try the cached value first
17909           fgExcptnTargetCache[kind]->acdData == refData))
17910     {
17911         // Too bad, have to search for the jump target for the exception
17912
17913         AddCodeDsc* add = nullptr;
17914
17915         for (add = fgAddCodeList; add != nullptr; add = add->acdNext)
17916         {
17917             if (add->acdData == refData && add->acdKind == kind)
17918             {
17919                 break;
17920             }
17921         }
17922
17923         fgExcptnTargetCache[kind] = add; // Cache it
17924     }
17925
17926     return fgExcptnTargetCache[kind];
17927 }
17928
17929 /*****************************************************************************
17930  *
17931  *  The given basic block contains an array range check; return the label this
17932  *  range check is to jump to upon failure.
17933  */
17934
17935 BasicBlock* Compiler::fgRngChkTarget(BasicBlock* block, unsigned stkDepth, SpecialCodeKind kind)
17936 {
17937 #ifdef DEBUG
17938     if (verbose)
17939     {
17940         printf("*** Computing fgRngChkTarget for block BB%02u to stkDepth %d\n", block->bbNum, stkDepth);
17941         if (!block->IsLIR())
17942         {
17943             gtDispTree(compCurStmt);
17944         }
17945     }
17946 #endif // DEBUG
17947
17948     /* We attach the target label to the containing try block (if any) */
17949     noway_assert(!compIsForInlining());
17950     return fgAddCodeRef(block, bbThrowIndex(block), kind, stkDepth);
17951 }
17952
17953 // Sequences the tree.
17954 // prevTree is what gtPrev of the first node in execution order gets set to.
17955 // Returns the first node (execution order) in the sequenced tree.
17956 GenTree* Compiler::fgSetTreeSeq(GenTree* tree, GenTree* prevTree, bool isLIR)
17957 {
17958     GenTree list;
17959
17960     if (prevTree == nullptr)
17961     {
17962         prevTree = &list;
17963     }
17964     fgTreeSeqLst = prevTree;
17965     fgTreeSeqNum = 0;
17966     fgTreeSeqBeg = nullptr;
17967     fgSetTreeSeqHelper(tree, isLIR);
17968
17969     GenTree* result = prevTree->gtNext;
17970     if (prevTree == &list)
17971     {
17972         list.gtNext->gtPrev = nullptr;
17973     }
17974
17975     return result;
17976 }
17977
17978 /*****************************************************************************
17979  *
17980  *  Assigns sequence numbers to the given tree and its sub-operands, and
17981  *  threads all the nodes together via the 'gtNext' and 'gtPrev' fields.
17982  *  Uses 'global' - fgTreeSeqLst
17983  */
17984
17985 void Compiler::fgSetTreeSeqHelper(GenTreePtr tree, bool isLIR)
17986 {
17987     genTreeOps oper;
17988     unsigned   kind;
17989
17990     noway_assert(tree);
17991     assert(!IsUninitialized(tree));
17992     noway_assert(tree->gtOper != GT_STMT);
17993
17994     /* Figure out what kind of a node we have */
17995
17996     oper = tree->OperGet();
17997     kind = tree->OperKind();
17998
17999     /* Is this a leaf/constant node? */
18000
18001     if (kind & (GTK_CONST | GTK_LEAF))
18002     {
18003         fgSetTreeSeqFinish(tree, isLIR);
18004         return;
18005     }
18006
18007     // Special handling for dynamic block ops.
18008     if (tree->OperIsDynBlkOp())
18009     {
18010         GenTreeDynBlk* dynBlk;
18011         GenTree*       src;
18012         GenTree*       asg = tree;
18013         if (tree->OperGet() == GT_ASG)
18014         {
18015             dynBlk = tree->gtGetOp1()->AsDynBlk();
18016             src    = tree->gtGetOp2();
18017         }
18018         else
18019         {
18020             dynBlk = tree->AsDynBlk();
18021             src    = dynBlk->Data();
18022             asg    = nullptr;
18023         }
18024         GenTree* sizeNode = dynBlk->gtDynamicSize;
18025         GenTree* dstAddr  = dynBlk->Addr();
18026         if (dynBlk->gtEvalSizeFirst)
18027         {
18028             fgSetTreeSeqHelper(sizeNode, isLIR);
18029         }
18030         if (tree->gtFlags & GTF_REVERSE_OPS)
18031         {
18032             fgSetTreeSeqHelper(src, isLIR);
18033             fgSetTreeSeqHelper(dstAddr, isLIR);
18034         }
18035         else
18036         {
18037             fgSetTreeSeqHelper(dstAddr, isLIR);
18038             fgSetTreeSeqHelper(src, isLIR);
18039         }
18040         if (!dynBlk->gtEvalSizeFirst)
18041         {
18042             fgSetTreeSeqHelper(sizeNode, isLIR);
18043         }
18044         fgSetTreeSeqFinish(dynBlk, isLIR);
18045         if (asg != nullptr)
18046         {
18047             fgSetTreeSeqFinish(asg, isLIR);
18048         }
18049         return;
18050     }
18051
18052     /* Is it a 'simple' unary/binary operator? */
18053
18054     if (kind & GTK_SMPOP)
18055     {
18056         GenTreePtr op1 = tree->gtOp.gtOp1;
18057         GenTreePtr op2 = tree->gtGetOp2IfPresent();
18058
18059         // Special handling for GT_LIST
18060         if (tree->OperGet() == GT_LIST)
18061         {
18062             // First, handle the list items, which will be linked in forward order.
18063             // As we go, we will link the GT_LIST nodes in reverse order - we will number
18064             // them and update fgTreeSeqList in a subsequent traversal.
18065             GenTreePtr nextList = tree;
18066             GenTreePtr list     = nullptr;
18067             while (nextList != nullptr && nextList->OperGet() == GT_LIST)
18068             {
18069                 list                = nextList;
18070                 GenTreePtr listItem = list->gtOp.gtOp1;
18071                 fgSetTreeSeqHelper(listItem, isLIR);
18072                 nextList = list->gtOp.gtOp2;
18073                 if (nextList != nullptr)
18074                 {
18075                     nextList->gtNext = list;
18076                 }
18077                 list->gtPrev = nextList;
18078             }
18079             // Next, handle the GT_LIST nodes.
18080             // Note that fgSetTreeSeqFinish() sets the gtNext to null, so we need to capture the nextList
18081             // before we call that method.
18082             nextList = list;
18083             do
18084             {
18085                 assert(list != nullptr);
18086                 list     = nextList;
18087                 nextList = list->gtNext;
18088                 fgSetTreeSeqFinish(list, isLIR);
18089             } while (list != tree);
18090             return;
18091         }
18092
18093         /* Special handling for AddrMode */
18094         if (tree->OperIsAddrMode())
18095         {
18096             bool reverse = ((tree->gtFlags & GTF_REVERSE_OPS) != 0);
18097             if (reverse)
18098             {
18099                 assert(op1 != nullptr && op2 != nullptr);
18100                 fgSetTreeSeqHelper(op2, isLIR);
18101             }
18102             if (op1 != nullptr)
18103             {
18104                 fgSetTreeSeqHelper(op1, isLIR);
18105             }
18106             if (!reverse && op2 != nullptr)
18107             {
18108                 fgSetTreeSeqHelper(op2, isLIR);
18109             }
18110
18111             fgSetTreeSeqFinish(tree, isLIR);
18112             return;
18113         }
18114
18115         /* Check for a nilary operator */
18116
18117         if (op1 == nullptr)
18118         {
18119             noway_assert(op2 == nullptr);
18120             fgSetTreeSeqFinish(tree, isLIR);
18121             return;
18122         }
18123
18124         /* Is this a unary operator?
18125          * Although UNARY GT_IND has a special structure */
18126
18127         if (oper == GT_IND)
18128         {
18129             /* Visit the indirection first - op2 may point to the
18130              * jump Label for array-index-out-of-range */
18131
18132             fgSetTreeSeqHelper(op1, isLIR);
18133             fgSetTreeSeqFinish(tree, isLIR);
18134             return;
18135         }
18136
18137         /* Now this is REALLY a unary operator */
18138
18139         if (!op2)
18140         {
18141             /* Visit the (only) operand and we're done */
18142
18143             fgSetTreeSeqHelper(op1, isLIR);
18144             fgSetTreeSeqFinish(tree, isLIR);
18145             return;
18146         }
18147
18148         /*
18149            For "real" ?: operators, we make sure the order is
18150            as follows:
18151
18152                condition
18153                1st operand
18154                GT_COLON
18155                2nd operand
18156                GT_QMARK
18157         */
18158
18159         if (oper == GT_QMARK)
18160         {
18161             noway_assert((tree->gtFlags & GTF_REVERSE_OPS) == 0);
18162
18163             fgSetTreeSeqHelper(op1, isLIR);
18164             // Here, for the colon, the sequence does not actually represent "order of evaluation":
18165             // one or the other of the branches is executed, not both.  Still, to make debugging checks
18166             // work, we want the sequence to match the order in which we'll generate code, which means
18167             // "else" clause then "then" clause.
18168             fgSetTreeSeqHelper(op2->AsColon()->ElseNode(), isLIR);
18169             fgSetTreeSeqHelper(op2, isLIR);
18170             fgSetTreeSeqHelper(op2->AsColon()->ThenNode(), isLIR);
18171
18172             fgSetTreeSeqFinish(tree, isLIR);
18173             return;
18174         }
18175
18176         if (oper == GT_COLON)
18177         {
18178             fgSetTreeSeqFinish(tree, isLIR);
18179             return;
18180         }
18181
18182         /* This is a binary operator */
18183
18184         if (tree->gtFlags & GTF_REVERSE_OPS)
18185         {
18186             fgSetTreeSeqHelper(op2, isLIR);
18187             fgSetTreeSeqHelper(op1, isLIR);
18188         }
18189         else
18190         {
18191             fgSetTreeSeqHelper(op1, isLIR);
18192             fgSetTreeSeqHelper(op2, isLIR);
18193         }
18194
18195         fgSetTreeSeqFinish(tree, isLIR);
18196         return;
18197     }
18198
18199     /* See what kind of a special operator we have here */
18200
18201     switch (oper)
18202     {
18203         case GT_FIELD:
18204             noway_assert(tree->gtField.gtFldObj == nullptr);
18205             break;
18206
18207         case GT_CALL:
18208
18209             /* We'll evaluate the 'this' argument value first */
18210             if (tree->gtCall.gtCallObjp)
18211             {
18212                 fgSetTreeSeqHelper(tree->gtCall.gtCallObjp, isLIR);
18213             }
18214
18215             /* We'll evaluate the arguments next, left to right
18216              * NOTE: setListOrder needs cleanup - eliminate the #ifdef afterwards */
18217
18218             if (tree->gtCall.gtCallArgs)
18219             {
18220                 fgSetTreeSeqHelper(tree->gtCall.gtCallArgs, isLIR);
18221             }
18222
18223             /* Evaluate the temp register arguments list
18224              * This is a "hidden" list and its only purpose is to
18225              * extend the life of temps until we make the call */
18226
18227             if (tree->gtCall.gtCallLateArgs)
18228             {
18229                 fgSetTreeSeqHelper(tree->gtCall.gtCallLateArgs, isLIR);
18230             }
18231
18232             if ((tree->gtCall.gtCallType == CT_INDIRECT) && (tree->gtCall.gtCallCookie != nullptr))
18233             {
18234                 fgSetTreeSeqHelper(tree->gtCall.gtCallCookie, isLIR);
18235             }
18236
18237             if (tree->gtCall.gtCallType == CT_INDIRECT)
18238             {
18239                 fgSetTreeSeqHelper(tree->gtCall.gtCallAddr, isLIR);
18240             }
18241
18242             if (tree->gtCall.gtControlExpr)
18243             {
18244                 fgSetTreeSeqHelper(tree->gtCall.gtControlExpr, isLIR);
18245             }
18246
18247             break;
18248
18249         case GT_ARR_ELEM:
18250
18251             fgSetTreeSeqHelper(tree->gtArrElem.gtArrObj, isLIR);
18252
18253             unsigned dim;
18254             for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
18255             {
18256                 fgSetTreeSeqHelper(tree->gtArrElem.gtArrInds[dim], isLIR);
18257             }
18258
18259             break;
18260
18261         case GT_ARR_OFFSET:
18262             fgSetTreeSeqHelper(tree->gtArrOffs.gtOffset, isLIR);
18263             fgSetTreeSeqHelper(tree->gtArrOffs.gtIndex, isLIR);
18264             fgSetTreeSeqHelper(tree->gtArrOffs.gtArrObj, isLIR);
18265             break;
18266
18267         case GT_CMPXCHG:
18268             // Evaluate the trees left to right
18269             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpLocation, isLIR);
18270             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpValue, isLIR);
18271             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpComparand, isLIR);
18272             break;
18273
18274         case GT_ARR_BOUNDS_CHECK:
18275 #ifdef FEATURE_SIMD
18276         case GT_SIMD_CHK:
18277 #endif // FEATURE_SIMD
18278             // Evaluate the trees left to right
18279             fgSetTreeSeqHelper(tree->gtBoundsChk.gtIndex, isLIR);
18280             fgSetTreeSeqHelper(tree->gtBoundsChk.gtArrLen, isLIR);
18281             break;
18282
18283         case GT_STORE_DYN_BLK:
18284         case GT_DYN_BLK:
18285             noway_assert(!"DYN_BLK nodes should be sequenced as a special case");
18286             break;
18287
18288         default:
18289 #ifdef DEBUG
18290             gtDispTree(tree);
18291             noway_assert(!"unexpected operator");
18292 #endif // DEBUG
18293             break;
18294     }
18295
18296     fgSetTreeSeqFinish(tree, isLIR);
18297 }
18298
18299 void Compiler::fgSetTreeSeqFinish(GenTreePtr tree, bool isLIR)
18300 {
18301     // If we are sequencing a node that does not appear in LIR,
18302     // do not add it to the list.
18303     if (isLIR)
18304     {
18305         if ((tree->OperGet() == GT_LIST) || (tree->OperGet() == GT_ARGPLACE) ||
18306             (tree->OperGet() == GT_FIELD_LIST && !tree->AsFieldList()->IsFieldListHead()))
18307         {
18308             return;
18309         }
18310     }
18311
18312     /* Append to the node list */
18313     ++fgTreeSeqNum;
18314
18315 #ifdef DEBUG
18316     tree->gtSeqNum = fgTreeSeqNum;
18317
18318     if (verbose & 0)
18319     {
18320         printf("SetTreeOrder: ");
18321         printTreeID(fgTreeSeqLst);
18322         printf(" followed by ");
18323         printTreeID(tree);
18324         printf("\n");
18325     }
18326 #endif // DEBUG
18327
18328     fgTreeSeqLst->gtNext = tree;
18329     tree->gtNext         = nullptr;
18330     tree->gtPrev         = fgTreeSeqLst;
18331     fgTreeSeqLst         = tree;
18332
18333     /* Remember the very first node */
18334
18335     if (!fgTreeSeqBeg)
18336     {
18337         fgTreeSeqBeg = tree;
18338         assert(tree->gtSeqNum == 1);
18339     }
18340 }
18341
18342 /*****************************************************************************
18343  *
18344  *  Figure out the order in which operators should be evaluated, along with
18345  *  other information (such as the register sets trashed by each subtree).
18346  *  Also finds blocks that need GC polls and inserts them as needed.
18347  */
18348
18349 void Compiler::fgSetBlockOrder()
18350 {
18351 #ifdef DEBUG
18352     if (verbose)
18353     {
18354         printf("*************** In fgSetBlockOrder()\n");
18355     }
18356 #endif // DEBUG
18357
18358 #ifdef DEBUG
18359     BasicBlock::s_nMaxTrees = 0;
18360 #endif
18361
18362     /* Walk the basic blocks to assign sequence numbers */
18363
18364     /* If we don't compute the doms, then we never mark blocks as loops. */
18365     if (fgDomsComputed)
18366     {
18367         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18368         {
18369             /* If this block is a loop header, mark it appropriately */
18370
18371             if (block->isLoopHead())
18372             {
18373                 fgMarkLoopHead(block);
18374             }
18375         }
18376     }
18377     // only enable fully interruptible code for if we're hijacking.
18378     else if (GCPOLL_NONE == opts.compGCPollType)
18379     {
18380         /* If we don't have the dominators, use an abbreviated test for fully interruptible.  If there are
18381          * any back edges, check the source and destination blocks to see if they're GC Safe.  If not, then
18382          * go fully interruptible. */
18383
18384         /* XXX Mon 1/21/2008
18385          * Wouldn't it be nice to have a block iterator that can do this loop?
18386          */
18387         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18388         {
18389 // true if the edge is forward, or if it is a back edge and either the source and dest are GC safe.
18390 #define EDGE_IS_GC_SAFE(src, dst)                                                                                      \
18391     (((src)->bbNum < (dst)->bbNum) || (((src)->bbFlags | (dst)->bbFlags) & BBF_GC_SAFE_POINT))
18392
18393             bool partiallyInterruptible = true;
18394             switch (block->bbJumpKind)
18395             {
18396                 case BBJ_COND:
18397                 case BBJ_ALWAYS:
18398                     partiallyInterruptible = EDGE_IS_GC_SAFE(block, block->bbJumpDest);
18399                     break;
18400
18401                 case BBJ_SWITCH:
18402
18403                     unsigned jumpCnt;
18404                     jumpCnt = block->bbJumpSwt->bbsCount;
18405                     BasicBlock** jumpPtr;
18406                     jumpPtr = block->bbJumpSwt->bbsDstTab;
18407
18408                     do
18409                     {
18410                         partiallyInterruptible &= EDGE_IS_GC_SAFE(block, *jumpPtr);
18411                     } while (++jumpPtr, --jumpCnt);
18412
18413                     break;
18414
18415                 default:
18416                     break;
18417             }
18418
18419             if (!partiallyInterruptible)
18420             {
18421                 // DDB 204533:
18422                 // The GC encoding for fully interruptible methods does not
18423                 // support more than 1023 pushed arguments, so we can't set
18424                 // genInterruptible here when we have 1024 or more pushed args
18425                 //
18426                 if (compCanEncodePtrArgCntMax())
18427                 {
18428                     genInterruptible = true;
18429                 }
18430                 break;
18431             }
18432 #undef EDGE_IS_GC_SAFE
18433         }
18434     }
18435
18436     if (!fgGCPollsCreated)
18437     {
18438         fgCreateGCPolls();
18439     }
18440
18441     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18442     {
18443
18444 #if FEATURE_FASTTAILCALL
18445 #ifndef JIT32_GCENCODER
18446         if (block->endsWithTailCallOrJmp(this, true) && !(block->bbFlags & BBF_GC_SAFE_POINT) &&
18447             optReachWithoutCall(fgFirstBB, block))
18448         {
18449             // We have a tail call that is reachable without making any other
18450             // 'normal' call that would have counted as a GC Poll.  If we were
18451             // using polls, all return blocks meeting this criteria would have
18452             // already added polls and then marked as being GC safe
18453             // (BBF_GC_SAFE_POINT). Thus we can only reach here when *NOT*
18454             // using GC polls, but instead relying on the JIT to generate
18455             // fully-interruptible code.
18456             noway_assert(GCPOLL_NONE == opts.compGCPollType);
18457
18458             // This tail call might combine with other tail calls to form a
18459             // loop.  Thus we need to either add a poll, or make the method
18460             // fully interruptible.  I chose the later because that's what
18461             // JIT64 does.
18462             genInterruptible = true;
18463         }
18464 #endif // !JIT32_GCENCODER
18465 #endif // FEATURE_FASTTAILCALL
18466
18467         fgSetBlockOrder(block);
18468     }
18469
18470     /* Remember that now the tree list is threaded */
18471
18472     fgStmtListThreaded = true;
18473
18474 #ifdef DEBUG
18475     if (verbose)
18476     {
18477         printf("The biggest BB has %4u tree nodes\n", BasicBlock::s_nMaxTrees);
18478     }
18479     fgDebugCheckLinks();
18480 #endif // DEBUG
18481 }
18482
18483 /*****************************************************************************/
18484
18485 void Compiler::fgSetStmtSeq(GenTreePtr tree)
18486 {
18487     GenTree list; // helper node that we use to start the StmtList
18488                   // It's located in front of the first node in the list
18489
18490     noway_assert(tree->gtOper == GT_STMT);
18491
18492     /* Assign numbers and next/prev links for this tree */
18493
18494     fgTreeSeqNum = 0;
18495     fgTreeSeqLst = &list;
18496     fgTreeSeqBeg = nullptr;
18497
18498     fgSetTreeSeqHelper(tree->gtStmt.gtStmtExpr, false);
18499
18500     /* Record the address of the first node */
18501
18502     tree->gtStmt.gtStmtList = fgTreeSeqBeg;
18503
18504 #ifdef DEBUG
18505
18506     if (list.gtNext->gtPrev != &list)
18507     {
18508         printf("&list ");
18509         printTreeID(&list);
18510         printf(" != list.next->prev ");
18511         printTreeID(list.gtNext->gtPrev);
18512         printf("\n");
18513         goto BAD_LIST;
18514     }
18515
18516     GenTreePtr temp;
18517     GenTreePtr last;
18518     for (temp = list.gtNext, last = &list; temp; last = temp, temp = temp->gtNext)
18519     {
18520         if (temp->gtPrev != last)
18521         {
18522             printTreeID(temp);
18523             printf("->gtPrev = ");
18524             printTreeID(temp->gtPrev);
18525             printf(", but last = ");
18526             printTreeID(last);
18527             printf("\n");
18528
18529         BAD_LIST:;
18530
18531             printf("\n");
18532             gtDispTree(tree->gtStmt.gtStmtExpr);
18533             printf("\n");
18534
18535             for (GenTreePtr bad = &list; bad; bad = bad->gtNext)
18536             {
18537                 printf("  entry at ");
18538                 printTreeID(bad);
18539                 printf(" (prev=");
18540                 printTreeID(bad->gtPrev);
18541                 printf(",next=)");
18542                 printTreeID(bad->gtNext);
18543                 printf("\n");
18544             }
18545
18546             printf("\n");
18547             noway_assert(!"Badly linked tree");
18548             break;
18549         }
18550     }
18551 #endif // DEBUG
18552
18553     /* Fix the first node's 'prev' link */
18554
18555     noway_assert(list.gtNext->gtPrev == &list);
18556     list.gtNext->gtPrev = nullptr;
18557
18558 #ifdef DEBUG
18559     /* Keep track of the highest # of tree nodes */
18560
18561     if (BasicBlock::s_nMaxTrees < fgTreeSeqNum)
18562     {
18563         BasicBlock::s_nMaxTrees = fgTreeSeqNum;
18564     }
18565 #endif // DEBUG
18566 }
18567
18568 /*****************************************************************************/
18569
18570 void Compiler::fgSetBlockOrder(BasicBlock* block)
18571 {
18572     GenTreePtr tree;
18573
18574     tree = block->bbTreeList;
18575     if (!tree)
18576     {
18577         return;
18578     }
18579
18580     for (;;)
18581     {
18582         fgSetStmtSeq(tree);
18583
18584         /* Are there any more trees in this basic block? */
18585
18586         if (tree->gtNext == nullptr)
18587         {
18588             /* last statement in the tree list */
18589             noway_assert(block->lastStmt() == tree);
18590             break;
18591         }
18592
18593 #ifdef DEBUG
18594         if (block->bbTreeList == tree)
18595         {
18596             /* first statement in the list */
18597             noway_assert(tree->gtPrev->gtNext == nullptr);
18598         }
18599         else
18600         {
18601             noway_assert(tree->gtPrev->gtNext == tree);
18602         }
18603
18604         noway_assert(tree->gtNext->gtPrev == tree);
18605 #endif // DEBUG
18606
18607         tree = tree->gtNext;
18608     }
18609 }
18610
18611 #ifdef LEGACY_BACKEND
18612 //------------------------------------------------------------------------
18613 // fgOrderBlockOps: Get the execution order for a block assignment
18614 //
18615 // Arguments:
18616 //    tree    - The block assignment
18617 //    reg0    - The register for the destination
18618 //    reg1    - The register for the source
18619 //    reg2    - The register for the size
18620 //    opsPtr  - An array of 3 GenTreePtr's, an out argument for the operands, in order
18621 //    regsPtr - An array of three regMaskTP - an out argument for the registers, in order
18622 //
18623 // Return Value:
18624 //    The return values go into the arrays that are passed in, and provide the
18625 //    operands and associated registers, in execution order.
18626 //
18627 // Notes:
18628 //    This method is somewhat convoluted in order to preserve old behavior from when
18629 //    block assignments had their dst and src in a GT_LIST as op1, and their size as op2.
18630 //    The old tree was like this:
18631 //                                tree->gtOp
18632 //                               /        \
18633 //                           GT_LIST  [size/clsHnd]
18634 //                           /      \
18635 //                       [dest]     [val/src]
18636 //
18637 //    The new tree looks like this:
18638 //                                GT_ASG
18639 //                               /       \
18640 //                           blk/obj   [val/src]
18641 //                           /      \
18642 //                    [destAddr]     [*size/clsHnd] *only for GT_DYN_BLK
18643 //
18644 //    For the (usual) case of GT_BLK or GT_OBJ, the size is always "evaluated" (i.e.
18645 //    instantiated into a register) last. In those cases, the GTF_REVERSE_OPS flag
18646 //    on the assignment works as usual.
18647 //    In order to preserve previous possible orderings, the order for evaluating
18648 //    the size of a GT_DYN_BLK node is controlled by its gtEvalSizeFirst flag. If
18649 //    that is set, the size is evaluated first, and then the src and dst are evaluated
18650 //    according to the GTF_REVERSE_OPS flag on the assignment.
18651
18652 void Compiler::fgOrderBlockOps(GenTreePtr  tree,
18653                                regMaskTP   reg0,
18654                                regMaskTP   reg1,
18655                                regMaskTP   reg2,
18656                                GenTreePtr* opsPtr,  // OUT
18657                                regMaskTP*  regsPtr) // OUT
18658 {
18659     assert(tree->OperIsBlkOp());
18660
18661     GenTreeBlk* destBlk     = tree->gtOp.gtOp1->AsBlk();
18662     GenTreePtr  destAddr    = destBlk->Addr();
18663     GenTreePtr  srcPtrOrVal = tree->gtOp.gtOp2;
18664     if (tree->OperIsCopyBlkOp())
18665     {
18666         assert(srcPtrOrVal->OperIsIndir());
18667         srcPtrOrVal = srcPtrOrVal->AsIndir()->Addr();
18668     }
18669     GenTreePtr sizeNode = (destBlk->gtOper == GT_DYN_BLK) ? destBlk->AsDynBlk()->gtDynamicSize : nullptr;
18670     noway_assert((sizeNode != nullptr) || ((destBlk->gtFlags & GTF_REVERSE_OPS) == 0));
18671     assert(destAddr != nullptr);
18672     assert(srcPtrOrVal != nullptr);
18673
18674     GenTreePtr ops[3] = {
18675         destAddr,    // Dest address
18676         srcPtrOrVal, // Val / Src address
18677         sizeNode     // Size of block
18678     };
18679
18680     regMaskTP regs[3] = {reg0, reg1, reg2};
18681
18682     static int blockOpsOrder[4][3] =
18683         //                destBlk->gtEvalSizeFirst |       tree->gtFlags
18684         {
18685             //            -------------------------+----------------------------
18686             {0, 1, 2}, //          false           |              -
18687             {2, 0, 1}, //          true            |              -
18688             {1, 0, 2}, //          false           |       GTF_REVERSE_OPS
18689             {2, 1, 0}  //          true            |       GTF_REVERSE_OPS
18690         };
18691
18692     int orderNum = ((destBlk->gtFlags & GTF_REVERSE_OPS) != 0) * 1 + ((tree->gtFlags & GTF_REVERSE_OPS) != 0) * 2;
18693
18694     assert(orderNum < 4);
18695
18696     int* order = blockOpsOrder[orderNum];
18697
18698     PREFIX_ASSUME(order != NULL);
18699
18700     // Fill in the OUT arrays according to the order we have selected
18701
18702     opsPtr[0] = ops[order[0]];
18703     opsPtr[1] = ops[order[1]];
18704     opsPtr[2] = ops[order[2]];
18705
18706     regsPtr[0] = regs[order[0]];
18707     regsPtr[1] = regs[order[1]];
18708     regsPtr[2] = regs[order[2]];
18709 }
18710 #endif // LEGACY_BACKEND
18711
18712 //------------------------------------------------------------------------
18713 // fgGetFirstNode: Get the first node in the tree, in execution order
18714 //
18715 // Arguments:
18716 //    tree - The top node of the tree of interest
18717 //
18718 // Return Value:
18719 //    The first node in execution order, that belongs to tree.
18720 //
18721 // Assumptions:
18722 //     'tree' must either be a leaf, or all of its constituent nodes must be contiguous
18723 //     in execution order.
18724 //     TODO-Cleanup: Add a debug-only method that verifies this.
18725
18726 /* static */
18727 GenTreePtr Compiler::fgGetFirstNode(GenTreePtr tree)
18728 {
18729     GenTreePtr child = tree;
18730     while (child->NumChildren() > 0)
18731     {
18732         if (child->OperIsBinary() && child->IsReverseOp())
18733         {
18734             child = child->GetChild(1);
18735         }
18736         else
18737         {
18738             child = child->GetChild(0);
18739         }
18740     }
18741     return child;
18742 }
18743
18744 // Examine the bbTreeList and return the estimated code size for this block
18745 unsigned Compiler::fgGetCodeEstimate(BasicBlock* block)
18746 {
18747     unsigned costSz = 0; // estimate of blocks code size cost
18748
18749     switch (block->bbJumpKind)
18750     {
18751         case BBJ_NONE:
18752             costSz = 0;
18753             break;
18754         case BBJ_ALWAYS:
18755         case BBJ_EHCATCHRET:
18756         case BBJ_LEAVE:
18757         case BBJ_COND:
18758             costSz = 2;
18759             break;
18760         case BBJ_CALLFINALLY:
18761             costSz = 5;
18762             break;
18763         case BBJ_SWITCH:
18764             costSz = 10;
18765             break;
18766         case BBJ_THROW:
18767             costSz = 1; // We place a int3 after the code for a throw block
18768             break;
18769         case BBJ_EHFINALLYRET:
18770         case BBJ_EHFILTERRET:
18771             costSz = 1;
18772             break;
18773         case BBJ_RETURN: // return from method
18774             costSz = 3;
18775             break;
18776         default:
18777             noway_assert(!"Bad bbJumpKind");
18778             break;
18779     }
18780
18781     GenTreePtr tree = block->FirstNonPhiDef();
18782     if (tree)
18783     {
18784         do
18785         {
18786             noway_assert(tree->gtOper == GT_STMT);
18787
18788             if (tree->gtCostSz < MAX_COST)
18789             {
18790                 costSz += tree->gtCostSz;
18791             }
18792             else
18793             {
18794                 // We could walk the tree to find out the real gtCostSz,
18795                 // but just using MAX_COST for this trees code size works OK
18796                 costSz += tree->gtCostSz;
18797             }
18798
18799             tree = tree->gtNext;
18800         } while (tree);
18801     }
18802
18803     return costSz;
18804 }
18805
18806 #if DUMP_FLOWGRAPHS
18807
18808 struct escapeMapping_t
18809 {
18810     char        ch;
18811     const char* sub;
18812 };
18813
18814 // clang-format off
18815 static escapeMapping_t s_EscapeFileMapping[] =
18816 {
18817     {':', "="},
18818     {'<', "["},
18819     {'>', "]"},
18820     {';', "~semi~"},
18821     {'|', "~bar~"},
18822     {'&', "~amp~"},
18823     {'"', "~quot~"},
18824     {'*', "~star~"},
18825     {0, nullptr}
18826 };
18827
18828 static escapeMapping_t s_EscapeMapping[] =
18829 {
18830     {'<', "&lt;"},
18831     {'>', "&gt;"},
18832     {'&', "&amp;"},
18833     {'"', "&quot;"},
18834     {0, nullptr}
18835 };
18836 // clang-format on
18837
18838 const char* Compiler::fgProcessEscapes(const char* nameIn, escapeMapping_t* map)
18839 {
18840     const char* nameOut = nameIn;
18841     unsigned    lengthOut;
18842     unsigned    index;
18843     bool        match;
18844     bool        subsitutionRequired;
18845     const char* pChar;
18846
18847     lengthOut           = 1;
18848     subsitutionRequired = false;
18849     pChar               = nameIn;
18850     while (*pChar != '\0')
18851     {
18852         match = false;
18853         index = 0;
18854         while (map[index].ch != 0)
18855         {
18856             if (*pChar == map[index].ch)
18857             {
18858                 match = true;
18859                 break;
18860             }
18861             index++;
18862         }
18863         if (match)
18864         {
18865             subsitutionRequired = true;
18866             lengthOut += (unsigned)strlen(map[index].sub);
18867         }
18868         else
18869         {
18870             lengthOut += 1;
18871         }
18872         pChar++;
18873     }
18874
18875     if (subsitutionRequired)
18876     {
18877         char* newName = (char*)compGetMemA(lengthOut, CMK_DebugOnly);
18878         char* pDest;
18879         pDest = newName;
18880         pChar = nameIn;
18881         while (*pChar != '\0')
18882         {
18883             match = false;
18884             index = 0;
18885             while (map[index].ch != 0)
18886             {
18887                 if (*pChar == map[index].ch)
18888                 {
18889                     match = true;
18890                     break;
18891                 }
18892                 index++;
18893             }
18894             if (match)
18895             {
18896                 strcpy(pDest, map[index].sub);
18897                 pDest += strlen(map[index].sub);
18898             }
18899             else
18900             {
18901                 *pDest++ = *pChar;
18902             }
18903             pChar++;
18904         }
18905         *pDest++ = '\0';
18906         nameOut  = (const char*)newName;
18907     }
18908
18909     return nameOut;
18910 }
18911
18912 static void fprintfDouble(FILE* fgxFile, double value)
18913 {
18914     assert(value >= 0.0);
18915
18916     if ((value >= 0.010) || (value == 0.0))
18917     {
18918         fprintf(fgxFile, "\"%7.3f\"", value);
18919     }
18920     else if (value >= 0.00010)
18921     {
18922         fprintf(fgxFile, "\"%7.5f\"", value);
18923     }
18924     else
18925     {
18926         fprintf(fgxFile, "\"%7E\"", value);
18927     }
18928 }
18929
18930 //------------------------------------------------------------------------
18931 // fgOpenFlowGraphFile: Open a file to dump either the xml or dot format flow graph
18932 //
18933 // Arguments:
18934 //    wbDontClose - A boolean out argument that indicates whether the caller should close the file
18935 //    phase       - A phase identifier to indicate which phase is associated with the dump
18936 //    type        - A (wide) string indicating the type of dump, "dot" or "xml"
18937 //
18938 // Return Value:
18939 //    Opens a file to which a flowgraph can be dumped, whose name is based on the current
18940 //    config vales.
18941
18942 FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR type)
18943 {
18944     FILE*       fgxFile;
18945     LPCWSTR     pattern  = nullptr;
18946     LPCWSTR     filename = nullptr;
18947     LPCWSTR     pathname = nullptr;
18948     const char* escapedString;
18949     bool        createDuplicateFgxFiles = true;
18950
18951 #ifdef DEBUG
18952     if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
18953     {
18954         pattern  = JitConfig.NgenDumpFg();
18955         filename = JitConfig.NgenDumpFgFile();
18956         pathname = JitConfig.NgenDumpFgDir();
18957     }
18958     else
18959     {
18960         pattern  = JitConfig.JitDumpFg();
18961         filename = JitConfig.JitDumpFgFile();
18962         pathname = JitConfig.JitDumpFgDir();
18963     }
18964 #endif // DEBUG
18965
18966     if (fgBBcount <= 1)
18967     {
18968         return nullptr;
18969     }
18970
18971     if (pattern == nullptr)
18972     {
18973         return nullptr;
18974     }
18975
18976     if (wcslen(pattern) == 0)
18977     {
18978         return nullptr;
18979     }
18980
18981     LPCWSTR phasePattern = JitConfig.JitDumpFgPhase();
18982     LPCWSTR phaseName    = PhaseShortNames[phase];
18983     if (phasePattern == nullptr)
18984     {
18985         if (phase != PHASE_DETERMINE_FIRST_COLD_BLOCK)
18986         {
18987             return nullptr;
18988         }
18989     }
18990     else if (*phasePattern != W('*'))
18991     {
18992         if (wcsstr(phasePattern, phaseName) == nullptr)
18993         {
18994             return nullptr;
18995         }
18996     }
18997
18998     if (*pattern != W('*'))
18999     {
19000         bool hasColon = (wcschr(pattern, W(':')) != nullptr);
19001
19002         if (hasColon)
19003         {
19004             const char* className = info.compClassName;
19005             if (*pattern == W('*'))
19006             {
19007                 pattern++;
19008             }
19009             else
19010             {
19011                 while ((*pattern != W(':')) && (*pattern != W('*')))
19012                 {
19013                     if (*pattern != *className)
19014                     {
19015                         return nullptr;
19016                     }
19017
19018                     pattern++;
19019                     className++;
19020                 }
19021                 if (*pattern == W('*'))
19022                 {
19023                     pattern++;
19024                 }
19025                 else
19026                 {
19027                     if (*className != 0)
19028                     {
19029                         return nullptr;
19030                     }
19031                 }
19032             }
19033             if (*pattern != W(':'))
19034             {
19035                 return nullptr;
19036             }
19037
19038             pattern++;
19039         }
19040
19041         const char* methodName = info.compMethodName;
19042         if (*pattern == W('*'))
19043         {
19044             pattern++;
19045         }
19046         else
19047         {
19048             while ((*pattern != 0) && (*pattern != W('*')))
19049             {
19050                 if (*pattern != *methodName)
19051                 {
19052                     return nullptr;
19053                 }
19054
19055                 pattern++;
19056                 methodName++;
19057             }
19058             if (*pattern == W('*'))
19059             {
19060                 pattern++;
19061             }
19062             else
19063             {
19064                 if (*methodName != 0)
19065                 {
19066                     return nullptr;
19067                 }
19068             }
19069         }
19070         if (*pattern != 0)
19071         {
19072             return nullptr;
19073         }
19074     }
19075
19076     if (filename == nullptr)
19077     {
19078         filename = W("default");
19079     }
19080
19081     if (wcscmp(filename, W("profiled")) == 0)
19082     {
19083         if (fgFirstBB->hasProfileWeight())
19084         {
19085             createDuplicateFgxFiles = true;
19086             goto ONE_FILE_PER_METHOD;
19087         }
19088         else
19089         {
19090             return nullptr;
19091         }
19092     }
19093     if (wcscmp(filename, W("hot")) == 0)
19094     {
19095         if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT)
19096
19097         {
19098             createDuplicateFgxFiles = true;
19099             goto ONE_FILE_PER_METHOD;
19100         }
19101         else
19102         {
19103             return nullptr;
19104         }
19105     }
19106     else if (wcscmp(filename, W("cold")) == 0)
19107     {
19108         if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD)
19109         {
19110             createDuplicateFgxFiles = true;
19111             goto ONE_FILE_PER_METHOD;
19112         }
19113         else
19114         {
19115             return nullptr;
19116         }
19117     }
19118     else if (wcscmp(filename, W("jit")) == 0)
19119     {
19120         if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT)
19121         {
19122             createDuplicateFgxFiles = true;
19123             goto ONE_FILE_PER_METHOD;
19124         }
19125         else
19126         {
19127             return nullptr;
19128         }
19129     }
19130     else if (wcscmp(filename, W("all")) == 0)
19131     {
19132         createDuplicateFgxFiles = true;
19133
19134     ONE_FILE_PER_METHOD:;
19135
19136         escapedString     = fgProcessEscapes(info.compFullName, s_EscapeFileMapping);
19137         size_t wCharCount = strlen(escapedString) + wcslen(phaseName) + 1 + strlen("~999") + wcslen(type) + 1;
19138         if (pathname != nullptr)
19139         {
19140             wCharCount += wcslen(pathname) + 1;
19141         }
19142         filename = (LPCWSTR)alloca(wCharCount * sizeof(WCHAR));
19143         if (pathname != nullptr)
19144         {
19145             swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S-%s.%s"), pathname, escapedString, phaseName, type);
19146         }
19147         else
19148         {
19149             swprintf_s((LPWSTR)filename, wCharCount, W("%S.%s"), escapedString, type);
19150         }
19151         fgxFile = _wfopen(filename, W("r")); // Check if this file already exists
19152         if (fgxFile != nullptr)
19153         {
19154             // For Generic methods we will have both hot and cold versions
19155             if (createDuplicateFgxFiles == false)
19156             {
19157                 fclose(fgxFile);
19158                 return nullptr;
19159             }
19160             // Yes, this filename already exists, so create a different one by appending ~2, ~3, etc...
19161             for (int i = 2; i < 1000; i++)
19162             {
19163                 fclose(fgxFile);
19164                 if (pathname != nullptr)
19165                 {
19166                     swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S~%d.%s"), pathname, escapedString, i, type);
19167                 }
19168                 else
19169                 {
19170                     swprintf_s((LPWSTR)filename, wCharCount, W("%S~%d.%s"), escapedString, i, type);
19171                 }
19172                 fgxFile = _wfopen(filename, W("r")); // Check if this file exists
19173                 if (fgxFile == nullptr)
19174                 {
19175                     break;
19176                 }
19177             }
19178             // If we have already created 1000 files with this name then just fail
19179             if (fgxFile != nullptr)
19180             {
19181                 fclose(fgxFile);
19182                 return nullptr;
19183             }
19184         }
19185         fgxFile      = _wfopen(filename, W("a+"));
19186         *wbDontClose = false;
19187     }
19188     else if (wcscmp(filename, W("stdout")) == 0)
19189     {
19190         fgxFile      = jitstdout;
19191         *wbDontClose = true;
19192     }
19193     else if (wcscmp(filename, W("stderr")) == 0)
19194     {
19195         fgxFile      = stderr;
19196         *wbDontClose = true;
19197     }
19198     else
19199     {
19200         LPCWSTR origFilename = filename;
19201         size_t  wCharCount   = wcslen(origFilename) + wcslen(type) + 2;
19202         if (pathname != nullptr)
19203         {
19204             wCharCount += wcslen(pathname) + 1;
19205         }
19206         filename = (LPCWSTR)alloca(wCharCount * sizeof(WCHAR));
19207         if (pathname != nullptr)
19208         {
19209             swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%s.%s"), pathname, origFilename, type);
19210         }
19211         else
19212         {
19213             swprintf_s((LPWSTR)filename, wCharCount, W("%s.%s"), origFilename, type);
19214         }
19215         fgxFile      = _wfopen(filename, W("a+"));
19216         *wbDontClose = false;
19217     }
19218
19219     return fgxFile;
19220 }
19221
19222 //------------------------------------------------------------------------
19223 // fgDumpFlowGraph: Dump the xml or dot format flow graph, if enabled for this phase.
19224 //
19225 // Arguments:
19226 //    phase       - A phase identifier to indicate which phase is associated with the dump,
19227 //                  i.e. which phase has just completed.
19228 //
19229 // Return Value:
19230 //    True iff a flowgraph has been dumped.
19231 //
19232 // Notes:
19233 //    The xml dumps are the historical mechanism for dumping the flowgraph.
19234 //    The dot format can be viewed by:
19235 //    - Graphviz (http://www.graphviz.org/)
19236 //      - The command "C:\Program Files (x86)\Graphviz2.38\bin\dot.exe" -Tsvg -oFoo.svg -Kdot Foo.dot
19237 //        will produce a Foo.svg file that can be opened with any svg-capable browser (e.g. IE).
19238 //    - http://rise4fun.com/Agl/
19239 //      - Cut and paste the graph from your .dot file, replacing the digraph on the page, and then click the play
19240 //        button.
19241 //      - It will show a rotating '/' and then render the graph in the browser.
19242 //    MSAGL has also been open-sourced to https://github.com/Microsoft/automatic-graph-layout.git.
19243 //
19244 //    Here are the config values that control it:
19245 //      COMPlus_JitDumpFg       A string (ala the COMPlus_JitDump string) indicating what methods to dump flowgraphs
19246 //                              for.
19247 //      COMPlus_JitDumpFgDir    A path to a directory into which the flowgraphs will be dumped.
19248 //      COMPlus_JitDumpFgFile   The filename to use. The default is "default.[xml|dot]".
19249 //                              Note that the new graphs will be appended to this file if it already exists.
19250 //      COMPlus_JitDumpFgPhase  Phase(s) after which to dump the flowgraph.
19251 //                              Set to the short name of a phase to see the flowgraph after that phase.
19252 //                              Leave unset to dump after COLD-BLK (determine first cold block) or set to * for all
19253 //                              phases.
19254 //      COMPlus_JitDumpFgDot    Set to non-zero to emit Dot instead of Xml Flowgraph dump. (Default is xml format.)
19255
19256 bool Compiler::fgDumpFlowGraph(Phases phase)
19257 {
19258     bool result        = false;
19259     bool dontClose     = false;
19260     bool createDotFile = false;
19261     if (JitConfig.JitDumpFgDot())
19262     {
19263         createDotFile = true;
19264     }
19265
19266     FILE* fgxFile = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx"));
19267
19268     if (fgxFile == nullptr)
19269     {
19270         return false;
19271     }
19272     bool        validWeights  = fgHaveValidEdgeWeights;
19273     unsigned    calledCount   = max(fgCalledCount, BB_UNITY_WEIGHT) / BB_UNITY_WEIGHT;
19274     double      weightDivisor = (double)(calledCount * BB_UNITY_WEIGHT);
19275     const char* escapedString;
19276     const char* regionString = "NONE";
19277
19278     if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT)
19279     {
19280         regionString = "HOT";
19281     }
19282     else if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD)
19283     {
19284         regionString = "COLD";
19285     }
19286     else if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT)
19287     {
19288         regionString = "JIT";
19289     }
19290
19291     if (createDotFile)
19292     {
19293         fprintf(fgxFile, "digraph %s\n{\n", info.compMethodName);
19294         fprintf(fgxFile, "/* Method %d, after phase %s */", Compiler::jitTotalMethodCompiled, PhaseNames[phase]);
19295     }
19296     else
19297     {
19298         fprintf(fgxFile, "<method");
19299
19300         escapedString = fgProcessEscapes(info.compFullName, s_EscapeMapping);
19301         fprintf(fgxFile, "\n    name=\"%s\"", escapedString);
19302
19303         escapedString = fgProcessEscapes(info.compClassName, s_EscapeMapping);
19304         fprintf(fgxFile, "\n    className=\"%s\"", escapedString);
19305
19306         escapedString = fgProcessEscapes(info.compMethodName, s_EscapeMapping);
19307         fprintf(fgxFile, "\n    methodName=\"%s\"", escapedString);
19308         fprintf(fgxFile, "\n    ngenRegion=\"%s\"", regionString);
19309
19310         fprintf(fgxFile, "\n    bytesOfIL=\"%d\"", info.compILCodeSize);
19311         fprintf(fgxFile, "\n    localVarCount=\"%d\"", lvaCount);
19312
19313         if (fgHaveProfileData())
19314         {
19315             fprintf(fgxFile, "\n    calledCount=\"%d\"", calledCount);
19316             fprintf(fgxFile, "\n    profileData=\"true\"");
19317         }
19318         if (compHndBBtabCount > 0)
19319         {
19320             fprintf(fgxFile, "\n    hasEHRegions=\"true\"");
19321         }
19322         if (fgHasLoops)
19323         {
19324             fprintf(fgxFile, "\n    hasLoops=\"true\"");
19325         }
19326         if (validWeights)
19327         {
19328             fprintf(fgxFile, "\n    validEdgeWeights=\"true\"");
19329             if (!fgSlopUsedInEdgeWeights && !fgRangeUsedInEdgeWeights)
19330             {
19331                 fprintf(fgxFile, "\n    exactEdgeWeights=\"true\"");
19332             }
19333         }
19334         if (fgFirstColdBlock != nullptr)
19335         {
19336             fprintf(fgxFile, "\n    firstColdBlock=\"%d\"", fgFirstColdBlock->bbNum);
19337         }
19338
19339         fprintf(fgxFile, ">");
19340
19341         fprintf(fgxFile, "\n    <blocks");
19342         fprintf(fgxFile, "\n        blockCount=\"%d\"", fgBBcount);
19343         fprintf(fgxFile, ">");
19344     }
19345
19346     static const char* kindImage[] = {"EHFINALLYRET", "EHFILTERRET", "EHCATCHRET",  "THROW", "RETURN", "NONE",
19347                                       "ALWAYS",       "LEAVE",       "CALLFINALLY", "COND",  "SWITCH"};
19348
19349     BasicBlock* block;
19350     unsigned    blockOrdinal;
19351     for (block = fgFirstBB, blockOrdinal = 1; block != nullptr; block = block->bbNext, blockOrdinal++)
19352     {
19353         if (createDotFile)
19354         {
19355             // Add constraint edges to try to keep nodes ordered.
19356             // It seems to work best if these edges are all created first.
19357             switch (block->bbJumpKind)
19358             {
19359                 case BBJ_COND:
19360                 case BBJ_NONE:
19361                     assert(block->bbNext != nullptr);
19362                     fprintf(fgxFile, "    BB%02u -> BB%02u\n", block->bbNum, block->bbNext->bbNum);
19363                     break;
19364                 default:
19365                     // These may or may not have an edge to the next block.
19366                     // Add a transparent edge to keep nodes ordered.
19367                     if (block->bbNext != nullptr)
19368                     {
19369                         fprintf(fgxFile, "    BB%02u -> BB%02u [arrowtail=none,color=transparent]\n", block->bbNum,
19370                                 block->bbNext->bbNum);
19371                     }
19372             }
19373         }
19374         else
19375         {
19376             fprintf(fgxFile, "\n        <block");
19377             fprintf(fgxFile, "\n            id=\"%d\"", block->bbNum);
19378             fprintf(fgxFile, "\n            ordinal=\"%d\"", blockOrdinal);
19379             fprintf(fgxFile, "\n            jumpKind=\"%s\"", kindImage[block->bbJumpKind]);
19380             if (block->hasTryIndex())
19381             {
19382                 fprintf(fgxFile, "\n            inTry=\"%s\"", "true");
19383             }
19384             if (block->hasHndIndex())
19385             {
19386                 fprintf(fgxFile, "\n            inHandler=\"%s\"", "true");
19387             }
19388             if ((fgFirstBB->hasProfileWeight()) && ((block->bbFlags & BBF_COLD) == 0))
19389             {
19390                 fprintf(fgxFile, "\n            hot=\"true\"");
19391             }
19392             if (block->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY))
19393             {
19394                 fprintf(fgxFile, "\n            callsNew=\"true\"");
19395             }
19396             if (block->bbFlags & BBF_LOOP_HEAD)
19397             {
19398                 fprintf(fgxFile, "\n            loopHead=\"true\"");
19399             }
19400             fprintf(fgxFile, "\n            weight=");
19401             fprintfDouble(fgxFile, ((double)block->bbWeight) / weightDivisor);
19402             fprintf(fgxFile, "\n            codeEstimate=\"%d\"", fgGetCodeEstimate(block));
19403             fprintf(fgxFile, "\n            startOffset=\"%d\"", block->bbCodeOffs);
19404             fprintf(fgxFile, "\n            endOffset=\"%d\"", block->bbCodeOffsEnd);
19405             fprintf(fgxFile, ">");
19406             fprintf(fgxFile, "\n        </block>");
19407         }
19408     }
19409
19410     if (!createDotFile)
19411     {
19412         fprintf(fgxFile, "\n    </blocks>");
19413
19414         fprintf(fgxFile, "\n    <edges");
19415         fprintf(fgxFile, "\n        edgeCount=\"%d\"", fgEdgeCount);
19416         fprintf(fgxFile, ">");
19417     }
19418
19419     unsigned    edgeNum = 1;
19420     BasicBlock* bTarget;
19421     for (bTarget = fgFirstBB; bTarget != nullptr; bTarget = bTarget->bbNext)
19422     {
19423         double targetWeightDivisor;
19424         if (bTarget->bbWeight == BB_ZERO_WEIGHT)
19425         {
19426             targetWeightDivisor = 1.0;
19427         }
19428         else
19429         {
19430             targetWeightDivisor = (double)bTarget->bbWeight;
19431         }
19432
19433         flowList* edge;
19434         for (edge = bTarget->bbPreds; edge != nullptr; edge = edge->flNext, edgeNum++)
19435         {
19436             BasicBlock* bSource = edge->flBlock;
19437             double      sourceWeightDivisor;
19438             if (bSource->bbWeight == BB_ZERO_WEIGHT)
19439             {
19440                 sourceWeightDivisor = 1.0;
19441             }
19442             else
19443             {
19444                 sourceWeightDivisor = (double)bSource->bbWeight;
19445             }
19446             if (createDotFile)
19447             {
19448                 // Don't duplicate the edges we added above.
19449                 if ((bSource->bbNum == (bTarget->bbNum - 1)) &&
19450                     ((bSource->bbJumpKind == BBJ_NONE) || (bSource->bbJumpKind == BBJ_COND)))
19451                 {
19452                     continue;
19453                 }
19454                 fprintf(fgxFile, "    BB%02u -> BB%02u", bSource->bbNum, bTarget->bbNum);
19455                 if ((bSource->bbNum > bTarget->bbNum))
19456                 {
19457                     fprintf(fgxFile, "[arrowhead=normal,arrowtail=none,color=green]\n");
19458                 }
19459                 else
19460                 {
19461                     fprintf(fgxFile, "\n");
19462                 }
19463             }
19464             else
19465             {
19466                 fprintf(fgxFile, "\n        <edge");
19467                 fprintf(fgxFile, "\n            id=\"%d\"", edgeNum);
19468                 fprintf(fgxFile, "\n            source=\"%d\"", bSource->bbNum);
19469                 fprintf(fgxFile, "\n            target=\"%d\"", bTarget->bbNum);
19470                 if (bSource->bbJumpKind == BBJ_SWITCH)
19471                 {
19472                     if (edge->flDupCount >= 2)
19473                     {
19474                         fprintf(fgxFile, "\n            switchCases=\"%d\"", edge->flDupCount);
19475                     }
19476                     if (bSource->bbJumpSwt->getDefault() == bTarget)
19477                     {
19478                         fprintf(fgxFile, "\n            switchDefault=\"true\"");
19479                     }
19480                 }
19481                 if (validWeights)
19482                 {
19483                     unsigned edgeWeight = (edge->flEdgeWeightMin + edge->flEdgeWeightMax) / 2;
19484                     fprintf(fgxFile, "\n            weight=");
19485                     fprintfDouble(fgxFile, ((double)edgeWeight) / weightDivisor);
19486
19487                     if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
19488                     {
19489                         fprintf(fgxFile, "\n            minWeight=");
19490                         fprintfDouble(fgxFile, ((double)edge->flEdgeWeightMin) / weightDivisor);
19491                         fprintf(fgxFile, "\n            maxWeight=");
19492                         fprintfDouble(fgxFile, ((double)edge->flEdgeWeightMax) / weightDivisor);
19493                     }
19494
19495                     if (edgeWeight > 0)
19496                     {
19497                         if (edgeWeight < bSource->bbWeight)
19498                         {
19499                             fprintf(fgxFile, "\n            out=");
19500                             fprintfDouble(fgxFile, ((double)edgeWeight) / sourceWeightDivisor);
19501                         }
19502                         if (edgeWeight < bTarget->bbWeight)
19503                         {
19504                             fprintf(fgxFile, "\n            in=");
19505                             fprintfDouble(fgxFile, ((double)edgeWeight) / targetWeightDivisor);
19506                         }
19507                     }
19508                 }
19509             }
19510             if (!createDotFile)
19511             {
19512                 fprintf(fgxFile, ">");
19513                 fprintf(fgxFile, "\n        </edge>");
19514             }
19515         }
19516     }
19517     if (createDotFile)
19518     {
19519         fprintf(fgxFile, "}\n");
19520     }
19521     else
19522     {
19523         fprintf(fgxFile, "\n    </edges>");
19524         fprintf(fgxFile, "\n</method>\n");
19525     }
19526
19527     if (dontClose)
19528     {
19529         // fgxFile is jitstdout or stderr
19530         fprintf(fgxFile, "\n");
19531     }
19532     else
19533     {
19534         fclose(fgxFile);
19535     }
19536
19537     return result;
19538 }
19539
19540 #endif // DUMP_FLOWGRAPHS
19541
19542 /*****************************************************************************/
19543 #ifdef DEBUG
19544
19545 void Compiler::fgDispReach()
19546 {
19547     printf("------------------------------------------------\n");
19548     printf("BBnum  Reachable by \n");
19549     printf("------------------------------------------------\n");
19550
19551     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
19552     {
19553         printf("BB%02u : ", block->bbNum);
19554         BLOCKSET_ITER_INIT(this, iter, block->bbReach, bbNum);
19555         while (iter.NextElem(this, &bbNum))
19556         {
19557             printf("BB%02u ", bbNum);
19558         }
19559         printf("\n");
19560     }
19561 }
19562
19563 void Compiler::fgDispDoms()
19564 {
19565     // Don't bother printing this when we have a large number of BasicBlocks in the method
19566     if (fgBBcount > 256)
19567     {
19568         return;
19569     }
19570
19571     printf("------------------------------------------------\n");
19572     printf("BBnum  Dominated by\n");
19573     printf("------------------------------------------------\n");
19574
19575     for (unsigned i = 1; i <= fgBBNumMax; ++i)
19576     {
19577         BasicBlock* current = fgBBInvPostOrder[i];
19578         printf("BB%02u:  ", current->bbNum);
19579         while (current != current->bbIDom)
19580         {
19581             printf("BB%02u ", current->bbNum);
19582             current = current->bbIDom;
19583         }
19584         printf("\n");
19585     }
19586 }
19587
19588 /*****************************************************************************/
19589
19590 void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 */)
19591 {
19592     const unsigned __int64 flags    = block->bbFlags;
19593     unsigned               bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax;
19594     int                    maxBlockNumWidth = CountDigits(bbNumMax);
19595     maxBlockNumWidth                        = max(maxBlockNumWidth, 2);
19596     int blockNumWidth                       = CountDigits(block->bbNum);
19597     blockNumWidth                           = max(blockNumWidth, 2);
19598     int blockNumPadding                     = maxBlockNumWidth - blockNumWidth;
19599
19600     printf("BB%02u%*s [%08p] %2u", block->bbNum, blockNumPadding, "", dspPtr(block), block->bbRefs);
19601
19602     //
19603     // Display EH 'try' region index
19604     //
19605
19606     if (block->hasTryIndex())
19607     {
19608         printf(" %2u", block->getTryIndex());
19609     }
19610     else
19611     {
19612         printf("   ");
19613     }
19614
19615     //
19616     // Display EH handler region index
19617     //
19618
19619     if (block->hasHndIndex())
19620     {
19621         printf(" %2u", block->getHndIndex());
19622     }
19623     else
19624     {
19625         printf("   ");
19626     }
19627
19628     printf(" ");
19629
19630     //
19631     // Display block predecessor list
19632     //
19633
19634     unsigned charCnt;
19635     if (fgCheapPredsValid)
19636     {
19637         charCnt = block->dspCheapPreds();
19638     }
19639     else
19640     {
19641         charCnt = block->dspPreds();
19642     }
19643
19644     if (charCnt < 19)
19645     {
19646         printf("%*s", 19 - charCnt, "");
19647     }
19648
19649     printf(" ");
19650
19651     //
19652     // Display block weight
19653     //
19654
19655     if (block->isMaxBBWeight())
19656     {
19657         printf(" MAX  ");
19658     }
19659     else
19660     {
19661         BasicBlock::weight_t weight = block->getBBWeight(this);
19662
19663         if (weight > 99999) // Is it going to be more than 6 characters?
19664         {
19665             if (weight <= 99999 * BB_UNITY_WEIGHT)
19666             {
19667                 // print weight in this format ddddd.
19668                 printf("%5u.", (weight + (BB_UNITY_WEIGHT / 2)) / BB_UNITY_WEIGHT);
19669             }
19670             else // print weight in terms of k (i.e. 156k )
19671             {
19672                 // print weight in this format dddddk
19673                 BasicBlock::weight_t weightK = weight / 1000;
19674                 printf("%5uk", (weightK + (BB_UNITY_WEIGHT / 2)) / BB_UNITY_WEIGHT);
19675             }
19676         }
19677         else // print weight in this format ddd.dd
19678         {
19679             printf("%6s", refCntWtd2str(weight));
19680         }
19681     }
19682     printf(" ");
19683
19684     //
19685     // Display optional IBC weight column.
19686     // Note that iColWidth includes one character for a leading space, if there is an IBC column.
19687     //
19688
19689     if (ibcColWidth > 0)
19690     {
19691         if (block->hasProfileWeight())
19692         {
19693             printf("%*u", ibcColWidth, block->bbWeight);
19694         }
19695         else
19696         {
19697             // No IBC data. Just print spaces to align the column.
19698             printf("%*s", ibcColWidth, "");
19699         }
19700     }
19701
19702     printf(" ");
19703
19704     //
19705     // Display block IL range
19706     //
19707
19708     block->dspBlockILRange();
19709
19710     //
19711     // Display block branch target
19712     //
19713
19714     if (flags & BBF_REMOVED)
19715     {
19716         printf("[removed]       ");
19717     }
19718     else
19719     {
19720         switch (block->bbJumpKind)
19721         {
19722             case BBJ_COND:
19723                 printf("-> BB%02u%*s ( cond )", block->bbJumpDest->bbNum,
19724                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19725                 break;
19726
19727             case BBJ_CALLFINALLY:
19728                 printf("-> BB%02u%*s (callf )", block->bbJumpDest->bbNum,
19729                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19730                 break;
19731
19732             case BBJ_ALWAYS:
19733                 if (flags & BBF_KEEP_BBJ_ALWAYS)
19734                 {
19735                     printf("-> BB%02u%*s (ALWAYS)", block->bbJumpDest->bbNum,
19736                            maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19737                 }
19738                 else
19739                 {
19740                     printf("-> BB%02u%*s (always)", block->bbJumpDest->bbNum,
19741                            maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19742                 }
19743                 break;
19744
19745             case BBJ_LEAVE:
19746                 printf("-> BB%02u%*s (leave )", block->bbJumpDest->bbNum,
19747                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19748                 break;
19749
19750             case BBJ_EHFINALLYRET:
19751                 printf("%*s        (finret)", maxBlockNumWidth - 2, "");
19752                 break;
19753
19754             case BBJ_EHFILTERRET:
19755                 printf("%*s        (fltret)", maxBlockNumWidth - 2, "");
19756                 break;
19757
19758             case BBJ_EHCATCHRET:
19759                 printf("-> BB%02u%*s ( cret )", block->bbJumpDest->bbNum,
19760                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19761                 break;
19762
19763             case BBJ_THROW:
19764                 printf("%*s        (throw )", maxBlockNumWidth - 2, "");
19765                 break;
19766
19767             case BBJ_RETURN:
19768                 printf("%*s        (return)", maxBlockNumWidth - 2, "");
19769                 break;
19770
19771             default:
19772                 printf("%*s                ", maxBlockNumWidth - 2, "");
19773                 break;
19774
19775             case BBJ_SWITCH:
19776                 printf("->");
19777
19778                 unsigned jumpCnt;
19779                 jumpCnt = block->bbJumpSwt->bbsCount;
19780                 BasicBlock** jumpTab;
19781                 jumpTab = block->bbJumpSwt->bbsDstTab;
19782                 int switchWidth;
19783                 switchWidth = 0;
19784                 do
19785                 {
19786                     printf("%cBB%02u", (jumpTab == block->bbJumpSwt->bbsDstTab) ? ' ' : ',', (*jumpTab)->bbNum);
19787                     switchWidth += 1 /* space/comma */ + 2 /* BB */ + max(CountDigits((*jumpTab)->bbNum), 2);
19788                 } while (++jumpTab, --jumpCnt);
19789
19790                 if (switchWidth < 7)
19791                 {
19792                     printf("%*s", 8 - switchWidth, "");
19793                 }
19794
19795                 printf(" (switch)");
19796                 break;
19797         }
19798     }
19799
19800     printf(" ");
19801
19802     //
19803     // Display block EH region and type, including nesting indicator
19804     //
19805
19806     if (block->hasTryIndex())
19807     {
19808         printf("T%d ", block->getTryIndex());
19809     }
19810     else
19811     {
19812         printf("   ");
19813     }
19814
19815     if (block->hasHndIndex())
19816     {
19817         printf("H%d ", block->getHndIndex());
19818     }
19819     else
19820     {
19821         printf("   ");
19822     }
19823
19824     if (flags & BBF_FUNCLET_BEG)
19825     {
19826         printf("F ");
19827     }
19828     else
19829     {
19830         printf("  ");
19831     }
19832
19833     int cnt = 0;
19834
19835     switch (block->bbCatchTyp)
19836     {
19837         case BBCT_NONE:
19838             break;
19839         case BBCT_FAULT:
19840             printf("fault ");
19841             cnt += 6;
19842             break;
19843         case BBCT_FINALLY:
19844             printf("finally ");
19845             cnt += 8;
19846             break;
19847         case BBCT_FILTER:
19848             printf("filter ");
19849             cnt += 7;
19850             break;
19851         case BBCT_FILTER_HANDLER:
19852             printf("filtHnd ");
19853             cnt += 8;
19854             break;
19855         default:
19856             printf("catch ");
19857             cnt += 6;
19858             break;
19859     }
19860
19861     if (block->bbCatchTyp != BBCT_NONE)
19862     {
19863         cnt += 2;
19864         printf("{ ");
19865         /* brace matching editor workaround to compensate for the preceding line: } */
19866     }
19867
19868     if (flags & BBF_TRY_BEG)
19869     {
19870         // Output a brace for every try region that this block opens
19871
19872         EHblkDsc* HBtab;
19873         EHblkDsc* HBtabEnd;
19874
19875         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
19876         {
19877             if (HBtab->ebdTryBeg == block)
19878             {
19879                 cnt += 6;
19880                 printf("try { ");
19881                 /* brace matching editor workaround to compensate for the preceding line: } */
19882             }
19883         }
19884     }
19885
19886     EHblkDsc* HBtab;
19887     EHblkDsc* HBtabEnd;
19888
19889     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
19890     {
19891         if (HBtab->ebdTryLast == block)
19892         {
19893             cnt += 2;
19894             /* brace matching editor workaround to compensate for the following line: { */
19895             printf("} ");
19896         }
19897         if (HBtab->ebdHndLast == block)
19898         {
19899             cnt += 2;
19900             /* brace matching editor workaround to compensate for the following line: { */
19901             printf("} ");
19902         }
19903         if (HBtab->HasFilter() && block->bbNext == HBtab->ebdHndBeg)
19904         {
19905             cnt += 2;
19906             /* brace matching editor workaround to compensate for the following line: { */
19907             printf("} ");
19908         }
19909     }
19910
19911     while (cnt < 12)
19912     {
19913         cnt++;
19914         printf(" ");
19915     }
19916
19917     //
19918     // Display block flags
19919     //
19920
19921     block->dspFlags();
19922
19923     printf("\n");
19924 }
19925
19926 /****************************************************************************
19927     Dump blocks from firstBlock to lastBlock.
19928 */
19929
19930 void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, bool dumpTrees)
19931 {
19932     BasicBlock* block;
19933
19934     int padWidth = 0;
19935 #ifdef _TARGET_AMD64_
19936     padWidth = 8;
19937 #endif // _TARGET_AMD64_
19938
19939     // If any block has IBC data, we add an "IBC weight" column just before the 'IL range' column. This column is as
19940     // wide as necessary to accommodate all the various IBC weights. It's at least 4 characters wide, to accommodate
19941     // the "IBC" title and leading space.
19942     int ibcColWidth = 0;
19943     for (block = firstBlock; block != nullptr; block = block->bbNext)
19944     {
19945         if (block->hasProfileWeight())
19946         {
19947             int thisIbcWidth = CountDigits(block->bbWeight);
19948             ibcColWidth      = max(ibcColWidth, thisIbcWidth);
19949         }
19950
19951         if (block == lastBlock)
19952         {
19953             break;
19954         }
19955     }
19956     if (ibcColWidth > 0)
19957     {
19958         ibcColWidth = max(ibcColWidth, 3) + 1; // + 1 for the leading space
19959     }
19960
19961     unsigned bbNumMax         = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax;
19962     int      maxBlockNumWidth = CountDigits(bbNumMax);
19963     maxBlockNumWidth          = max(maxBlockNumWidth, 2);
19964
19965     padWidth += maxBlockNumWidth - 2; // Account for functions with a large number of blocks.
19966
19967     // clang-format off
19968
19969     printf("\n");
19970     printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n",
19971         padWidth, "------------",
19972         ibcColWidth, "------------",
19973         maxBlockNumWidth, "----");
19974     printf("BBnum %*sdescAddr ref try hnd %s     weight  %*s%s  [IL range]     [jump]%*s    [EH region]         [flags]\n",
19975         padWidth, "",
19976         fgCheapPredsValid       ? "cheap preds" :
19977         (fgComputePredsDone     ? "preds      "
19978                                 : "           "),
19979         ((ibcColWidth > 0) ? ibcColWidth - 3 : 0), "",  // Subtract 3 for the width of "IBC", printed next.
19980         ((ibcColWidth > 0)      ? "IBC"
19981                                 : ""),
19982         maxBlockNumWidth, ""
19983         );
19984     printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n",
19985         padWidth, "------------",
19986         ibcColWidth, "------------",
19987         maxBlockNumWidth, "----");
19988
19989     // clang-format on
19990
19991     for (block = firstBlock; block; block = block->bbNext)
19992     {
19993         // First, do some checking on the bbPrev links
19994         if (block->bbPrev)
19995         {
19996             if (block->bbPrev->bbNext != block)
19997             {
19998                 printf("bad prev link\n");
19999             }
20000         }
20001         else if (block != fgFirstBB)
20002         {
20003             printf("bad prev link!\n");
20004         }
20005
20006         if (block == fgFirstColdBlock)
20007         {
20008             printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~"
20009                    "~~~~~~~~~~~~~~~~\n",
20010                    padWidth, "~~~~~~~~~~~~", ibcColWidth, "~~~~~~~~~~~~", maxBlockNumWidth, "~~~~");
20011         }
20012
20013 #if FEATURE_EH_FUNCLETS
20014         if (block == fgFirstFuncletBB)
20015         {
20016             printf("++++++%*s+++++++++++++++++++++++++++++++++++++%*s+++++++++++++++++++++++%*s++++++++++++++++++++++++"
20017                    "++++++++++++++++ funclets follow\n",
20018                    padWidth, "++++++++++++", ibcColWidth, "++++++++++++", maxBlockNumWidth, "++++");
20019         }
20020 #endif // FEATURE_EH_FUNCLETS
20021
20022         fgTableDispBasicBlock(block, ibcColWidth);
20023
20024         if (block == lastBlock)
20025         {
20026             break;
20027         }
20028     }
20029
20030     printf("------%*s-------------------------------------%*s-----------------------%*s--------------------------------"
20031            "--------\n",
20032            padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----");
20033
20034     if (dumpTrees)
20035     {
20036         fgDumpTrees(firstBlock, lastBlock);
20037     }
20038 }
20039
20040 /*****************************************************************************/
20041
20042 void Compiler::fgDispBasicBlocks(bool dumpTrees)
20043 {
20044     fgDispBasicBlocks(fgFirstBB, nullptr, dumpTrees);
20045 }
20046
20047 /*****************************************************************************/
20048 //  Increment the stmtNum and dump the tree using gtDispTree
20049 //
20050 void Compiler::fgDumpStmtTree(GenTreePtr stmt, unsigned blkNum)
20051 {
20052     compCurStmtNum++; // Increment the current stmtNum
20053
20054     printf("\n***** BB%02u, stmt %d\n", blkNum, compCurStmtNum);
20055
20056     if (fgOrder == FGOrderLinear || opts.compDbgInfo)
20057     {
20058         gtDispTree(stmt);
20059     }
20060     else
20061     {
20062         gtDispTree(stmt->gtStmt.gtStmtExpr);
20063     }
20064 }
20065
20066 //------------------------------------------------------------------------
20067 // Compiler::fgDumpBlock: dumps the contents of the given block to stdout.
20068 //
20069 // Arguments:
20070 //    block - The block to dump.
20071 //
20072 void Compiler::fgDumpBlock(BasicBlock* block)
20073 {
20074     printf("\n------------ ");
20075     block->dspBlockHeader(this);
20076
20077     if (!block->IsLIR())
20078     {
20079         for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
20080         {
20081             fgDumpStmtTree(stmt, block->bbNum);
20082             if (stmt == block->bbTreeList)
20083             {
20084                 block->bbStmtNum = compCurStmtNum; // Set the block->bbStmtNum
20085             }
20086         }
20087     }
20088     else
20089     {
20090         gtDispRange(LIR::AsRange(block));
20091     }
20092 }
20093
20094 /*****************************************************************************/
20095 //  Walk the BasicBlock list calling fgDumpTree once per Stmt
20096 //
20097 void Compiler::fgDumpTrees(BasicBlock* firstBlock, BasicBlock* lastBlock)
20098 {
20099     compCurStmtNum = 0; // Reset the current stmtNum
20100
20101     /* Walk the basic blocks */
20102
20103     // Note that typically we have already called fgDispBasicBlocks()
20104     //  so we don't need to print the preds and succs again here
20105     //
20106     for (BasicBlock* block = firstBlock; block; block = block->bbNext)
20107     {
20108         fgDumpBlock(block);
20109
20110         if (block == lastBlock)
20111         {
20112             break;
20113         }
20114     }
20115     printf("\n---------------------------------------------------------------------------------------------------------"
20116            "----------\n");
20117 }
20118
20119 /*****************************************************************************
20120  * Try to create as many candidates for GTF_MUL_64RSLT as possible.
20121  * We convert 'intOp1*intOp2' into 'int(long(nop(intOp1))*long(intOp2))'.
20122  */
20123
20124 /* static */
20125 Compiler::fgWalkResult Compiler::fgStress64RsltMulCB(GenTreePtr* pTree, fgWalkData* data)
20126 {
20127     GenTreePtr tree  = *pTree;
20128     Compiler*  pComp = data->compiler;
20129
20130     if (tree->gtOper != GT_MUL || tree->gtType != TYP_INT || (tree->gtOverflow()))
20131     {
20132         return WALK_CONTINUE;
20133     }
20134
20135 #ifdef DEBUG
20136     if (pComp->verbose)
20137     {
20138         printf("STRESS_64RSLT_MUL before:\n");
20139         pComp->gtDispTree(tree);
20140     }
20141 #endif // DEBUG
20142
20143     // To ensure optNarrowTree() doesn't fold back to the original tree.
20144     tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, TYP_LONG);
20145     tree->gtOp.gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->gtOp.gtOp1);
20146     tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, TYP_LONG);
20147     tree->gtOp.gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp2, TYP_LONG);
20148     tree->gtType     = TYP_LONG;
20149     *pTree           = pComp->gtNewCastNode(TYP_INT, tree, TYP_INT);
20150
20151 #ifdef DEBUG
20152     if (pComp->verbose)
20153     {
20154         printf("STRESS_64RSLT_MUL after:\n");
20155         pComp->gtDispTree(*pTree);
20156     }
20157 #endif // DEBUG
20158
20159     return WALK_SKIP_SUBTREES;
20160 }
20161
20162 void Compiler::fgStress64RsltMul()
20163 {
20164     if (!compStressCompile(STRESS_64RSLT_MUL, 20))
20165     {
20166         return;
20167     }
20168
20169     fgWalkAllTreesPre(fgStress64RsltMulCB, (void*)this);
20170 }
20171
20172 // This variable is used to generate "traversal labels": one-time constants with which
20173 // we label basic blocks that are members of the basic block list, in order to have a
20174 // fast, high-probability test for membership in that list.  Type is "volatile" because
20175 // it's incremented with an atomic operation, which wants a volatile type; "long" so that
20176 // wrap-around to 0 (which I think has the highest probability of accidental collision) is
20177 // postponed a *long* time.
20178 static volatile int bbTraverseLabel = 1;
20179
20180 /*****************************************************************************
20181  *
20182  * A DEBUG routine to check the consistency of the flowgraph,
20183  * i.e. bbNum, bbRefs, bbPreds have to be up to date.
20184  *
20185  *****************************************************************************/
20186
20187 void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, bool checkBBRefs /* = true  */)
20188 {
20189 #ifdef DEBUG
20190     if (verbose)
20191     {
20192         printf("*************** In fgDebugCheckBBlist\n");
20193     }
20194 #endif // DEBUG
20195
20196     fgDebugCheckBlockLinks();
20197
20198     if (fgBBcount > 10000 && expensiveDebugCheckLevel < 1)
20199     {
20200         // The basic block checks are too expensive if there are too many blocks,
20201         // so give up unless we've been told to try hard.
20202         return;
20203     }
20204
20205     DWORD startTickCount = GetTickCount();
20206
20207     BasicBlock* block;
20208     BasicBlock* prevBlock;
20209     BasicBlock* blockPred;
20210     flowList*   pred;
20211     unsigned    blockRefs;
20212
20213 #if FEATURE_EH_FUNCLETS
20214     bool reachedFirstFunclet = false;
20215     if (fgFuncletsCreated)
20216     {
20217         //
20218         // Make sure that fgFirstFuncletBB is accurate.
20219         // It should be the first basic block in a handler region.
20220         //
20221         if (fgFirstFuncletBB != nullptr)
20222         {
20223             assert(fgFirstFuncletBB->hasHndIndex() == true);
20224             assert(fgFirstFuncletBB->bbFlags & BBF_FUNCLET_BEG);
20225         }
20226     }
20227 #endif // FEATURE_EH_FUNCLETS
20228
20229     /* Check bbNum, bbRefs and bbPreds */
20230     // First, pick a traversal stamp, and label all the blocks with it.
20231     unsigned curTraversalStamp = unsigned(InterlockedIncrement((LONG*)&bbTraverseLabel));
20232     for (block = fgFirstBB; block; block = block->bbNext)
20233     {
20234         block->bbTraversalStamp = curTraversalStamp;
20235     }
20236
20237     for (prevBlock = nullptr, block = fgFirstBB; block; prevBlock = block, block = block->bbNext)
20238     {
20239         blockRefs = 0;
20240
20241         /* First basic block has countOfInEdges() >= 1 */
20242
20243         if (block == fgFirstBB)
20244         {
20245             noway_assert(block->countOfInEdges() >= 1);
20246             blockRefs = 1;
20247         }
20248
20249         if (checkBBNum)
20250         {
20251             // Check that bbNum is sequential
20252             noway_assert(block->bbNext == nullptr || (block->bbNum + 1 == block->bbNext->bbNum));
20253         }
20254
20255         // If the block is a BBJ_COND, a BBJ_SWITCH or a
20256         // lowered GT_SWITCH_TABLE node then make sure it
20257         // ends with a conditional jump or a GT_SWITCH
20258
20259         if (block->bbJumpKind == BBJ_COND)
20260         {
20261             noway_assert(block->lastNode()->gtNext == nullptr && block->lastNode()->OperIsConditionalJump());
20262         }
20263         else if (block->bbJumpKind == BBJ_SWITCH)
20264         {
20265 #ifndef LEGACY_BACKEND
20266             noway_assert(block->lastNode()->gtNext == nullptr &&
20267                          (block->lastNode()->gtOper == GT_SWITCH || block->lastNode()->gtOper == GT_SWITCH_TABLE));
20268 #else  // LEGACY_BACKEND
20269             noway_assert(block->lastStmt()->gtNext == NULL && block->lastStmt()->gtStmtExpr->gtOper == GT_SWITCH);
20270 #endif // LEGACY_BACKEND
20271         }
20272         else if (!(block->bbJumpKind == BBJ_ALWAYS || block->bbJumpKind == BBJ_RETURN))
20273         {
20274             // this block cannot have a poll
20275             noway_assert(!(block->bbFlags & BBF_NEEDS_GCPOLL));
20276         }
20277
20278         if (block->bbCatchTyp == BBCT_FILTER)
20279         {
20280             if (!fgCheapPredsValid) // Don't check cheap preds
20281             {
20282                 // A filter has no predecessors
20283                 noway_assert(block->bbPreds == nullptr);
20284             }
20285         }
20286
20287 #if FEATURE_EH_FUNCLETS
20288         if (fgFuncletsCreated)
20289         {
20290             //
20291             // There should be no handler blocks until
20292             // we get to the fgFirstFuncletBB block,
20293             // then every block should be a handler block
20294             //
20295             if (!reachedFirstFunclet)
20296             {
20297                 if (block == fgFirstFuncletBB)
20298                 {
20299                     assert(block->hasHndIndex() == true);
20300                     reachedFirstFunclet = true;
20301                 }
20302                 else
20303                 {
20304                     assert(block->hasHndIndex() == false);
20305                 }
20306             }
20307             else // reachedFirstFunclet
20308             {
20309                 assert(block->hasHndIndex() == true);
20310             }
20311         }
20312 #endif // FEATURE_EH_FUNCLETS
20313
20314         // Don't check cheap preds.
20315         for (pred = (fgCheapPredsValid ? nullptr : block->bbPreds); pred != nullptr;
20316              blockRefs += pred->flDupCount, pred = pred->flNext)
20317         {
20318             assert(fgComputePredsDone); // If this isn't set, why do we have a preds list?
20319
20320             /*  make sure this pred is part of the BB list */
20321
20322             blockPred = pred->flBlock;
20323             noway_assert(blockPred->bbTraversalStamp == curTraversalStamp);
20324
20325             EHblkDsc* ehTryDsc = ehGetBlockTryDsc(block);
20326             if (ehTryDsc != nullptr)
20327             {
20328                 // You can jump to the start of a try
20329                 if (ehTryDsc->ebdTryBeg == block)
20330                 {
20331                     goto CHECK_HND;
20332                 }
20333
20334                 // You can jump within the same try region
20335                 if (bbInTryRegions(block->getTryIndex(), blockPred))
20336                 {
20337                     goto CHECK_HND;
20338                 }
20339
20340                 // The catch block can jump back into the middle of the try
20341                 if (bbInCatchHandlerRegions(block, blockPred))
20342                 {
20343                     goto CHECK_HND;
20344                 }
20345
20346                 // The end of a finally region is a BBJ_EHFINALLYRET block (during importing, BBJ_LEAVE) which
20347                 // is marked as "returning" to the BBJ_ALWAYS block following the BBJ_CALLFINALLY
20348                 // block that does a local call to the finally. This BBJ_ALWAYS is within
20349                 // the try region protected by the finally (for x86, ARM), but that's ok.
20350                 if (prevBlock->bbJumpKind == BBJ_CALLFINALLY && block->bbJumpKind == BBJ_ALWAYS &&
20351                     blockPred->bbJumpKind == BBJ_EHFINALLYRET)
20352                 {
20353                     goto CHECK_HND;
20354                 }
20355
20356                 printf("Jump into the middle of try region: BB%02u branches to BB%02u\n", blockPred->bbNum,
20357                        block->bbNum);
20358                 noway_assert(!"Jump into middle of try region");
20359             }
20360
20361         CHECK_HND:;
20362
20363             EHblkDsc* ehHndDsc = ehGetBlockHndDsc(block);
20364             if (ehHndDsc != nullptr)
20365             {
20366                 // You can do a BBJ_EHFINALLYRET or BBJ_EHFILTERRET into a handler region
20367                 if ((blockPred->bbJumpKind == BBJ_EHFINALLYRET) || (blockPred->bbJumpKind == BBJ_EHFILTERRET))
20368                 {
20369                     goto CHECK_JUMP;
20370                 }
20371
20372                 // Our try block can call our finally block
20373                 if ((block->bbCatchTyp == BBCT_FINALLY) && (blockPred->bbJumpKind == BBJ_CALLFINALLY) &&
20374                     ehCallFinallyInCorrectRegion(blockPred, block->getHndIndex()))
20375                 {
20376                     goto CHECK_JUMP;
20377                 }
20378
20379                 // You can jump within the same handler region
20380                 if (bbInHandlerRegions(block->getHndIndex(), blockPred))
20381                 {
20382                     goto CHECK_JUMP;
20383                 }
20384
20385                 // A filter can jump to the start of the filter handler
20386                 if (ehHndDsc->HasFilter())
20387                 {
20388                     goto CHECK_JUMP;
20389                 }
20390
20391                 printf("Jump into the middle of handler region: BB%02u branches to BB%02u\n", blockPred->bbNum,
20392                        block->bbNum);
20393                 noway_assert(!"Jump into the middle of handler region");
20394             }
20395
20396         CHECK_JUMP:;
20397
20398             switch (blockPred->bbJumpKind)
20399             {
20400                 case BBJ_COND:
20401                     noway_assert(blockPred->bbNext == block || blockPred->bbJumpDest == block);
20402                     break;
20403
20404                 case BBJ_NONE:
20405                     noway_assert(blockPred->bbNext == block);
20406                     break;
20407
20408                 case BBJ_CALLFINALLY:
20409                 case BBJ_ALWAYS:
20410                 case BBJ_EHCATCHRET:
20411                 case BBJ_EHFILTERRET:
20412                     noway_assert(blockPred->bbJumpDest == block);
20413                     break;
20414
20415                 case BBJ_EHFINALLYRET:
20416                 {
20417                     // If the current block is a successor to a BBJ_EHFINALLYRET (return from finally),
20418                     // then the lexically previous block should be a call to the same finally.
20419                     // Verify all of that.
20420
20421                     unsigned    hndIndex = blockPred->getHndIndex();
20422                     EHblkDsc*   ehDsc    = ehGetDsc(hndIndex);
20423                     BasicBlock* finBeg   = ehDsc->ebdHndBeg;
20424
20425                     // Because there is no bbPrev, we have to search for the lexically previous
20426                     // block.  We can shorten the search by only looking in places where it is legal
20427                     // to have a call to the finally.
20428
20429                     BasicBlock* begBlk;
20430                     BasicBlock* endBlk;
20431                     ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
20432
20433                     for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
20434                     {
20435                         if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
20436                         {
20437                             continue;
20438                         }
20439
20440                         if (block == bcall->bbNext)
20441                         {
20442                             goto PRED_OK;
20443                         }
20444                     }
20445
20446 #if FEATURE_EH_FUNCLETS
20447
20448                     if (fgFuncletsCreated)
20449                     {
20450                         // There is no easy way to search just the funclets that were pulled out of
20451                         // the corresponding try body, so instead we search all the funclets, and if
20452                         // we find a potential 'hit' we check if the funclet we're looking at is
20453                         // from the correct try region.
20454
20455                         for (BasicBlock* bcall = fgFirstFuncletBB; bcall; bcall = bcall->bbNext)
20456                         {
20457                             if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
20458                             {
20459                                 continue;
20460                             }
20461
20462                             if (block != bcall->bbNext)
20463                             {
20464                                 continue;
20465                             }
20466
20467                             if (ehCallFinallyInCorrectRegion(bcall, hndIndex))
20468                             {
20469                                 goto PRED_OK;
20470                             }
20471                         }
20472                     }
20473
20474 #endif // FEATURE_EH_FUNCLETS
20475
20476                     noway_assert(!"BBJ_EHFINALLYRET predecessor of block that doesn't follow a BBJ_CALLFINALLY!");
20477                 }
20478                 break;
20479
20480                 case BBJ_THROW:
20481                 case BBJ_RETURN:
20482                     noway_assert(!"THROW and RETURN block cannot be in the predecessor list!");
20483                     break;
20484
20485                 case BBJ_SWITCH:
20486                     unsigned jumpCnt;
20487                     jumpCnt = blockPred->bbJumpSwt->bbsCount;
20488                     BasicBlock** jumpTab;
20489                     jumpTab = blockPred->bbJumpSwt->bbsDstTab;
20490
20491                     do
20492                     {
20493                         if (block == *jumpTab)
20494                         {
20495                             goto PRED_OK;
20496                         }
20497                     } while (++jumpTab, --jumpCnt);
20498
20499                     noway_assert(!"SWITCH in the predecessor list with no jump label to BLOCK!");
20500                     break;
20501
20502                 default:
20503                     noway_assert(!"Unexpected bbJumpKind");
20504                     break;
20505             }
20506
20507         PRED_OK:;
20508         }
20509
20510         /* Check the bbRefs */
20511         noway_assert(!checkBBRefs || block->bbRefs == blockRefs);
20512
20513         /* Check that BBF_HAS_HANDLER is valid bbTryIndex */
20514         if (block->hasTryIndex())
20515         {
20516             noway_assert(block->getTryIndex() < compHndBBtabCount);
20517         }
20518
20519         /* Check if BBF_RUN_RARELY is set that we have bbWeight of zero */
20520         if (block->isRunRarely())
20521         {
20522             noway_assert(block->bbWeight == BB_ZERO_WEIGHT);
20523         }
20524         else
20525         {
20526             noway_assert(block->bbWeight > BB_ZERO_WEIGHT);
20527         }
20528     }
20529
20530     // Make sure the one return BB is not changed.
20531     if (genReturnBB)
20532     {
20533         noway_assert(genReturnBB->bbTreeList);
20534         noway_assert(genReturnBB->IsLIR() || genReturnBB->bbTreeList->gtOper == GT_STMT);
20535         noway_assert(genReturnBB->IsLIR() || genReturnBB->bbTreeList->gtType == TYP_VOID);
20536     }
20537
20538     // The general encoder/decoder (currently) only reports "this" as a generics context as a stack location,
20539     // so we mark info.compThisArg as lvAddrTaken to ensure that it is not enregistered. Otherwise, it should
20540     // not be address-taken.  This variable determines if the address-taken-ness of "thisArg" is "OK".
20541     bool copiedForGenericsCtxt;
20542 #ifndef JIT32_GCENCODER
20543     copiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0);
20544 #else  // JIT32_GCENCODER
20545     copiedForGenericsCtxt = FALSE;
20546 #endif // JIT32_GCENCODER
20547
20548     // This if only in support of the noway_asserts it contains.
20549     if (info.compIsStatic)
20550     {
20551         // For static method, should have never grabbed the temp.
20552         noway_assert(lvaArg0Var == BAD_VAR_NUM);
20553     }
20554     else
20555     {
20556         // For instance method:
20557         assert(info.compThisArg != BAD_VAR_NUM);
20558         bool compThisArgAddrExposedOK = !lvaTable[info.compThisArg].lvAddrExposed;
20559
20560 #ifndef JIT32_GCENCODER
20561         compThisArgAddrExposedOK = compThisArgAddrExposedOK || copiedForGenericsCtxt;
20562 #endif // !JIT32_GCENCODER
20563
20564         // Should never expose the address of arg 0 or write to arg 0.
20565         // In addition, lvArg0Var should remain 0 if arg0 is not
20566         // written to or address-exposed.
20567         noway_assert(
20568             compThisArgAddrExposedOK && !lvaTable[info.compThisArg].lvHasILStoreOp &&
20569             (lvaArg0Var == info.compThisArg ||
20570              lvaArg0Var != info.compThisArg &&
20571                  (lvaTable[lvaArg0Var].lvAddrExposed || lvaTable[lvaArg0Var].lvHasILStoreOp || copiedForGenericsCtxt)));
20572     }
20573 }
20574
20575 /*****************************************************************************
20576  *
20577  * A DEBUG routine to check the that the exception flags are correctly set.
20578  *
20579  ****************************************************************************/
20580
20581 void Compiler::fgDebugCheckFlags(GenTreePtr tree)
20582 {
20583     noway_assert(tree->gtOper != GT_STMT);
20584
20585     genTreeOps oper      = tree->OperGet();
20586     unsigned   kind      = tree->OperKind();
20587     unsigned   treeFlags = tree->gtFlags & GTF_ALL_EFFECT;
20588     unsigned   chkFlags  = 0;
20589
20590     /* Is this a leaf node? */
20591
20592     if (kind & GTK_LEAF)
20593     {
20594         switch (oper)
20595         {
20596             case GT_CLS_VAR:
20597                 chkFlags |= GTF_GLOB_REF;
20598                 break;
20599
20600             case GT_CATCH_ARG:
20601                 chkFlags |= GTF_ORDER_SIDEEFF;
20602                 break;
20603
20604             default:
20605                 break;
20606         }
20607     }
20608
20609     /* Is it a 'simple' unary/binary operator? */
20610
20611     else if (kind & GTK_SMPOP)
20612     {
20613         GenTreePtr op1 = tree->gtOp.gtOp1;
20614         GenTreePtr op2 = tree->gtGetOp2IfPresent();
20615
20616         // During GS work, we make shadow copies for params.
20617         // In gsParamsToShadows(), we create a shadow var of TYP_INT for every small type param.
20618         // Then in gsReplaceShadowParams(), we change the gtLclNum to the shadow var.
20619         // We also change the types of the local var tree and the assignment tree to TYP_INT if necessary.
20620         // However, since we don't morph the tree at this late stage. Manually propagating
20621         // TYP_INT up to the GT_ASG tree is only correct if we don't need to propagate the TYP_INT back up.
20622         // The following checks will ensure this.
20623
20624         // Is the left child of "tree" a GT_ASG?
20625         //
20626         // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
20627         // (or) If GT_ASG is the left child of a GT_COMMA, the type of the GT_COMMA node will
20628         // be determined by its right child. So we don't need to propagate TYP_INT up either. We are fine.
20629         if (op1 && op1->gtOper == GT_ASG)
20630         {
20631             assert(tree->gtType == TYP_VOID || tree->gtOper == GT_COMMA);
20632         }
20633
20634         // Is the right child of "tree" a GT_ASG?
20635         //
20636         // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
20637         if (op2 && op2->gtOper == GT_ASG)
20638         {
20639             assert(tree->gtType == TYP_VOID);
20640         }
20641
20642         switch (oper)
20643         {
20644             case GT_QMARK:
20645                 if (op1->OperIsCompare())
20646                 {
20647                     noway_assert(op1->gtFlags & GTF_DONT_CSE);
20648                 }
20649                 else
20650                 {
20651                     noway_assert((op1->gtOper == GT_CNS_INT) &&
20652                                  ((op1->gtIntCon.gtIconVal == 0) || (op1->gtIntCon.gtIconVal == 1)));
20653                 }
20654                 break;
20655
20656             case GT_LIST:
20657             case GT_FIELD_LIST:
20658                 if ((op2 != nullptr) && op2->OperIsAnyList())
20659                 {
20660                     ArrayStack<GenTree*> stack(this);
20661                     while ((tree->gtGetOp2() != nullptr) && tree->gtGetOp2()->OperIsAnyList())
20662                     {
20663                         stack.Push(tree);
20664                         tree = tree->gtGetOp2();
20665                     }
20666
20667                     fgDebugCheckFlags(tree);
20668
20669                     while (stack.Height() > 0)
20670                     {
20671                         tree = stack.Pop();
20672                         assert((tree->gtFlags & GTF_REVERSE_OPS) == 0);
20673                         fgDebugCheckFlags(tree->gtOp.gtOp1);
20674                         chkFlags |= (tree->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT);
20675                         chkFlags |= (tree->gtGetOp2()->gtFlags & GTF_ALL_EFFECT);
20676                         fgDebugCheckFlagsHelper(tree, (tree->gtFlags & GTF_ALL_EFFECT), chkFlags);
20677                     }
20678
20679                     return;
20680                 }
20681                 break;
20682
20683             default:
20684                 break;
20685         }
20686
20687         /* Recursively check the subtrees */
20688
20689         if (op1)
20690         {
20691             fgDebugCheckFlags(op1);
20692         }
20693         if (op2)
20694         {
20695             fgDebugCheckFlags(op2);
20696         }
20697
20698         if (op1)
20699         {
20700             chkFlags |= (op1->gtFlags & GTF_ALL_EFFECT);
20701         }
20702         if (op2)
20703         {
20704             chkFlags |= (op2->gtFlags & GTF_ALL_EFFECT);
20705         }
20706
20707         // We reuse the value of GTF_REVERSE_OPS for a GT_IND-specific flag,
20708         // so exempt that (unary) operator.
20709         if (tree->OperGet() != GT_IND && tree->gtFlags & GTF_REVERSE_OPS)
20710         {
20711             /* Must have two operands if GTF_REVERSE is set */
20712             noway_assert(op1 && op2);
20713
20714             /* Make sure that the order of side effects has not been swapped. */
20715
20716             /* However CSE may introduce an assignment after the reverse flag
20717                was set and thus GTF_ASG cannot be considered here. */
20718
20719             /* For a GT_ASG(GT_IND(x), y) we are interested in the side effects of x */
20720             GenTreePtr op1p;
20721             if ((kind & GTK_ASGOP) && (op1->gtOper == GT_IND))
20722             {
20723                 op1p = op1->gtOp.gtOp1;
20724             }
20725             else
20726             {
20727                 op1p = op1;
20728             }
20729
20730             /* This isn't true any more with the sticky GTF_REVERSE */
20731             /*
20732             // if op1p has side effects, then op2 cannot have side effects
20733             if (op1p->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
20734             {
20735                 if (op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
20736                     gtDispTree(tree);
20737                 noway_assert(!(op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG)));
20738             }
20739             */
20740         }
20741
20742         if (kind & GTK_ASGOP)
20743         {
20744             chkFlags |= GTF_ASG;
20745         }
20746
20747         /* Note that it is OK for treeFlags not to have a GTF_EXCEPT,
20748            AssertionProp's non-Null may have cleared it */
20749         if (tree->OperMayThrow())
20750         {
20751             chkFlags |= (treeFlags & GTF_EXCEPT);
20752         }
20753
20754         if (oper == GT_ADDR && (op1->OperIsLocal() || op1->gtOper == GT_CLS_VAR ||
20755                                 (op1->gtOper == GT_IND && op1->gtOp.gtOp1->gtOper == GT_CLS_VAR_ADDR)))
20756         {
20757             /* &aliasedVar doesn't need GTF_GLOB_REF, though alisasedVar does.
20758                Similarly for clsVar */
20759             treeFlags |= GTF_GLOB_REF;
20760         }
20761     }
20762
20763     /* See what kind of a special operator we have here */
20764
20765     else
20766     {
20767         switch (tree->OperGet())
20768         {
20769             case GT_CALL:
20770
20771                 GenTreePtr   args;
20772                 GenTreePtr   argx;
20773                 GenTreeCall* call;
20774
20775                 call = tree->AsCall();
20776
20777                 chkFlags |= GTF_CALL;
20778
20779                 if ((treeFlags & GTF_EXCEPT) && !(chkFlags & GTF_EXCEPT))
20780                 {
20781                     switch (eeGetHelperNum(call->gtCallMethHnd))
20782                     {
20783                         // Is this a helper call that can throw an exception ?
20784                         case CORINFO_HELP_LDIV:
20785                         case CORINFO_HELP_LMOD:
20786                         case CORINFO_HELP_METHOD_ACCESS_CHECK:
20787                         case CORINFO_HELP_FIELD_ACCESS_CHECK:
20788                         case CORINFO_HELP_CLASS_ACCESS_CHECK:
20789                         case CORINFO_HELP_DELEGATE_SECURITY_CHECK:
20790                             chkFlags |= GTF_EXCEPT;
20791                             break;
20792                         default:
20793                             break;
20794                     }
20795                 }
20796
20797                 if (call->gtCallObjp)
20798                 {
20799                     fgDebugCheckFlags(call->gtCallObjp);
20800                     chkFlags |= (call->gtCallObjp->gtFlags & GTF_SIDE_EFFECT);
20801
20802                     if (call->gtCallObjp->gtFlags & GTF_ASG)
20803                     {
20804                         treeFlags |= GTF_ASG;
20805                     }
20806                 }
20807
20808                 for (args = call->gtCallArgs; args; args = args->gtOp.gtOp2)
20809                 {
20810                     argx = args->gtOp.gtOp1;
20811                     fgDebugCheckFlags(argx);
20812
20813                     chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT);
20814
20815                     if (argx->gtFlags & GTF_ASG)
20816                     {
20817                         treeFlags |= GTF_ASG;
20818                     }
20819                 }
20820
20821                 for (args = call->gtCallLateArgs; args; args = args->gtOp.gtOp2)
20822                 {
20823                     argx = args->gtOp.gtOp1;
20824                     fgDebugCheckFlags(argx);
20825
20826                     chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT);
20827
20828                     if (argx->gtFlags & GTF_ASG)
20829                     {
20830                         treeFlags |= GTF_ASG;
20831                     }
20832                 }
20833
20834                 if ((call->gtCallType == CT_INDIRECT) && (call->gtCallCookie != nullptr))
20835                 {
20836                     fgDebugCheckFlags(call->gtCallCookie);
20837                     chkFlags |= (call->gtCallCookie->gtFlags & GTF_SIDE_EFFECT);
20838                 }
20839
20840                 if (call->gtCallType == CT_INDIRECT)
20841                 {
20842                     fgDebugCheckFlags(call->gtCallAddr);
20843                     chkFlags |= (call->gtCallAddr->gtFlags & GTF_SIDE_EFFECT);
20844                 }
20845
20846                 if (call->IsUnmanaged() && (call->gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL))
20847                 {
20848                     if (call->gtCallArgs->gtOp.gtOp1->OperGet() == GT_NOP)
20849                     {
20850                         noway_assert(call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL ||
20851                                      call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF);
20852                     }
20853                     else
20854                     {
20855                         noway_assert(call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL ||
20856                                      call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF);
20857                     }
20858                 }
20859                 break;
20860
20861             case GT_ARR_ELEM:
20862
20863                 GenTreePtr arrObj;
20864                 unsigned   dim;
20865
20866                 arrObj = tree->gtArrElem.gtArrObj;
20867                 fgDebugCheckFlags(arrObj);
20868                 chkFlags |= (arrObj->gtFlags & GTF_ALL_EFFECT);
20869
20870                 for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
20871                 {
20872                     fgDebugCheckFlags(tree->gtArrElem.gtArrInds[dim]);
20873                     chkFlags |= tree->gtArrElem.gtArrInds[dim]->gtFlags & GTF_ALL_EFFECT;
20874                 }
20875                 break;
20876
20877             case GT_ARR_OFFSET:
20878                 fgDebugCheckFlags(tree->gtArrOffs.gtOffset);
20879                 chkFlags |= (tree->gtArrOffs.gtOffset->gtFlags & GTF_ALL_EFFECT);
20880                 fgDebugCheckFlags(tree->gtArrOffs.gtIndex);
20881                 chkFlags |= (tree->gtArrOffs.gtIndex->gtFlags & GTF_ALL_EFFECT);
20882                 fgDebugCheckFlags(tree->gtArrOffs.gtArrObj);
20883                 chkFlags |= (tree->gtArrOffs.gtArrObj->gtFlags & GTF_ALL_EFFECT);
20884                 break;
20885
20886             default:
20887                 break;
20888         }
20889     }
20890
20891     fgDebugCheckFlagsHelper(tree, treeFlags, chkFlags);
20892 }
20893
20894 //------------------------------------------------------------------------------
20895 // fgDebugCheckFlagsHelper : Check if all bits that are set in chkFlags are also set in treeFlags.
20896 //
20897 //
20898 // Arguments:
20899 //    tree  - Tree whose flags are being checked
20900 //    treeFlags - Actual flags on the tree
20901 //    chkFlags - Expected flags
20902 //
20903 // Note:
20904 //    Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled.
20905
20906 void Compiler::fgDebugCheckFlagsHelper(GenTreePtr tree, unsigned treeFlags, unsigned chkFlags)
20907 {
20908     if (chkFlags & ~treeFlags)
20909     {
20910         // Print the tree so we can see it in the log.
20911         printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
20912         GenTree::gtDispFlags(chkFlags & ~treeFlags, GTF_DEBUG_NONE);
20913         printf("\n");
20914         gtDispTree(tree);
20915
20916         noway_assert(!"Missing flags on tree");
20917
20918         // Print the tree again so we can see it right after we hook up the debugger.
20919         printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
20920         GenTree::gtDispFlags(chkFlags & ~treeFlags, GTF_DEBUG_NONE);
20921         printf("\n");
20922         gtDispTree(tree);
20923     }
20924     else if (treeFlags & ~chkFlags)
20925     {
20926 #if 0
20927         // TODO-Cleanup:
20928         /* The tree has extra flags set. However, this will happen if we
20929         replace a subtree with something, but don't clear the flags up
20930         the tree. Can't flag this unless we start clearing flags above.
20931
20932         Note: we need this working for GTF_CALL and CSEs, so I'm enabling
20933         it for calls.
20934         */
20935         if (tree->OperGet() != GT_CALL && (treeFlags & GTF_CALL) && !(chkFlags & GTF_CALL))
20936         {
20937             // Print the tree so we can see it in the log.
20938             printf("Extra GTF_CALL flags on parent tree [%X]: ", tree);
20939             GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE);
20940             printf("\n");
20941             gtDispTree(tree);
20942
20943             noway_assert(!"Extra flags on tree");
20944
20945             // Print the tree again so we can see it right after we hook up the debugger.
20946             printf("Extra GTF_CALL flags on parent tree [%X]: ", tree);
20947             GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE);
20948             printf("\n");
20949             gtDispTree(tree);
20950     }
20951 #endif // 0
20952     }
20953 }
20954
20955 // DEBUG routine to check correctness of the internal gtNext, gtPrev threading of a statement.
20956 // This threading is only valid when fgStmtListThreaded is true.
20957 // This calls an alternate method for FGOrderLinear.
20958 void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node)
20959 {
20960     // LIR blocks are checked using BasicBlock::CheckLIR().
20961     if (block->IsLIR())
20962     {
20963         LIR::AsRange(block).CheckLIR(this);
20964         // TODO: return?
20965     }
20966
20967     GenTreeStmt* stmt = node->AsStmt();
20968
20969     assert(fgStmtListThreaded);
20970
20971     noway_assert(stmt->gtStmtList);
20972
20973     // The first node's gtPrev must be nullptr (the gtPrev list is not circular).
20974     // The last node's gtNext must be nullptr (the gtNext list is not circular). This is tested if the loop below
20975     // terminates.
20976     assert(stmt->gtStmtList->gtPrev == nullptr);
20977
20978     for (GenTreePtr tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext)
20979     {
20980         if (tree->gtPrev)
20981         {
20982             noway_assert(tree->gtPrev->gtNext == tree);
20983         }
20984         else
20985         {
20986             noway_assert(tree == stmt->gtStmtList);
20987         }
20988
20989         if (tree->gtNext)
20990         {
20991             noway_assert(tree->gtNext->gtPrev == tree);
20992         }
20993         else
20994         {
20995             noway_assert(tree == stmt->gtStmtExpr);
20996         }
20997
20998         /* Cross-check gtPrev,gtNext with gtOp for simple trees */
20999
21000         GenTreePtr expectedPrevTree = nullptr;
21001
21002         if (tree->OperIsLeaf())
21003         {
21004             if (tree->gtOper == GT_CATCH_ARG)
21005             {
21006                 // The GT_CATCH_ARG should always have GTF_ORDER_SIDEEFF set
21007                 noway_assert(tree->gtFlags & GTF_ORDER_SIDEEFF);
21008                 // The GT_CATCH_ARG has to be the first thing evaluated
21009                 noway_assert(stmt == block->FirstNonPhiDef());
21010                 noway_assert(stmt->gtStmtList->gtOper == GT_CATCH_ARG);
21011                 // The root of the tree should have GTF_ORDER_SIDEEFF set
21012                 noway_assert(stmt->gtStmtExpr->gtFlags & GTF_ORDER_SIDEEFF);
21013             }
21014         }
21015
21016         if (tree->OperIsUnary() && tree->gtOp.gtOp1)
21017         {
21018             GenTreePtr lclVarTree;
21019             expectedPrevTree = tree->gtOp.gtOp1;
21020         }
21021         else if (tree->OperIsBinary() && tree->gtOp.gtOp1)
21022         {
21023             switch (tree->gtOper)
21024             {
21025                 case GT_QMARK:
21026                     expectedPrevTree =
21027                         tree->gtOp.gtOp2->AsColon()->ThenNode(); // "then" operand of the GT_COLON (generated second).
21028                     break;
21029
21030                 case GT_COLON:
21031                     expectedPrevTree = tree->AsColon()->ElseNode(); // "else" branch result (generated first).
21032                     break;
21033
21034                 default:
21035                     if (tree->gtOp.gtOp2)
21036                     {
21037                         if (tree->gtFlags & GTF_REVERSE_OPS)
21038                         {
21039                             expectedPrevTree = tree->gtOp.gtOp1;
21040                         }
21041                         else
21042                         {
21043                             expectedPrevTree = tree->gtOp.gtOp2;
21044                         }
21045                     }
21046                     else
21047                     {
21048                         expectedPrevTree = tree->gtOp.gtOp1;
21049                     }
21050                     break;
21051             }
21052         }
21053
21054         noway_assert(expectedPrevTree == nullptr ||     // No expectations about the prev node
21055                      tree->gtPrev == expectedPrevTree); // The "normal" case
21056     }
21057 }
21058
21059 /*****************************************************************************
21060  *
21061  * A DEBUG routine to check the correctness of the links between GT_STMT nodes
21062  * and ordinary nodes within a statement.
21063  *
21064  ****************************************************************************/
21065
21066 void Compiler::fgDebugCheckLinks(bool morphTrees)
21067 {
21068     // This used to be only on for stress, and there was a comment stating that
21069     // it was "quite an expensive operation" but I did not find that to be true.
21070     // Set DO_SANITY_DEBUG_CHECKS to false to revert to that behavior.
21071     const bool DO_SANITY_DEBUG_CHECKS = true;
21072
21073     if (!DO_SANITY_DEBUG_CHECKS && !compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))
21074     {
21075         return;
21076     }
21077
21078     fgDebugCheckBlockLinks();
21079
21080     /* For each basic block check the bbTreeList links */
21081     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
21082     {
21083     PROCESS_BLOCK_AGAIN:;
21084         if (block->IsLIR())
21085         {
21086             LIR::AsRange(block).CheckLIR(this);
21087         }
21088         else
21089         {
21090             for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
21091             {
21092                 /* Verify that bbTreeList is threaded correctly */
21093                 /* Note that for the GT_STMT list, the gtPrev list is circular. The gtNext list is not: gtNext of the
21094                  * last GT_STMT in a block is nullptr. */
21095
21096                 noway_assert(stmt->gtPrev);
21097
21098                 if (stmt == block->bbTreeList)
21099                 {
21100                     noway_assert(stmt->gtPrev->gtNext == nullptr);
21101                 }
21102                 else
21103                 {
21104                     noway_assert(stmt->gtPrev->gtNext == stmt);
21105                 }
21106
21107                 if (stmt->gtNext)
21108                 {
21109                     noway_assert(stmt->gtNext->gtPrev == stmt);
21110                 }
21111                 else
21112                 {
21113                     noway_assert(block->lastStmt() == stmt);
21114                 }
21115
21116                 /* For each statement check that the exception flags are properly set */
21117
21118                 noway_assert(stmt->gtStmtExpr);
21119
21120                 if (verbose && 0)
21121                 {
21122                     gtDispTree(stmt->gtStmtExpr);
21123                 }
21124
21125                 fgDebugCheckFlags(stmt->gtStmtExpr);
21126
21127                 // Not only will this stress fgMorphBlockStmt(), but we also get all the checks
21128                 // done by fgMorphTree()
21129
21130                 if (morphTrees)
21131                 {
21132                     // If 'stmt' is removed from the block, restart
21133                     if (fgMorphBlockStmt(block, stmt DEBUGARG("test morphing")))
21134                     {
21135                         goto PROCESS_BLOCK_AGAIN;
21136                     }
21137                 }
21138
21139                 /* For each GT_STMT node check that the nodes are threaded correcly - gtStmtList */
21140
21141                 if (fgStmtListThreaded)
21142                 {
21143                     fgDebugCheckNodeLinks(block, stmt);
21144                 }
21145             }
21146         }
21147     }
21148 }
21149
21150 // ensure that bbNext and bbPrev are consistent
21151 void Compiler::fgDebugCheckBlockLinks()
21152 {
21153     assert(fgFirstBB->bbPrev == nullptr);
21154
21155     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
21156     {
21157         if (block->bbNext)
21158         {
21159             assert(block->bbNext->bbPrev == block);
21160         }
21161         else
21162         {
21163             assert(block == fgLastBB);
21164         }
21165
21166         if (block->bbPrev)
21167         {
21168             assert(block->bbPrev->bbNext == block);
21169         }
21170         else
21171         {
21172             assert(block == fgFirstBB);
21173         }
21174
21175         // If this is a switch, check that the tables are consistent.
21176         // Note that we don't call GetSwitchDescMap(), because it has the side-effect
21177         // of allocating it if it is not present.
21178         if (block->bbJumpKind == BBJ_SWITCH && m_switchDescMap != nullptr)
21179         {
21180             SwitchUniqueSuccSet uniqueSuccSet;
21181             if (m_switchDescMap->Lookup(block, &uniqueSuccSet))
21182             {
21183                 // Create a set with all the successors. Don't use BlockSet, so we don't need to worry
21184                 // about the BlockSet epoch.
21185                 BitVecTraits bitVecTraits(fgBBNumMax + 1, this);
21186                 BitVec       BITVEC_INIT_NOCOPY(succBlocks, BitVecOps::MakeEmpty(&bitVecTraits));
21187                 BasicBlock** jumpTable = block->bbJumpSwt->bbsDstTab;
21188                 unsigned     jumpCount = block->bbJumpSwt->bbsCount;
21189                 for (unsigned i = 0; i < jumpCount; i++)
21190                 {
21191                     BitVecOps::AddElemD(&bitVecTraits, succBlocks, jumpTable[i]->bbNum);
21192                 }
21193                 // Now we should have a set of unique successors that matches what's in the switchMap.
21194                 // First, check the number of entries, then make sure all the blocks in uniqueSuccSet
21195                 // are in the BlockSet.
21196                 unsigned count = BitVecOps::Count(&bitVecTraits, succBlocks);
21197                 assert(uniqueSuccSet.numDistinctSuccs == count);
21198                 for (unsigned i = 0; i < uniqueSuccSet.numDistinctSuccs; i++)
21199                 {
21200                     assert(BitVecOps::IsMember(&bitVecTraits, succBlocks, uniqueSuccSet.nonDuplicates[i]->bbNum));
21201                 }
21202             }
21203         }
21204     }
21205 }
21206
21207 /*****************************************************************************/
21208 #endif // DEBUG
21209 /*****************************************************************************/
21210
21211 //------------------------------------------------------------------------
21212 // fgCheckForInlineDepthAndRecursion: compute depth of the candidate, and
21213 // check for recursion.
21214 //
21215 // Return Value:
21216 //    The depth of the inline candidate. The root method is a depth 0, top-level
21217 //    candidates at depth 1, etc.
21218 //
21219 // Notes:
21220 //    We generally disallow recursive inlines by policy. However, they are
21221 //    supported by the underlying machinery.
21222 //
21223 //    Likewise the depth limit is a policy consideration, and serves mostly
21224 //    as a safeguard to prevent runaway inlining of small methods.
21225
21226 unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo)
21227 {
21228     BYTE*          candidateCode = inlineInfo->inlineCandidateInfo->methInfo.ILCode;
21229     InlineContext* inlineContext = inlineInfo->iciStmt->gtInlineContext;
21230     InlineResult*  inlineResult  = inlineInfo->inlineResult;
21231
21232     // There should be a context for all candidates.
21233     assert(inlineContext != nullptr);
21234     int depth = 0;
21235
21236     for (; inlineContext != nullptr; inlineContext = inlineContext->GetParent())
21237     {
21238
21239         depth++;
21240
21241         if (inlineContext->GetCode() == candidateCode)
21242         {
21243             // This inline candidate has the same IL code buffer as an already
21244             // inlined method does.
21245             inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_RECURSIVE);
21246             break;
21247         }
21248
21249         if (depth > InlineStrategy::IMPLEMENTATION_MAX_INLINE_DEPTH)
21250         {
21251             break;
21252         }
21253     }
21254
21255     inlineResult->NoteInt(InlineObservation::CALLSITE_DEPTH, depth);
21256     return depth;
21257 }
21258
21259 /*****************************************************************************
21260  *
21261  *  Inlining phase
21262  */
21263
21264 void Compiler::fgInline()
21265 {
21266     if (!opts.OptEnabled(CLFLG_INLINING))
21267     {
21268         return;
21269     }
21270
21271 #ifdef DEBUG
21272     if (verbose)
21273     {
21274         printf("*************** In fgInline()\n");
21275     }
21276 #endif // DEBUG
21277
21278     BasicBlock* block = fgFirstBB;
21279     noway_assert(block != nullptr);
21280
21281     // Set the root inline context on all statements
21282     InlineContext* rootContext = m_inlineStrategy->GetRootContext();
21283
21284     for (; block != nullptr; block = block->bbNext)
21285     {
21286         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
21287         {
21288             stmt->gtInlineContext = rootContext;
21289         }
21290     }
21291
21292     // Reset block back to start for inlining
21293     block = fgFirstBB;
21294
21295     do
21296     {
21297         /* Make the current basic block address available globally */
21298
21299         compCurBB = block;
21300
21301         GenTreeStmt* stmt;
21302         GenTreePtr   expr;
21303
21304         for (stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
21305         {
21306             expr = stmt->gtStmtExpr;
21307
21308             // See if we can expand the inline candidate
21309             if ((expr->gtOper == GT_CALL) && ((expr->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0))
21310             {
21311                 GenTreeCall* call = expr->AsCall();
21312                 InlineResult inlineResult(this, call, stmt, "fgInline");
21313
21314                 fgMorphStmt = stmt;
21315
21316                 fgMorphCallInline(call, &inlineResult);
21317
21318                 if (stmt->gtStmtExpr->IsNothingNode())
21319                 {
21320                     fgRemoveStmt(block, stmt);
21321                     continue;
21322                 }
21323             }
21324             else
21325             {
21326 #ifdef DEBUG
21327                 // Look for non-candidates.
21328                 fgWalkTreePre(&stmt->gtStmtExpr, fgFindNonInlineCandidate, stmt);
21329 #endif
21330             }
21331
21332             // See if we need to replace the return value place holder.
21333             // Also, see if this update enables further devirtualization.
21334             fgWalkTreePre(&stmt->gtStmtExpr, fgUpdateInlineReturnExpressionPlaceHolder, (void*)this);
21335
21336             // See if stmt is of the form GT_COMMA(call, nop)
21337             // If yes, we can get rid of GT_COMMA.
21338             if (expr->OperGet() == GT_COMMA && expr->gtOp.gtOp1->OperGet() == GT_CALL &&
21339                 expr->gtOp.gtOp2->OperGet() == GT_NOP)
21340             {
21341                 stmt->gtStmtExpr = expr->gtOp.gtOp1;
21342             }
21343         }
21344
21345         block = block->bbNext;
21346
21347     } while (block);
21348
21349 #ifdef DEBUG
21350
21351     // Check that we should not have any inline candidate or return value place holder left.
21352
21353     block = fgFirstBB;
21354     noway_assert(block);
21355
21356     do
21357     {
21358         GenTreeStmt* stmt;
21359
21360         for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
21361         {
21362             // Call Compiler::fgDebugCheckInlineCandidates on each node
21363             fgWalkTreePre(&stmt->gtStmtExpr, fgDebugCheckInlineCandidates);
21364         }
21365
21366         block = block->bbNext;
21367
21368     } while (block);
21369
21370     fgVerifyHandlerTab();
21371
21372     if (verbose)
21373     {
21374         printf("*************** After fgInline()\n");
21375         fgDispBasicBlocks(true);
21376         fgDispHandlerTab();
21377     }
21378
21379     if (verbose || fgPrintInlinedMethods)
21380     {
21381         printf("**************** Inline Tree\n");
21382         m_inlineStrategy->Dump();
21383     }
21384
21385 #endif // DEBUG
21386 }
21387
21388 #ifdef DEBUG
21389
21390 //------------------------------------------------------------------------
21391 // fgFindNonInlineCandidate: tree walk helper to ensure that a tree node
21392 // that is not an inline candidate is noted as a failed inline.
21393 //
21394 // Arguments:
21395 //    pTree - pointer to pointer tree node being walked
21396 //    data  - contextual data for the walk
21397 //
21398 // Return Value:
21399 //    walk result
21400 //
21401 // Note:
21402 //    Invokes fgNoteNonInlineCandidate on the nodes it finds.
21403
21404 Compiler::fgWalkResult Compiler::fgFindNonInlineCandidate(GenTreePtr* pTree, fgWalkData* data)
21405 {
21406     GenTreePtr tree = *pTree;
21407     if (tree->gtOper == GT_CALL)
21408     {
21409         Compiler*    compiler = data->compiler;
21410         GenTreeStmt* stmt     = (GenTreeStmt*)data->pCallbackData;
21411         GenTreeCall* call     = tree->AsCall();
21412
21413         compiler->fgNoteNonInlineCandidate(stmt, call);
21414     }
21415     return WALK_CONTINUE;
21416 }
21417
21418 //------------------------------------------------------------------------
21419 // fgNoteNonInlineCandidate: account for inlining failures in calls
21420 // not marked as inline candidates.
21421 //
21422 // Arguments:
21423 //    stmt  - statement containing the call
21424 //    call  - the call itself
21425 //
21426 // Notes:
21427 //    Used in debug only to try and place descriptions of inline failures
21428 //    into the proper context in the inline tree.
21429
21430 void Compiler::fgNoteNonInlineCandidate(GenTreeStmt* stmt, GenTreeCall* call)
21431 {
21432     InlineResult      inlineResult(this, call, nullptr, "fgNotInlineCandidate");
21433     InlineObservation currentObservation = InlineObservation::CALLSITE_NOT_CANDIDATE;
21434
21435     // Try and recover the reason left behind when the jit decided
21436     // this call was not a candidate.
21437     InlineObservation priorObservation = call->gtInlineObservation;
21438
21439     if (InlIsValidObservation(priorObservation))
21440     {
21441         currentObservation = priorObservation;
21442     }
21443
21444     // Would like to just call noteFatal here, since this
21445     // observation blocked candidacy, but policy comes into play
21446     // here too.  Also note there's no need to re-report these
21447     // failures, since we reported them during the initial
21448     // candidate scan.
21449     InlineImpact impact = InlGetImpact(currentObservation);
21450
21451     if (impact == InlineImpact::FATAL)
21452     {
21453         inlineResult.NoteFatal(currentObservation);
21454     }
21455     else
21456     {
21457         inlineResult.Note(currentObservation);
21458     }
21459
21460     inlineResult.SetReported();
21461
21462     if (call->gtCallType == CT_USER_FUNC)
21463     {
21464         // Create InlineContext for the failure
21465         m_inlineStrategy->NewFailure(stmt, &inlineResult);
21466     }
21467 }
21468
21469 #endif
21470
21471 #if FEATURE_MULTIREG_RET
21472
21473 /*********************************************************************************
21474  *
21475  * tree - The node which needs to be converted to a struct pointer.
21476  *
21477  *  Return the pointer by either __replacing__ the tree node with a suitable pointer
21478  *  type or __without replacing__ and just returning a subtree or by __modifying__
21479  *  a subtree.
21480  */
21481 GenTreePtr Compiler::fgGetStructAsStructPtr(GenTreePtr tree)
21482 {
21483     noway_assert((tree->gtOper == GT_LCL_VAR) || (tree->gtOper == GT_FIELD) || (tree->gtOper == GT_IND) ||
21484                  (tree->gtOper == GT_BLK) || (tree->gtOper == GT_OBJ) || tree->OperIsSIMD() ||
21485                  // tree->gtOper == GT_CALL     || cannot get address of call.
21486                  // tree->gtOper == GT_MKREFANY || inlining should've been aborted due to mkrefany opcode.
21487                  // tree->gtOper == GT_RET_EXPR || cannot happen after fgUpdateInlineReturnExpressionPlaceHolder
21488                  (tree->gtOper == GT_COMMA));
21489
21490     switch (tree->OperGet())
21491     {
21492         case GT_BLK:
21493         case GT_OBJ:
21494         case GT_IND:
21495             return tree->gtOp.gtOp1;
21496
21497         case GT_COMMA:
21498             tree->gtOp.gtOp2 = fgGetStructAsStructPtr(tree->gtOp.gtOp2);
21499             tree->gtType     = TYP_BYREF;
21500             return tree;
21501
21502         default:
21503             return gtNewOperNode(GT_ADDR, TYP_BYREF, tree);
21504     }
21505 }
21506
21507 /***************************************************************************************************
21508  * child     - The inlinee of the retExpr node.
21509  * retClsHnd - The struct class handle of the type of the inlinee.
21510  *
21511  * Assign the inlinee to a tmp, if it is a call, just assign it to a lclVar, else we can
21512  * use a copyblock to do the assignment.
21513  */
21514 GenTreePtr Compiler::fgAssignStructInlineeToVar(GenTreePtr child, CORINFO_CLASS_HANDLE retClsHnd)
21515 {
21516     assert(child->gtOper != GT_RET_EXPR && child->gtOper != GT_MKREFANY);
21517
21518     unsigned tmpNum = lvaGrabTemp(false DEBUGARG("RetBuf for struct inline return candidates."));
21519     lvaSetStruct(tmpNum, retClsHnd, false);
21520     var_types structType = lvaTable[tmpNum].lvType;
21521
21522     GenTreePtr dst = gtNewLclvNode(tmpNum, structType);
21523
21524     // If we have a call, we'd like it to be: V00 = call(), but first check if
21525     // we have a ", , , call()" -- this is very defensive as we may never get
21526     // an inlinee that is made of commas. If the inlinee is not a call, then
21527     // we use a copy block to do the assignment.
21528     GenTreePtr src       = child;
21529     GenTreePtr lastComma = nullptr;
21530     while (src->gtOper == GT_COMMA)
21531     {
21532         lastComma = src;
21533         src       = src->gtOp.gtOp2;
21534     }
21535
21536     GenTreePtr newInlinee = nullptr;
21537     if (src->gtOper == GT_CALL)
21538     {
21539         // If inlinee was just a call, new inlinee is v05 = call()
21540         newInlinee = gtNewAssignNode(dst, src);
21541
21542         // When returning a multi-register value in a local var, make sure the variable is
21543         // marked as lvIsMultiRegRet, so it does not get promoted.
21544         if (src->AsCall()->HasMultiRegRetVal())
21545         {
21546             lvaTable[tmpNum].lvIsMultiRegRet = true;
21547         }
21548
21549         // If inlinee was comma, but a deeper call, new inlinee is (, , , v05 = call())
21550         if (child->gtOper == GT_COMMA)
21551         {
21552             lastComma->gtOp.gtOp2 = newInlinee;
21553             newInlinee            = child;
21554         }
21555     }
21556     else
21557     {
21558         // Inlinee is not a call, so just create a copy block to the tmp.
21559         src                = child;
21560         GenTreePtr dstAddr = fgGetStructAsStructPtr(dst);
21561         GenTreePtr srcAddr = fgGetStructAsStructPtr(src);
21562         newInlinee         = gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false);
21563     }
21564
21565     GenTreePtr production = gtNewLclvNode(tmpNum, structType);
21566     return gtNewOperNode(GT_COMMA, structType, newInlinee, production);
21567 }
21568
21569 /***************************************************************************************************
21570  * tree      - The tree pointer that has one of its child nodes as retExpr.
21571  * child     - The inlinee child.
21572  * retClsHnd - The struct class handle of the type of the inlinee.
21573  *
21574  * V04 = call() assignments are okay as we codegen it. Everything else needs to be a copy block or
21575  * would need a temp. For example, a cast(ldobj) will then be, cast(v05 = ldobj, v05); But it is
21576  * a very rare (or impossible) scenario that we'd have a retExpr transform into a ldobj other than
21577  * a lclVar/call. So it is not worthwhile to do pattern matching optimizations like addr(ldobj(op1))
21578  * can just be op1.
21579  */
21580 void Compiler::fgAttachStructInlineeToAsg(GenTreePtr tree, GenTreePtr child, CORINFO_CLASS_HANDLE retClsHnd)
21581 {
21582     // We are okay to have:
21583     // 1. V02 = call();
21584     // 2. copyBlk(dstAddr, srcAddr);
21585     assert(tree->gtOper == GT_ASG);
21586
21587     // We have an assignment, we codegen only V05 = call().
21588     // However, if it is a multireg return on x64/ux we want to assign it to a temp.
21589     if (child->gtOper == GT_CALL && tree->gtOp.gtOp1->gtOper == GT_LCL_VAR && !child->AsCall()->HasMultiRegRetVal())
21590     {
21591         return;
21592     }
21593
21594     GenTreePtr dstAddr = fgGetStructAsStructPtr(tree->gtOp.gtOp1);
21595     GenTreePtr srcAddr = fgGetStructAsStructPtr(
21596         (child->gtOper == GT_CALL)
21597             ? fgAssignStructInlineeToVar(child, retClsHnd) // Assign to a variable if it is a call.
21598             : child);                                      // Just get the address, if not a call.
21599
21600     tree->CopyFrom(gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false), this);
21601 }
21602
21603 #endif // FEATURE_MULTIREG_RET
21604
21605 //------------------------------------------------------------------------
21606 // fgUpdateInlineReturnExpressionPlaceHolder: callback to replace the
21607 // inline return expression placeholder.
21608 //
21609 // Arguments:
21610 //    pTree -- pointer to tree to examine for updates
21611 //    data  -- context data for the tree walk
21612 //
21613 // Returns:
21614 //    fgWalkResult indicating the walk should continue; that
21615 //    is we wish to fully explore the tree.
21616 //
21617 // Notes:
21618 //    Looks for GT_RET_EXPR nodes that arose from tree splitting done
21619 //    during importation for inline candidates, and replaces them.
21620 //
21621 //    For successful inlines, substitutes the return value expression
21622 //    from the inline body for the GT_RET_EXPR.
21623 //
21624 //    For failed inlines, rejoins the original call into the tree from
21625 //    whence it was split during importation.
21626 //
21627 //    The code doesn't actually know if the corresponding inline
21628 //    succeeded or not; it relies on the fact that gtInlineCandidate
21629 //    initially points back at the call and is modified in place to
21630 //    the inlinee return expression if the inline is successful (see
21631 //    tail end of fgInsertInlineeBlocks for the update of iciCall).
21632 //
21633 //    If the parent of the GT_RET_EXPR is a virtual call,
21634 //    devirtualization is attempted. This should only succeed in the
21635 //    successful inline case, when the inlinee's return value
21636 //    expression provides a better type than the return type of the
21637 //    method. Note for failed inlines, the devirtualizer can only go
21638 //    by the return type, and any devirtualization that type enabled
21639 //    would have already happened during importation.
21640 //
21641 //    If the return type is a struct type and we're on a platform
21642 //    where structs can be returned in multiple registers, ensure the
21643 //    call has a suitable parent.
21644
21645 Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTreePtr* pTree, fgWalkData* data)
21646 {
21647     GenTreePtr           tree      = *pTree;
21648     Compiler*            comp      = data->compiler;
21649     CORINFO_CLASS_HANDLE retClsHnd = NO_CLASS_HANDLE;
21650
21651     if (tree->gtOper == GT_RET_EXPR)
21652     {
21653         // We are going to copy the tree from the inlinee,
21654         // so record the handle now.
21655         //
21656         if (varTypeIsStruct(tree))
21657         {
21658             retClsHnd = tree->gtRetExpr.gtRetClsHnd;
21659         }
21660
21661         do
21662         {
21663             // Obtained the expanded inline candidate
21664             GenTreePtr inlineCandidate = tree->gtRetExpr.gtInlineCandidate;
21665
21666 #ifdef DEBUG
21667             if (comp->verbose)
21668             {
21669                 printf("\nReplacing the return expression placeholder ");
21670                 printTreeID(tree);
21671                 printf(" with ");
21672                 printTreeID(inlineCandidate);
21673                 printf("\n");
21674                 // Dump out the old return expression placeholder it will be overwritten by the CopyFrom below
21675                 comp->gtDispTree(tree);
21676             }
21677 #endif // DEBUG
21678
21679             tree->CopyFrom(inlineCandidate, comp);
21680
21681 #ifdef DEBUG
21682             if (comp->verbose)
21683             {
21684                 printf("\nInserting the inline return expression\n");
21685                 comp->gtDispTree(tree);
21686                 printf("\n");
21687             }
21688 #endif // DEBUG
21689         } while (tree->gtOper == GT_RET_EXPR);
21690
21691         // Now see if this return value expression feeds the 'this'
21692         // object at a virtual call site.
21693         //
21694         // Note for void returns where the inline failed, the
21695         // GT_RET_EXPR may be top-level.
21696         //
21697         // May miss cases where there are intermediaries between call
21698         // and this, eg commas.
21699         GenTreePtr parentTree = data->parent;
21700
21701         if ((parentTree != nullptr) && (parentTree->gtOper == GT_CALL))
21702         {
21703             GenTreeCall* call          = parentTree->AsCall();
21704             bool         tryLateDevirt = call->IsVirtual() && (call->gtCallObjp == tree);
21705
21706 #ifdef DEBUG
21707             tryLateDevirt = tryLateDevirt && (JitConfig.JitEnableLateDevirtualization() == 1);
21708 #endif // DEBUG
21709
21710             if (tryLateDevirt)
21711             {
21712 #ifdef DEBUG
21713                 if (comp->verbose)
21714                 {
21715                     printf("**** Late devirt opportunity\n");
21716                     comp->gtDispTree(call);
21717                 }
21718 #endif // DEBUG
21719
21720                 CORINFO_CALL_INFO x = {};
21721                 x.hMethod           = call->gtCallMethHnd;
21722                 comp->impDevirtualizeCall(call, tree, &x, nullptr);
21723             }
21724         }
21725     }
21726
21727 #if FEATURE_MULTIREG_RET
21728
21729     // Did we record a struct return class handle above?
21730     //
21731     if (retClsHnd != NO_CLASS_HANDLE)
21732     {
21733         // Is this a type that is returned in multiple registers?
21734         // if so we need to force into into a form we accept.
21735         // i.e. LclVar = call()
21736         //
21737         if (comp->IsMultiRegReturnedType(retClsHnd))
21738         {
21739             GenTreePtr parent = data->parent;
21740             // See assert below, we only look one level above for an asg parent.
21741             if (parent->gtOper == GT_ASG)
21742             {
21743                 // Either lhs is a call V05 = call(); or lhs is addr, and asg becomes a copyBlk.
21744                 comp->fgAttachStructInlineeToAsg(parent, tree, retClsHnd);
21745             }
21746             else
21747             {
21748                 // Just assign the inlinee to a variable to keep it simple.
21749                 tree->CopyFrom(comp->fgAssignStructInlineeToVar(tree, retClsHnd), comp);
21750             }
21751         }
21752     }
21753
21754 #if defined(DEBUG)
21755
21756     // Make sure we don't have a tree like so: V05 = (, , , retExpr);
21757     // Since we only look one level above for the parent for '=' and
21758     // do not check if there is a series of COMMAs. See above.
21759     // Importer and FlowGraph will not generate such a tree, so just
21760     // leaving an assert in here. This can be fixed by looking ahead
21761     // when we visit GT_ASG similar to fgAttachStructInlineeToAsg.
21762     //
21763     if ((tree->gtOper == GT_ASG) && (tree->gtOp.gtOp2->gtOper == GT_COMMA))
21764     {
21765         GenTreePtr comma;
21766         for (comma = tree->gtOp.gtOp2; comma->gtOper == GT_COMMA; comma = comma->gtOp.gtOp2)
21767         {
21768             // empty
21769         }
21770
21771         noway_assert(!varTypeIsStruct(comma) || comma->gtOper != GT_RET_EXPR ||
21772                      !comp->IsMultiRegReturnedType(comma->gtRetExpr.gtRetClsHnd));
21773     }
21774
21775 #endif // defined(DEBUG)
21776 #endif // FEATURE_MULTIREG_RET
21777
21778     return WALK_CONTINUE;
21779 }
21780
21781 #ifdef DEBUG
21782
21783 /*****************************************************************************
21784  * Callback to make sure there is no more GT_RET_EXPR and GTF_CALL_INLINE_CANDIDATE nodes.
21785  */
21786
21787 /* static */
21788 Compiler::fgWalkResult Compiler::fgDebugCheckInlineCandidates(GenTreePtr* pTree, fgWalkData* data)
21789 {
21790     GenTreePtr tree = *pTree;
21791     if (tree->gtOper == GT_CALL)
21792     {
21793         assert((tree->gtFlags & GTF_CALL_INLINE_CANDIDATE) == 0);
21794     }
21795     else
21796     {
21797         assert(tree->gtOper != GT_RET_EXPR);
21798     }
21799
21800     return WALK_CONTINUE;
21801 }
21802
21803 #endif // DEBUG
21804
21805 void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineResult)
21806 {
21807     noway_assert(call->gtOper == GT_CALL);
21808     noway_assert((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0);
21809     noway_assert(opts.OptEnabled(CLFLG_INLINING));
21810
21811     // This is the InlineInfo struct representing a method to be inlined.
21812     InlineInfo inlineInfo;
21813     memset(&inlineInfo, 0, sizeof(inlineInfo));
21814     CORINFO_METHOD_HANDLE fncHandle = call->gtCallMethHnd;
21815
21816     inlineInfo.fncHandle             = fncHandle;
21817     inlineInfo.iciCall               = call;
21818     inlineInfo.iciStmt               = fgMorphStmt;
21819     inlineInfo.iciBlock              = compCurBB;
21820     inlineInfo.thisDereferencedFirst = false;
21821     inlineInfo.retExpr               = nullptr;
21822     inlineInfo.inlineResult          = inlineResult;
21823 #ifdef FEATURE_SIMD
21824     inlineInfo.hasSIMDTypeArgLocalOrReturn = false;
21825 #endif // FEATURE_SIMD
21826
21827     InlineCandidateInfo* inlineCandidateInfo = call->gtInlineCandidateInfo;
21828     noway_assert(inlineCandidateInfo);
21829     // Store the link to inlineCandidateInfo into inlineInfo
21830     inlineInfo.inlineCandidateInfo = inlineCandidateInfo;
21831
21832     unsigned inlineDepth = fgCheckInlineDepthAndRecursion(&inlineInfo);
21833
21834     if (inlineResult->IsFailure())
21835     {
21836 #ifdef DEBUG
21837         if (verbose)
21838         {
21839             printf("Recursive or deep inline recursion detected. Will not expand this INLINECANDIDATE \n");
21840         }
21841 #endif // DEBUG
21842         return;
21843     }
21844
21845     // Set the trap to catch all errors (including recoverable ones from the EE)
21846     struct Param
21847     {
21848         Compiler*             pThis;
21849         GenTree*              call;
21850         CORINFO_METHOD_HANDLE fncHandle;
21851         InlineCandidateInfo*  inlineCandidateInfo;
21852         InlineInfo*           inlineInfo;
21853     } param;
21854     memset(&param, 0, sizeof(param));
21855
21856     param.pThis               = this;
21857     param.call                = call;
21858     param.fncHandle           = fncHandle;
21859     param.inlineCandidateInfo = inlineCandidateInfo;
21860     param.inlineInfo          = &inlineInfo;
21861     bool success              = eeRunWithErrorTrap<Param>(
21862         [](Param* pParam) {
21863             // Init the local var info of the inlinee
21864             pParam->pThis->impInlineInitVars(pParam->inlineInfo);
21865
21866             if (pParam->inlineInfo->inlineResult->IsCandidate())
21867             {
21868                 /* Clear the temp table */
21869                 memset(pParam->inlineInfo->lclTmpNum, -1, sizeof(pParam->inlineInfo->lclTmpNum));
21870
21871                 //
21872                 // Prepare the call to jitNativeCode
21873                 //
21874
21875                 pParam->inlineInfo->InlinerCompiler = pParam->pThis;
21876                 if (pParam->pThis->impInlineInfo == nullptr)
21877                 {
21878                     pParam->inlineInfo->InlineRoot = pParam->pThis;
21879                 }
21880                 else
21881                 {
21882                     pParam->inlineInfo->InlineRoot = pParam->pThis->impInlineInfo->InlineRoot;
21883                 }
21884                 pParam->inlineInfo->argCnt                   = pParam->inlineCandidateInfo->methInfo.args.totalILArgs();
21885                 pParam->inlineInfo->tokenLookupContextHandle = pParam->inlineCandidateInfo->exactContextHnd;
21886
21887                 JITLOG_THIS(pParam->pThis,
21888                             (LL_INFO100000, "INLINER: inlineInfo.tokenLookupContextHandle for %s set to 0x%p:\n",
21889                              pParam->pThis->eeGetMethodFullName(pParam->fncHandle),
21890                              pParam->pThis->dspPtr(pParam->inlineInfo->tokenLookupContextHandle)));
21891
21892                 JitFlags compileFlagsForInlinee = *pParam->pThis->opts.jitFlags;
21893
21894                 // The following flags are lost when inlining.
21895                 // (This is checked in Compiler::compInitOptions().)
21896                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_BBOPT);
21897                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_BBINSTR);
21898                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_PROF_ENTERLEAVE);
21899                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_EnC);
21900                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_INFO);
21901
21902                 compileFlagsForInlinee.Set(JitFlags::JIT_FLAG_SKIP_VERIFICATION);
21903
21904 #ifdef DEBUG
21905                 if (pParam->pThis->verbose)
21906                 {
21907                     printf("\nInvoking compiler for the inlinee method %s :\n",
21908                            pParam->pThis->eeGetMethodFullName(pParam->fncHandle));
21909                 }
21910 #endif // DEBUG
21911
21912                 int result =
21913                     jitNativeCode(pParam->fncHandle, pParam->inlineCandidateInfo->methInfo.scope,
21914                                   pParam->pThis->info.compCompHnd, &pParam->inlineCandidateInfo->methInfo,
21915                                   (void**)pParam->inlineInfo, nullptr, &compileFlagsForInlinee, pParam->inlineInfo);
21916
21917                 if (result != CORJIT_OK)
21918                 {
21919                     // If we haven't yet determined why this inline fails, use
21920                     // a catch-all something bad happened observation.
21921                     InlineResult* innerInlineResult = pParam->inlineInfo->inlineResult;
21922
21923                     if (!innerInlineResult->IsFailure())
21924                     {
21925                         innerInlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_FAILURE);
21926                     }
21927                 }
21928             }
21929         },
21930         &param);
21931     if (!success)
21932     {
21933 #ifdef DEBUG
21934         if (verbose)
21935         {
21936             printf("\nInlining failed due to an exception during invoking the compiler for the inlinee method %s.\n",
21937                    eeGetMethodFullName(fncHandle));
21938         }
21939 #endif // DEBUG
21940
21941         // If we haven't yet determined why this inline fails, use
21942         // a catch-all something bad happened observation.
21943         if (!inlineResult->IsFailure())
21944         {
21945             inlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_ERROR);
21946         }
21947     }
21948
21949     if (inlineResult->IsFailure())
21950     {
21951         return;
21952     }
21953
21954 #ifdef DEBUG
21955     if (0 && verbose)
21956     {
21957         printf("\nDone invoking compiler for the inlinee method %s\n", eeGetMethodFullName(fncHandle));
21958     }
21959 #endif // DEBUG
21960
21961     // If there is non-NULL return, but we haven't set the pInlineInfo->retExpr,
21962     // That means we haven't imported any BB that contains CEE_RET opcode.
21963     // (This could happen for example for a BBJ_THROW block fall through a BBJ_RETURN block which
21964     // causes the BBJ_RETURN block not to be imported at all.)
21965     // Fail the inlining attempt
21966     if (inlineCandidateInfo->fncRetType != TYP_VOID && inlineInfo.retExpr == nullptr)
21967     {
21968 #ifdef DEBUG
21969         if (verbose)
21970         {
21971             printf("\nInlining failed because pInlineInfo->retExpr is not set in the inlinee method %s.\n",
21972                    eeGetMethodFullName(fncHandle));
21973         }
21974 #endif // DEBUG
21975         inlineResult->NoteFatal(InlineObservation::CALLEE_LACKS_RETURN);
21976         return;
21977     }
21978
21979     if (inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_SPECULATIVE)
21980     {
21981         // we defer the call to initClass() until inlining is completed in case it fails. If inlining succeeds,
21982         // we will call initClass().
21983         if (!(info.compCompHnd->initClass(nullptr /* field */, fncHandle /* method */,
21984                                           inlineCandidateInfo->exactContextHnd /* context */) &
21985               CORINFO_INITCLASS_INITIALIZED))
21986         {
21987             inlineResult->NoteFatal(InlineObservation::CALLEE_CLASS_INIT_FAILURE);
21988             return;
21989         }
21990     }
21991
21992     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21993     // The inlining attempt cannot be failed starting from this point.
21994     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21995
21996     // We've successfully obtain the list of inlinee's basic blocks.
21997     // Let's insert it to inliner's basic block list.
21998     fgInsertInlineeBlocks(&inlineInfo);
21999
22000 #ifdef DEBUG
22001
22002     if (verbose || fgPrintInlinedMethods)
22003     {
22004         printf("Successfully inlined %s (%d IL bytes) (depth %d) [%s]\n", eeGetMethodFullName(fncHandle),
22005                inlineCandidateInfo->methInfo.ILCodeSize, inlineDepth, inlineResult->ReasonString());
22006     }
22007
22008     if (verbose)
22009     {
22010         printf("--------------------------------------------------------------------------------------------\n");
22011     }
22012 #endif // DEBUG
22013
22014 #if defined(DEBUG)
22015     impInlinedCodeSize += inlineCandidateInfo->methInfo.ILCodeSize;
22016 #endif
22017
22018     // We inlined...
22019     inlineResult->NoteSuccess();
22020 }
22021
22022 //------------------------------------------------------------------------
22023 // fgInsertInlineeBlocks: incorporate statements for an inline into the
22024 // root method.
22025 //
22026 // Arguments:
22027 //    inlineInfo -- info for the inline
22028 //
22029 // Notes:
22030 //    The inlining attempt cannot be failed once this method is called.
22031 //
22032 //    Adds all inlinee statements, plus any glue statements needed
22033 //    either before or after the inlined call.
22034 //
22035 //    Updates flow graph and assigns weights to inlinee
22036 //    blocks. Currently does not attempt to read IBC data for the
22037 //    inlinee.
22038 //
22039 //    Updates relevant root method status flags (eg optMethodFlags) to
22040 //    include information from the inlinee.
22041 //
22042 //    Marks newly added statements with an appropriate inline context.
22043
22044 void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo)
22045 {
22046     GenTreeCall* iciCall  = pInlineInfo->iciCall;
22047     GenTreeStmt* iciStmt  = pInlineInfo->iciStmt;
22048     BasicBlock*  iciBlock = pInlineInfo->iciBlock;
22049     BasicBlock*  block;
22050
22051     // We can write better assert here. For example, we can check that
22052     // iciBlock contains iciStmt, which in turn contains iciCall.
22053     noway_assert(iciBlock->bbTreeList != nullptr);
22054     noway_assert(iciStmt->gtStmtExpr != nullptr);
22055     noway_assert(iciCall->gtOper == GT_CALL);
22056
22057 #ifdef DEBUG
22058
22059     GenTreePtr currentDumpStmt = nullptr;
22060
22061     if (verbose)
22062     {
22063         printf("\n\n----------- Statements (and blocks) added due to the inlining of call ");
22064         printTreeID(iciCall);
22065         printf(" -----------\n");
22066     }
22067
22068 #endif // DEBUG
22069
22070     // Create a new inline context and mark the inlined statements with it
22071     InlineContext* calleeContext = m_inlineStrategy->NewSuccess(pInlineInfo);
22072
22073     for (block = InlineeCompiler->fgFirstBB; block != nullptr; block = block->bbNext)
22074     {
22075         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
22076         {
22077             stmt->gtInlineContext = calleeContext;
22078         }
22079     }
22080
22081     // Prepend statements
22082     GenTreePtr stmtAfter = fgInlinePrependStatements(pInlineInfo);
22083
22084 #ifdef DEBUG
22085     if (verbose)
22086     {
22087         currentDumpStmt = stmtAfter;
22088         printf("\nInlinee method body:");
22089     }
22090 #endif // DEBUG
22091
22092     BasicBlock* topBlock    = iciBlock;
22093     BasicBlock* bottomBlock = nullptr;
22094
22095     if (InlineeCompiler->fgBBcount == 1)
22096     {
22097         // When fgBBCount is 1 we will always have a non-NULL fgFirstBB
22098         //
22099         PREFAST_ASSUME(InlineeCompiler->fgFirstBB != nullptr);
22100
22101         // DDB 91389: Don't throw away the (only) inlinee block
22102         // when its return type is not BBJ_RETURN.
22103         // In other words, we need its BBJ_ to perform the right thing.
22104         if (InlineeCompiler->fgFirstBB->bbJumpKind == BBJ_RETURN)
22105         {
22106             // Inlinee contains just one BB. So just insert its statement list to topBlock.
22107             if (InlineeCompiler->fgFirstBB->bbTreeList)
22108             {
22109                 stmtAfter = fgInsertStmtListAfter(iciBlock, stmtAfter, InlineeCompiler->fgFirstBB->bbTreeList);
22110
22111                 // Copy inlinee bbFlags to caller bbFlags.
22112                 const unsigned __int64 inlineeBlockFlags = InlineeCompiler->fgFirstBB->bbFlags;
22113                 noway_assert((inlineeBlockFlags & BBF_HAS_JMP) == 0);
22114                 noway_assert((inlineeBlockFlags & BBF_KEEP_BBJ_ALWAYS) == 0);
22115                 iciBlock->bbFlags |= inlineeBlockFlags;
22116             }
22117
22118 #ifdef DEBUG
22119             if (verbose)
22120             {
22121                 noway_assert(currentDumpStmt);
22122
22123                 if (currentDumpStmt != stmtAfter)
22124                 {
22125                     do
22126                     {
22127                         currentDumpStmt = currentDumpStmt->gtNext;
22128
22129                         printf("\n");
22130
22131                         noway_assert(currentDumpStmt->gtOper == GT_STMT);
22132
22133                         gtDispTree(currentDumpStmt);
22134                         printf("\n");
22135
22136                     } while (currentDumpStmt != stmtAfter);
22137                 }
22138             }
22139 #endif // DEBUG
22140
22141             // Append statements to null out gc ref locals, if necessary.
22142             fgInlineAppendStatements(pInlineInfo, iciBlock, stmtAfter);
22143
22144             goto _Done;
22145         }
22146     }
22147
22148     //
22149     // ======= Inserting inlinee's basic blocks ===============
22150     //
22151
22152     bottomBlock             = fgNewBBafter(topBlock->bbJumpKind, topBlock, true);
22153     bottomBlock->bbRefs     = 1;
22154     bottomBlock->bbJumpDest = topBlock->bbJumpDest;
22155     bottomBlock->inheritWeight(topBlock);
22156
22157     topBlock->bbJumpKind = BBJ_NONE;
22158
22159     // Update block flags
22160     {
22161         const unsigned __int64 originalFlags = topBlock->bbFlags;
22162         noway_assert((originalFlags & BBF_SPLIT_NONEXIST) == 0);
22163         topBlock->bbFlags &= ~(BBF_SPLIT_LOST);
22164         bottomBlock->bbFlags |= originalFlags & BBF_SPLIT_GAINED;
22165     }
22166
22167     //
22168     // Split statements between topBlock and bottomBlock
22169     //
22170     GenTreePtr topBlock_Begin;
22171     GenTreePtr topBlock_End;
22172     GenTreePtr bottomBlock_Begin;
22173     GenTreePtr bottomBlock_End;
22174
22175     topBlock_Begin    = nullptr;
22176     topBlock_End      = nullptr;
22177     bottomBlock_Begin = nullptr;
22178     bottomBlock_End   = nullptr;
22179
22180     //
22181     // First figure out bottomBlock_Begin
22182     //
22183
22184     bottomBlock_Begin = stmtAfter->gtNext;
22185
22186     if (topBlock->bbTreeList == nullptr)
22187     {
22188         // topBlock is empty before the split.
22189         // In this case, both topBlock and bottomBlock should be empty
22190         noway_assert(bottomBlock_Begin == nullptr);
22191         topBlock->bbTreeList    = nullptr;
22192         bottomBlock->bbTreeList = nullptr;
22193     }
22194     else if (topBlock->bbTreeList == bottomBlock_Begin)
22195     {
22196         noway_assert(bottomBlock_Begin);
22197
22198         // topBlock contains at least one statement before the split.
22199         // And the split is before the first statement.
22200         // In this case, topBlock should be empty, and everything else should be moved to the bottonBlock.
22201         bottomBlock->bbTreeList = topBlock->bbTreeList;
22202         topBlock->bbTreeList    = nullptr;
22203     }
22204     else if (bottomBlock_Begin == nullptr)
22205     {
22206         noway_assert(topBlock->bbTreeList);
22207
22208         // topBlock contains at least one statement before the split.
22209         // And the split is at the end of the topBlock.
22210         // In this case, everything should be kept in the topBlock, and the bottomBlock should be empty
22211
22212         bottomBlock->bbTreeList = nullptr;
22213     }
22214     else
22215     {
22216         noway_assert(topBlock->bbTreeList);
22217         noway_assert(bottomBlock_Begin);
22218
22219         // This is the normal case where both blocks should contain at least one statement.
22220         topBlock_Begin = topBlock->bbTreeList;
22221         noway_assert(topBlock_Begin);
22222         topBlock_End = bottomBlock_Begin->gtPrev;
22223         noway_assert(topBlock_End);
22224         bottomBlock_End = topBlock->lastStmt();
22225         noway_assert(bottomBlock_End);
22226
22227         // Break the linkage between 2 blocks.
22228         topBlock_End->gtNext = nullptr;
22229
22230         // Fix up all the pointers.
22231         topBlock->bbTreeList         = topBlock_Begin;
22232         topBlock->bbTreeList->gtPrev = topBlock_End;
22233
22234         bottomBlock->bbTreeList         = bottomBlock_Begin;
22235         bottomBlock->bbTreeList->gtPrev = bottomBlock_End;
22236     }
22237
22238     //
22239     // Set the try and handler index and fix the jump types of inlinee's blocks.
22240     //
22241
22242     bool inheritWeight;
22243     inheritWeight = true; // The firstBB does inherit the weight from the iciBlock
22244
22245     for (block = InlineeCompiler->fgFirstBB; block != nullptr; block = block->bbNext)
22246     {
22247         noway_assert(!block->hasTryIndex());
22248         noway_assert(!block->hasHndIndex());
22249         block->copyEHRegion(iciBlock);
22250         block->bbFlags |= iciBlock->bbFlags & BBF_BACKWARD_JUMP;
22251
22252         if (iciStmt->gtStmtILoffsx != BAD_IL_OFFSET)
22253         {
22254             block->bbCodeOffs    = jitGetILoffs(iciStmt->gtStmtILoffsx);
22255             block->bbCodeOffsEnd = block->bbCodeOffs + 1; // TODO: is code size of 1 some magic number for inlining?
22256         }
22257         else
22258         {
22259             block->bbCodeOffs    = 0; // TODO: why not BAD_IL_OFFSET?
22260             block->bbCodeOffsEnd = 0;
22261             block->bbFlags |= BBF_INTERNAL;
22262         }
22263
22264         if (block->bbJumpKind == BBJ_RETURN)
22265         {
22266             inheritWeight = true; // A return block does inherit the weight from the iciBlock
22267             noway_assert((block->bbFlags & BBF_HAS_JMP) == 0);
22268             if (block->bbNext)
22269             {
22270                 block->bbJumpKind = BBJ_ALWAYS;
22271                 block->bbJumpDest = bottomBlock;
22272 #ifdef DEBUG
22273                 if (verbose)
22274                 {
22275                     printf("\nConvert bbJumpKind of BB%02u to BBJ_ALWAYS to bottomBlock BB%02u\n", block->bbNum,
22276                            bottomBlock->bbNum);
22277                 }
22278 #endif // DEBUG
22279             }
22280             else
22281             {
22282 #ifdef DEBUG
22283                 if (verbose)
22284                 {
22285                     printf("\nConvert bbJumpKind of BB%02u to BBJ_NONE\n", block->bbNum);
22286                 }
22287 #endif // DEBUG
22288                 block->bbJumpKind = BBJ_NONE;
22289             }
22290         }
22291         if (inheritWeight)
22292         {
22293             block->inheritWeight(iciBlock);
22294             inheritWeight = false;
22295         }
22296         else
22297         {
22298             block->modifyBBWeight(iciBlock->bbWeight / 2);
22299         }
22300     }
22301
22302     // Insert inlinee's blocks into inliner's block list.
22303     topBlock->setNext(InlineeCompiler->fgFirstBB);
22304     InlineeCompiler->fgLastBB->setNext(bottomBlock);
22305
22306     //
22307     // Add inlinee's block count to inliner's.
22308     //
22309     fgBBcount += InlineeCompiler->fgBBcount;
22310
22311     // Append statements to null out gc ref locals, if necessary.
22312     fgInlineAppendStatements(pInlineInfo, bottomBlock, nullptr);
22313
22314 #ifdef DEBUG
22315     if (verbose)
22316     {
22317         fgDispBasicBlocks(InlineeCompiler->fgFirstBB, InlineeCompiler->fgLastBB, true);
22318     }
22319 #endif // DEBUG
22320
22321 _Done:
22322
22323     //
22324     // At this point, we have successully inserted inlinee's code.
22325     //
22326
22327     //
22328     // Copy out some flags
22329     //
22330     compLongUsed |= InlineeCompiler->compLongUsed;
22331     compFloatingPointUsed |= InlineeCompiler->compFloatingPointUsed;
22332     compLocallocUsed |= InlineeCompiler->compLocallocUsed;
22333     compQmarkUsed |= InlineeCompiler->compQmarkUsed;
22334     compUnsafeCastUsed |= InlineeCompiler->compUnsafeCastUsed;
22335     compNeedsGSSecurityCookie |= InlineeCompiler->compNeedsGSSecurityCookie;
22336     compGSReorderStackLayout |= InlineeCompiler->compGSReorderStackLayout;
22337
22338 #ifdef FEATURE_SIMD
22339     if (InlineeCompiler->usesSIMDTypes())
22340     {
22341         setUsesSIMDTypes(true);
22342     }
22343 #endif // FEATURE_SIMD
22344
22345     // Update unmanaged call count
22346     info.compCallUnmanaged += InlineeCompiler->info.compCallUnmanaged;
22347
22348 // Update optMethodFlags
22349
22350 #ifdef DEBUG
22351     unsigned optMethodFlagsBefore = optMethodFlags;
22352 #endif
22353
22354     optMethodFlags |= InlineeCompiler->optMethodFlags;
22355
22356 #ifdef DEBUG
22357     if (optMethodFlags != optMethodFlagsBefore)
22358     {
22359         JITDUMP("INLINER: Updating optMethodFlags --  root:%0x callee:%0x new:%0x\n", optMethodFlagsBefore,
22360                 InlineeCompiler->optMethodFlags, optMethodFlags);
22361     }
22362 #endif
22363
22364     // If there is non-NULL return, replace the GT_CALL with its return value expression,
22365     // so later it will be picked up by the GT_RET_EXPR node.
22366     if ((pInlineInfo->inlineCandidateInfo->fncRetType != TYP_VOID) || (iciCall->gtReturnType == TYP_STRUCT))
22367     {
22368         noway_assert(pInlineInfo->retExpr);
22369 #ifdef DEBUG
22370         if (verbose)
22371         {
22372             printf("\nReturn expression for call at ");
22373             printTreeID(iciCall);
22374             printf(" is\n");
22375             gtDispTree(pInlineInfo->retExpr);
22376         }
22377 #endif // DEBUG
22378         // Replace the call with the return expression
22379         iciCall->CopyFrom(pInlineInfo->retExpr, this);
22380     }
22381
22382     //
22383     // Detach the GT_CALL node from the original statement by hanging a "nothing" node under it,
22384     // so that fgMorphStmts can remove the statement once we return from here.
22385     //
22386     iciStmt->gtStmtExpr = gtNewNothingNode();
22387 }
22388
22389 //------------------------------------------------------------------------
22390 // fgInlinePrependStatements: prepend statements needed to match up
22391 // caller and inlined callee
22392 //
22393 // Arguments:
22394 //    inlineInfo -- info for the inline
22395 //
22396 // Return Value:
22397 //    The last statement that was added, or the original call if no
22398 //    statements were added.
22399 //
22400 // Notes:
22401 //    Statements prepended may include the following:
22402 //    * This pointer null check
22403 //    * Class initialization
22404 //    * Zeroing of must-init locals in the callee
22405 //    * Passing of call arguments via temps
22406 //
22407 //    Newly added statements are placed just after the original call
22408 //    and are are given the same inline context as the call any calls
22409 //    added here will appear to have been part of the immediate caller.
22410
22411 GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
22412 {
22413     BasicBlock*  block        = inlineInfo->iciBlock;
22414     GenTreeStmt* callStmt     = inlineInfo->iciStmt;
22415     IL_OFFSETX   callILOffset = callStmt->gtStmtILoffsx;
22416     GenTreeStmt* postStmt     = callStmt->gtNextStmt;
22417     GenTreePtr   afterStmt    = callStmt; // afterStmt is the place where the new statements should be inserted after.
22418     GenTreePtr   newStmt      = nullptr;
22419     GenTreeCall* call         = inlineInfo->iciCall->AsCall();
22420
22421     noway_assert(call->gtOper == GT_CALL);
22422
22423 #ifdef DEBUG
22424     if (0 && verbose)
22425     {
22426         printf("\nfgInlinePrependStatements for iciCall= ");
22427         printTreeID(call);
22428         printf(":\n");
22429     }
22430 #endif
22431
22432     // Prepend statements for any initialization / side effects
22433
22434     InlArgInfo*    inlArgInfo = inlineInfo->inlArgInfo;
22435     InlLclVarInfo* lclVarInfo = inlineInfo->lclVarInfo;
22436
22437     GenTreePtr tree;
22438
22439     // Create the null check statement (but not appending it to the statement list yet) for the 'this' pointer if
22440     // necessary.
22441     // The NULL check should be done after "argument setup statements".
22442     // The only reason we move it here is for calling "impInlineFetchArg(0,..." to reserve a temp
22443     // for the "this" pointer.
22444     // Note: Here we no longer do the optimization that was done by thisDereferencedFirst in the old inliner.
22445     // However the assetionProp logic will remove any unecessary null checks that we may have added
22446     //
22447     GenTreePtr nullcheck = nullptr;
22448
22449     if (call->gtFlags & GTF_CALL_NULLCHECK && !inlineInfo->thisDereferencedFirst)
22450     {
22451         // Call impInlineFetchArg to "reserve" a temp for the "this" pointer.
22452         nullcheck = gtNewOperNode(GT_IND, TYP_INT, impInlineFetchArg(0, inlArgInfo, lclVarInfo));
22453         nullcheck->gtFlags |= GTF_EXCEPT;
22454
22455         // The NULL-check statement will be inserted to the statement list after those statements
22456         // that assign arguments to temps and before the actual body of the inlinee method.
22457     }
22458
22459     /* Treat arguments that had to be assigned to temps */
22460     if (inlineInfo->argCnt)
22461     {
22462
22463 #ifdef DEBUG
22464         if (verbose)
22465         {
22466             printf("\nArguments setup:\n");
22467         }
22468 #endif // DEBUG
22469
22470         for (unsigned argNum = 0; argNum < inlineInfo->argCnt; argNum++)
22471         {
22472             const InlArgInfo& argInfo        = inlArgInfo[argNum];
22473             const bool        argIsSingleDef = !argInfo.argHasLdargaOp && !argInfo.argHasStargOp;
22474             GenTree* const    argNode        = inlArgInfo[argNum].argNode;
22475
22476             if (argInfo.argHasTmp)
22477             {
22478                 noway_assert(argInfo.argIsUsed);
22479
22480                 /* argBashTmpNode is non-NULL iff the argument's value was
22481                    referenced exactly once by the original IL. This offers an
22482                    oppportunity to avoid an intermediate temp and just insert
22483                    the original argument tree.
22484
22485                    However, if the temp node has been cloned somewhere while
22486                    importing (e.g. when handling isinst or dup), or if the IL
22487                    took the address of the argument, then argBashTmpNode will
22488                    be set (because the value was only explicitly retrieved
22489                    once) but the optimization cannot be applied.
22490                  */
22491
22492                 GenTreePtr argSingleUseNode = argInfo.argBashTmpNode;
22493
22494                 if ((argSingleUseNode != nullptr) && !(argSingleUseNode->gtFlags & GTF_VAR_CLONED) && argIsSingleDef)
22495                 {
22496                     // Change the temp in-place to the actual argument.
22497                     // We currently do not support this for struct arguments, so it must not be a GT_OBJ.
22498                     assert(argNode->gtOper != GT_OBJ);
22499                     argSingleUseNode->CopyFrom(argNode, this);
22500                     continue;
22501                 }
22502                 else
22503                 {
22504                     // We're going to assign the argument value to the
22505                     // temp we use for it in the inline body.
22506                     const unsigned  tmpNum  = argInfo.argTmpNum;
22507                     const var_types argType = lclVarInfo[argNum].lclTypeInfo;
22508
22509                     // Create the temp assignment for this argument
22510                     CORINFO_CLASS_HANDLE structHnd = DUMMY_INIT(0);
22511
22512                     if (varTypeIsStruct(argType))
22513                     {
22514                         structHnd = gtGetStructHandleIfPresent(argNode);
22515                         noway_assert(structHnd != NO_CLASS_HANDLE);
22516                     }
22517
22518                     // Unsafe value cls check is not needed for
22519                     // argTmpNum here since in-linee compiler instance
22520                     // would have iterated over these and marked them
22521                     // accordingly.
22522                     impAssignTempGen(tmpNum, argNode, structHnd, (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset,
22523                                      block);
22524
22525                     // If we know the argument's value can't be
22526                     // changed within the method body, try and improve
22527                     // the type of the temp.
22528                     if (argIsSingleDef && (argType == TYP_REF))
22529                     {
22530                         lvaUpdateClass(tmpNum, argNode);
22531                     }
22532
22533 #ifdef DEBUG
22534                     if (verbose)
22535                     {
22536                         gtDispTree(afterStmt);
22537                     }
22538 #endif // DEBUG
22539                 }
22540             }
22541             else if (argInfo.argIsByRefToStructLocal)
22542             {
22543                 // Do nothing. Arg was directly substituted as we read
22544                 // the inlinee.
22545             }
22546             else
22547             {
22548                 /* The argument is either not used or a const or lcl var */
22549
22550                 noway_assert(!argInfo.argIsUsed || argInfo.argIsInvariant || argInfo.argIsLclVar);
22551
22552                 /* Make sure we didnt change argNode's along the way, or else
22553                    subsequent uses of the arg would have worked with the bashed value */
22554                 if (argInfo.argIsInvariant)
22555                 {
22556                     assert(argNode->OperIsConst() || argNode->gtOper == GT_ADDR);
22557                 }
22558                 noway_assert((argInfo.argIsLclVar == 0) ==
22559                              (argNode->gtOper != GT_LCL_VAR || (argNode->gtFlags & GTF_GLOB_REF)));
22560
22561                 /* If the argument has side effects, append it */
22562
22563                 if (argInfo.argHasSideEff)
22564                 {
22565                     noway_assert(argInfo.argIsUsed == false);
22566
22567                     if (argNode->gtOper == GT_OBJ || argNode->gtOper == GT_MKREFANY)
22568                     {
22569                         // Don't put GT_OBJ node under a GT_COMMA.
22570                         // Codegen can't deal with it.
22571                         // Just hang the address here in case there are side-effect.
22572                         newStmt = gtNewStmt(gtUnusedValNode(argNode->gtOp.gtOp1), callILOffset);
22573                     }
22574                     else
22575                     {
22576                         newStmt = gtNewStmt(gtUnusedValNode(argNode), callILOffset);
22577                     }
22578                     afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
22579
22580 #ifdef DEBUG
22581                     if (verbose)
22582                     {
22583                         gtDispTree(afterStmt);
22584                     }
22585 #endif // DEBUG
22586                 }
22587             }
22588         }
22589     }
22590
22591     // Add the CCTOR check if asked for.
22592     // Note: We no longer do the optimization that is done before by staticAccessedFirstUsingHelper in the old inliner.
22593     //       Therefore we might prepend redundant call to HELPER.CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
22594     //       before the inlined method body, even if a static field of this type was accessed in the inlinee
22595     //       using a helper before any other observable side-effect.
22596
22597     if (inlineInfo->inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_USE_HELPER)
22598     {
22599         CORINFO_CONTEXT_HANDLE exactContext = inlineInfo->inlineCandidateInfo->exactContextHnd;
22600         CORINFO_CLASS_HANDLE   exactClass;
22601
22602         if (((SIZE_T)exactContext & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
22603         {
22604             exactClass = CORINFO_CLASS_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK);
22605         }
22606         else
22607         {
22608             exactClass = info.compCompHnd->getMethodClass(
22609                 CORINFO_METHOD_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK));
22610         }
22611
22612         tree      = fgGetSharedCCtor(exactClass);
22613         newStmt   = gtNewStmt(tree, callILOffset);
22614         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
22615     }
22616
22617     // Insert the nullcheck statement now.
22618     if (nullcheck)
22619     {
22620         newStmt   = gtNewStmt(nullcheck, callILOffset);
22621         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
22622     }
22623
22624     //
22625     // Now zero-init inlinee locals
22626     //
22627
22628     CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
22629
22630     unsigned lclCnt = InlineeMethodInfo->locals.numArgs;
22631
22632     // Does callee contain any zero-init local?
22633     if ((lclCnt != 0) && (InlineeMethodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0)
22634     {
22635
22636 #ifdef DEBUG
22637         if (verbose)
22638         {
22639             printf("\nZero init inlinee locals:\n");
22640         }
22641 #endif // DEBUG
22642
22643         for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++)
22644         {
22645             unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
22646
22647             // Is the local used at all?
22648             if (tmpNum != BAD_VAR_NUM)
22649             {
22650                 var_types lclTyp = (var_types)lvaTable[tmpNum].lvType;
22651                 noway_assert(lclTyp == lclVarInfo[lclNum + inlineInfo->argCnt].lclTypeInfo);
22652
22653                 if (!varTypeIsStruct(lclTyp))
22654                 {
22655                     // Unsafe value cls check is not needed here since in-linee compiler instance would have
22656                     // iterated over locals and marked accordingly.
22657                     impAssignTempGen(tmpNum, gtNewZeroConNode(genActualType(lclTyp)), NO_CLASS_HANDLE,
22658                                      (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset, block);
22659                 }
22660                 else
22661                 {
22662                     CORINFO_CLASS_HANDLE structType =
22663                         lclVarInfo[lclNum + inlineInfo->argCnt].lclVerTypeInfo.GetClassHandle();
22664
22665                     tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp),              // Dest
22666                                           gtNewIconNode(0),                           // Value
22667                                           info.compCompHnd->getClassSize(structType), // Size
22668                                           false,                                      // isVolatile
22669                                           false);                                     // not copyBlock
22670
22671                     newStmt   = gtNewStmt(tree, callILOffset);
22672                     afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
22673                 }
22674
22675 #ifdef DEBUG
22676                 if (verbose)
22677                 {
22678                     gtDispTree(afterStmt);
22679                 }
22680 #endif // DEBUG
22681             }
22682         }
22683     }
22684
22685     // Update any newly added statements with the appropriate context.
22686     InlineContext* context = callStmt->gtInlineContext;
22687     assert(context != nullptr);
22688     for (GenTreeStmt* addedStmt = callStmt->gtNextStmt; addedStmt != postStmt; addedStmt = addedStmt->gtNextStmt)
22689     {
22690         assert(addedStmt->gtInlineContext == nullptr);
22691         addedStmt->gtInlineContext = context;
22692     }
22693
22694     return afterStmt;
22695 }
22696
22697 //------------------------------------------------------------------------
22698 // fgInlineAppendStatements: Append statements that are needed
22699 // after the inlined call.
22700 //
22701 // Arguments:
22702 //    inlineInfo - information about the inline
22703 //    block      - basic block for the new statements
22704 //    stmtAfter  - (optional) insertion point for mid-block cases
22705 //
22706 // Notes:
22707 //    If the call we're inlining is in tail position then
22708 //    we skip nulling the locals, since it can interfere
22709 //    with tail calls introduced by the local.
22710
22711 void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTreePtr stmtAfter)
22712 {
22713     // If this inlinee was passed a runtime lookup generic context and
22714     // ignores it, we can decrement the "generic context was used" ref
22715     // count, because we created a new lookup tree and incremented the
22716     // count when we imported the type parameter argument to pass to
22717     // the inlinee. See corresponding logic in impImportCall that
22718     // checks the sig for CORINFO_CALLCONV_PARAMTYPE.
22719     //
22720     // Does this method require a context (type) parameter?
22721     if ((inlineInfo->inlineCandidateInfo->methInfo.args.callConv & CORINFO_CALLCONV_PARAMTYPE) != 0)
22722     {
22723         // Did the computation of that parameter require the
22724         // caller to perform a runtime lookup?
22725         if (inlineInfo->inlineCandidateInfo->exactContextNeedsRuntimeLookup)
22726         {
22727             // Fetch the temp for the generic context as it would
22728             // appear in the inlinee's body.
22729             const unsigned typeCtxtArg = inlineInfo->typeContextArg;
22730             const unsigned tmpNum      = inlineInfo->lclTmpNum[typeCtxtArg];
22731
22732             // Was it used in the inline body?
22733             if (tmpNum == BAD_VAR_NUM)
22734             {
22735                 // No -- so the associated runtime lookup is not needed
22736                 // and also no longer provides evidence that the generic
22737                 // context should be kept alive.
22738                 JITDUMP("Inlinee ignores runtime lookup generics context\n");
22739                 assert(lvaGenericsContextUseCount > 0);
22740                 lvaGenericsContextUseCount--;
22741             }
22742         }
22743     }
22744
22745     // Null out any gc ref locals
22746     if (!inlineInfo->HasGcRefLocals())
22747     {
22748         // No ref locals, nothing to do.
22749         JITDUMP("fgInlineAppendStatements: no gc ref inline locals.\n");
22750         return;
22751     }
22752
22753     if (inlineInfo->iciCall->IsImplicitTailCall())
22754     {
22755         JITDUMP("fgInlineAppendStatements: implicit tail call; skipping nulling.\n");
22756         return;
22757     }
22758
22759     JITDUMP("fgInlineAppendStatements: nulling out gc ref inlinee locals.\n");
22760
22761     GenTreePtr           callStmt          = inlineInfo->iciStmt;
22762     IL_OFFSETX           callILOffset      = callStmt->gtStmt.gtStmtILoffsx;
22763     CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
22764     const unsigned       lclCnt            = InlineeMethodInfo->locals.numArgs;
22765     InlLclVarInfo*       lclVarInfo        = inlineInfo->lclVarInfo;
22766     unsigned             gcRefLclCnt       = inlineInfo->numberOfGcRefLocals;
22767     const unsigned       argCnt            = inlineInfo->argCnt;
22768
22769     noway_assert(callStmt->gtOper == GT_STMT);
22770
22771     for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++)
22772     {
22773         // Is the local a gc ref type? Need to look at the
22774         // inline info for this since we will not have local
22775         // temps for unused inlinee locals.
22776         const var_types lclTyp = lclVarInfo[argCnt + lclNum].lclTypeInfo;
22777
22778         if (!varTypeIsGC(lclTyp))
22779         {
22780             // Nope, nothing to null out.
22781             continue;
22782         }
22783
22784         // Ensure we're examining just the right number of locals.
22785         assert(gcRefLclCnt > 0);
22786         gcRefLclCnt--;
22787
22788         // Fetch the temp for this inline local
22789         const unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
22790
22791         // Is the local used at all?
22792         if (tmpNum == BAD_VAR_NUM)
22793         {
22794             // Nope, nothing to null out.
22795             continue;
22796         }
22797
22798         // Local was used, make sure the type is consistent.
22799         assert(lvaTable[tmpNum].lvType == lclTyp);
22800
22801         // Does the local we're about to null out appear in the return
22802         // expression?  If so we somehow messed up and didn't properly
22803         // spill the return value. See impInlineFetchLocal.
22804         GenTreePtr retExpr = inlineInfo->retExpr;
22805         if (retExpr != nullptr)
22806         {
22807             const bool interferesWithReturn = gtHasRef(inlineInfo->retExpr, tmpNum, false);
22808             noway_assert(!interferesWithReturn);
22809         }
22810
22811         // Assign null to the local.
22812         GenTreePtr nullExpr = gtNewTempAssign(tmpNum, gtNewZeroConNode(lclTyp));
22813         GenTreePtr nullStmt = gtNewStmt(nullExpr, callILOffset);
22814
22815         if (stmtAfter == nullptr)
22816         {
22817             stmtAfter = fgInsertStmtAtBeg(block, nullStmt);
22818         }
22819         else
22820         {
22821             stmtAfter = fgInsertStmtAfter(block, stmtAfter, nullStmt);
22822         }
22823
22824 #ifdef DEBUG
22825         if (verbose)
22826         {
22827             gtDispTree(nullStmt);
22828         }
22829 #endif // DEBUG
22830     }
22831
22832     // There should not be any GC ref locals left to null out.
22833     assert(gcRefLclCnt == 0);
22834 }
22835
22836 /*****************************************************************************/
22837 /*static*/
22838 Compiler::fgWalkResult Compiler::fgChkThrowCB(GenTreePtr* pTree, fgWalkData* data)
22839 {
22840     GenTreePtr tree = *pTree;
22841
22842     // If this tree doesn't have the EXCEPT flag set, then there is no
22843     // way any of the child nodes could throw, so we can stop recursing.
22844     if (!(tree->gtFlags & GTF_EXCEPT))
22845     {
22846         return Compiler::WALK_SKIP_SUBTREES;
22847     }
22848
22849     switch (tree->gtOper)
22850     {
22851         case GT_MUL:
22852         case GT_ADD:
22853         case GT_SUB:
22854         case GT_ASG_ADD:
22855         case GT_ASG_SUB:
22856         case GT_CAST:
22857             if (tree->gtOverflow())
22858             {
22859                 return Compiler::WALK_ABORT;
22860             }
22861             break;
22862
22863         case GT_INDEX:
22864             if (tree->gtFlags & GTF_INX_RNGCHK)
22865             {
22866                 return Compiler::WALK_ABORT;
22867             }
22868             break;
22869
22870         case GT_ARR_BOUNDS_CHECK:
22871             return Compiler::WALK_ABORT;
22872
22873         default:
22874             break;
22875     }
22876
22877     return Compiler::WALK_CONTINUE;
22878 }
22879
22880 /*****************************************************************************/
22881 /*static*/
22882 Compiler::fgWalkResult Compiler::fgChkLocAllocCB(GenTreePtr* pTree, fgWalkData* data)
22883 {
22884     GenTreePtr tree = *pTree;
22885
22886     if (tree->gtOper == GT_LCLHEAP)
22887     {
22888         return Compiler::WALK_ABORT;
22889     }
22890
22891     return Compiler::WALK_CONTINUE;
22892 }
22893
22894 /*****************************************************************************/
22895 /*static*/
22896 Compiler::fgWalkResult Compiler::fgChkQmarkCB(GenTreePtr* pTree, fgWalkData* data)
22897 {
22898     GenTreePtr tree = *pTree;
22899
22900     if (tree->gtOper == GT_QMARK)
22901     {
22902         return Compiler::WALK_ABORT;
22903     }
22904
22905     return Compiler::WALK_CONTINUE;
22906 }
22907
22908 void Compiler::fgLclFldAssign(unsigned lclNum)
22909 {
22910     assert(varTypeIsStruct(lvaTable[lclNum].lvType));
22911     if (lvaTable[lclNum].lvPromoted && lvaTable[lclNum].lvFieldCnt > 1)
22912     {
22913         lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField));
22914     }
22915 }
22916
22917 //------------------------------------------------------------------------
22918 // fgRemoveEmptyFinally: Remove try/finallys where the finally is empty
22919 //
22920 // Notes:
22921 //    Removes all try/finallys in the method with empty finallys.
22922 //    These typically arise from inlining empty Dispose methods.
22923 //
22924 //    Converts callfinally to a jump to the finally continuation.
22925 //    Removes the finally, and reparents all blocks in the try to the
22926 //    enclosing try or method region.
22927 //
22928 //    Currently limited to trivially empty finallys: those with one basic
22929 //    block containing only single RETFILT statement. It is possible but
22930 //    not likely that more complex-looking finallys will eventually become
22931 //    empty (from say subsequent optimization). An SPMI run with
22932 //    just the "detection" part of this phase run after optimization
22933 //    found only one example where a new empty finally was detected.
22934
22935 void Compiler::fgRemoveEmptyFinally()
22936 {
22937     JITDUMP("\n*************** In fgRemoveEmptyFinally()\n");
22938
22939 #if FEATURE_EH_FUNCLETS
22940     // We need to do this transformation before funclets are created.
22941     assert(!fgFuncletsCreated);
22942 #endif // FEATURE_EH_FUNCLETS
22943
22944     // Assume we don't need to update the bbPreds lists.
22945     assert(!fgComputePredsDone);
22946
22947     if (compHndBBtabCount == 0)
22948     {
22949         JITDUMP("No EH in this method, nothing to remove.\n");
22950         return;
22951     }
22952
22953     if (opts.MinOpts())
22954     {
22955         JITDUMP("Method compiled with minOpts, no removal.\n");
22956         return;
22957     }
22958
22959     if (opts.compDbgCode)
22960     {
22961         JITDUMP("Method compiled with debug codegen, no removal.\n");
22962         return;
22963     }
22964
22965 #ifdef DEBUG
22966     if (verbose)
22967     {
22968         printf("\n*************** Before fgRemoveEmptyFinally()\n");
22969         fgDispBasicBlocks();
22970         fgDispHandlerTab();
22971         printf("\n");
22972     }
22973 #endif // DEBUG
22974
22975     // Look for finallys or faults that are empty.
22976     unsigned finallyCount = 0;
22977     unsigned emptyCount   = 0;
22978     unsigned XTnum        = 0;
22979     while (XTnum < compHndBBtabCount)
22980     {
22981         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
22982
22983         // Check if this is a try/finally.  We could also look for empty
22984         // try/fault but presumably those are rare.
22985         if (!HBtab->HasFinallyHandler())
22986         {
22987             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
22988             XTnum++;
22989             continue;
22990         }
22991
22992         finallyCount++;
22993
22994         // Look at blocks involved.
22995         BasicBlock* const firstBlock = HBtab->ebdHndBeg;
22996         BasicBlock* const lastBlock  = HBtab->ebdHndLast;
22997
22998         // Limit for now to finallys that are single blocks.
22999         if (firstBlock != lastBlock)
23000         {
23001             JITDUMP("EH#%u finally has multiple basic blocks; skipping.\n", XTnum);
23002             XTnum++;
23003             continue;
23004         }
23005
23006         // Limit for now to finallys that contain only a GT_RETFILT.
23007         bool isEmpty = true;
23008
23009         for (GenTreeStmt* stmt = firstBlock->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
23010         {
23011             GenTreePtr stmtExpr = stmt->gtStmtExpr;
23012
23013             if (stmtExpr->gtOper != GT_RETFILT)
23014             {
23015                 isEmpty = false;
23016                 break;
23017             }
23018         }
23019
23020         if (!isEmpty)
23021         {
23022             JITDUMP("EH#%u finally is not empty; skipping.\n", XTnum);
23023             XTnum++;
23024             continue;
23025         }
23026
23027         JITDUMP("EH#%u has empty finally, removing the region.\n", XTnum);
23028
23029         // Find all the call finallys that invoke this finally,
23030         // and modify them to jump to the return point.
23031         BasicBlock* firstCallFinallyRangeBlock = nullptr;
23032         BasicBlock* endCallFinallyRangeBlock   = nullptr;
23033         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
23034
23035         BasicBlock* currentBlock = firstCallFinallyRangeBlock;
23036
23037         while (currentBlock != endCallFinallyRangeBlock)
23038         {
23039             BasicBlock* nextBlock = currentBlock->bbNext;
23040
23041             if ((currentBlock->bbJumpKind == BBJ_CALLFINALLY) && (currentBlock->bbJumpDest == firstBlock))
23042             {
23043                 // Retarget the call finally to jump to the return
23044                 // point.
23045                 //
23046                 // We don't expect to see retless finallys here, since
23047                 // the finally is empty.
23048                 noway_assert(currentBlock->isBBCallAlwaysPair());
23049
23050                 BasicBlock* const leaveBlock          = currentBlock->bbNext;
23051                 BasicBlock* const postTryFinallyBlock = leaveBlock->bbJumpDest;
23052
23053                 noway_assert(leaveBlock->bbJumpKind == BBJ_ALWAYS);
23054
23055                 currentBlock->bbJumpDest = postTryFinallyBlock;
23056                 currentBlock->bbJumpKind = BBJ_ALWAYS;
23057
23058                 // Ref count updates.
23059                 fgAddRefPred(postTryFinallyBlock, currentBlock);
23060                 // fgRemoveRefPred(firstBlock, currentBlock);
23061
23062                 // Delete the leave block, which should be marked as
23063                 // keep always.
23064                 assert((leaveBlock->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
23065                 nextBlock = leaveBlock->bbNext;
23066
23067                 leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
23068                 fgRemoveBlock(leaveBlock, true);
23069
23070                 // Cleanup the postTryFinallyBlock
23071                 fgCleanupContinuation(postTryFinallyBlock);
23072
23073                 // Make sure iteration isn't going off the deep end.
23074                 assert(leaveBlock != endCallFinallyRangeBlock);
23075             }
23076
23077             currentBlock = nextBlock;
23078         }
23079
23080         // Handler block should now be unreferenced, since the only
23081         // explicit references to it were in call finallys.
23082         firstBlock->bbRefs = 0;
23083
23084         // Remove the handler block.
23085         const bool unreachable = true;
23086         firstBlock->bbFlags &= ~BBF_DONT_REMOVE;
23087         fgRemoveBlock(firstBlock, unreachable);
23088
23089         // Find enclosing try region for the try, if any, and update
23090         // the try region. Note the handler region (if any) won't
23091         // change.
23092         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
23093         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
23094         assert(firstTryBlock->getTryIndex() == XTnum);
23095
23096         for (BasicBlock* block = firstTryBlock; block != nullptr; block = block->bbNext)
23097         {
23098             // Look for blocks directly contained in this try, and
23099             // update the try region appropriately.
23100             //
23101             // Try region for blocks transitively contained (say in a
23102             // child try) will get updated by the subsequent call to
23103             // fgRemoveEHTableEntry.
23104             if (block->getTryIndex() == XTnum)
23105             {
23106                 if (firstBlock->hasTryIndex())
23107                 {
23108                     block->setTryIndex(firstBlock->getTryIndex());
23109                 }
23110                 else
23111                 {
23112                     block->clearTryIndex();
23113                 }
23114             }
23115
23116             if (block == firstTryBlock)
23117             {
23118                 assert((block->bbFlags & BBF_TRY_BEG) != 0);
23119                 block->bbFlags &= ~BBF_TRY_BEG;
23120             }
23121
23122             if (block == lastTryBlock)
23123             {
23124                 break;
23125             }
23126         }
23127
23128         // Remove the try-finally EH region. This will compact the EH table
23129         // so XTnum now points at the next entry.
23130         fgRemoveEHTableEntry(XTnum);
23131
23132         emptyCount++;
23133     }
23134
23135     if (emptyCount > 0)
23136     {
23137         JITDUMP("fgRemoveEmptyFinally() removed %u try-finally clauses from %u finallys\n", emptyCount, finallyCount);
23138         fgOptimizedFinally = true;
23139
23140 #ifdef DEBUG
23141         if (verbose)
23142         {
23143             printf("\n*************** After fgRemoveEmptyFinally()\n");
23144             fgDispBasicBlocks();
23145             fgDispHandlerTab();
23146             printf("\n");
23147         }
23148
23149         fgVerifyHandlerTab();
23150         fgDebugCheckBBlist(false, false);
23151
23152 #endif // DEBUG
23153     }
23154 }
23155
23156 //------------------------------------------------------------------------
23157 // fgRemoveEmptyTry: Optimize try/finallys where the try is empty
23158 //
23159 // Notes:
23160 //    In runtimes where thread abort is not possible, `try {} finally {S}`
23161 //    can be optimized to simply `S`. This method looks for such
23162 //    cases and removes the try-finally from the EH table, making
23163 //    suitable flow, block flag, statement, and region updates.
23164 //
23165 //    This optimization is not legal in runtimes that support thread
23166 //    abort because those runtimes ensure that a finally is completely
23167 //    executed before continuing to process the thread abort.  With
23168 //    this optimization, the code block `S` can lose special
23169 //    within-finally status and so complete execution is no longer
23170 //    guaranteed.
23171
23172 void Compiler::fgRemoveEmptyTry()
23173 {
23174     JITDUMP("\n*************** In fgRemoveEmptyTry()\n");
23175
23176 #if FEATURE_EH_FUNCLETS
23177     // We need to do this transformation before funclets are created.
23178     assert(!fgFuncletsCreated);
23179 #endif // FEATURE_EH_FUNCLETS
23180
23181     // Assume we don't need to update the bbPreds lists.
23182     assert(!fgComputePredsDone);
23183
23184 #ifdef FEATURE_CORECLR
23185     bool enableRemoveEmptyTry = true;
23186 #else
23187     // Code in a finally gets special treatment in the presence of
23188     // thread abort.
23189     bool enableRemoveEmptyTry = false;
23190 #endif // FEATURE_CORECLR
23191
23192 #ifdef DEBUG
23193     // Allow override to enable/disable.
23194     enableRemoveEmptyTry = (JitConfig.JitEnableRemoveEmptyTry() == 1);
23195 #endif // DEBUG
23196
23197     if (!enableRemoveEmptyTry)
23198     {
23199         JITDUMP("Empty try removal disabled.\n");
23200         return;
23201     }
23202
23203     if (compHndBBtabCount == 0)
23204     {
23205         JITDUMP("No EH in this method, nothing to remove.\n");
23206         return;
23207     }
23208
23209     if (opts.MinOpts())
23210     {
23211         JITDUMP("Method compiled with minOpts, no removal.\n");
23212         return;
23213     }
23214
23215     if (opts.compDbgCode)
23216     {
23217         JITDUMP("Method compiled with debug codegen, no removal.\n");
23218         return;
23219     }
23220
23221 #ifdef DEBUG
23222     if (verbose)
23223     {
23224         printf("\n*************** Before fgRemoveEmptyTry()\n");
23225         fgDispBasicBlocks();
23226         fgDispHandlerTab();
23227         printf("\n");
23228     }
23229 #endif // DEBUG
23230
23231     // Look for try-finallys where the try is empty.
23232     unsigned emptyCount = 0;
23233     unsigned XTnum      = 0;
23234     while (XTnum < compHndBBtabCount)
23235     {
23236         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
23237
23238         // Check if this is a try/finally.  We could also look for empty
23239         // try/fault but presumably those are rare.
23240         if (!HBtab->HasFinallyHandler())
23241         {
23242             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
23243             XTnum++;
23244             continue;
23245         }
23246
23247         // Examine the try region
23248         BasicBlock* const firstTryBlock     = HBtab->ebdTryBeg;
23249         BasicBlock* const lastTryBlock      = HBtab->ebdTryLast;
23250         BasicBlock* const firstHandlerBlock = HBtab->ebdHndBeg;
23251         BasicBlock* const lastHandlerBlock  = HBtab->ebdHndLast;
23252         BasicBlock* const endHandlerBlock   = lastHandlerBlock->bbNext;
23253
23254         assert(firstTryBlock->getTryIndex() == XTnum);
23255
23256         // Limit for now to trys that contain only a callfinally pair
23257         // or branch to same.
23258         if (!firstTryBlock->isEmpty())
23259         {
23260             JITDUMP("EH#%u first try block BB%02u not empty; skipping.\n", XTnum, firstTryBlock->bbNum);
23261             XTnum++;
23262             continue;
23263         }
23264
23265 #if FEATURE_EH_CALLFINALLY_THUNKS
23266
23267         // Look for blocks that are always jumps to a call finally
23268         // pair that targets the finally
23269         if (firstTryBlock->bbJumpKind != BBJ_ALWAYS)
23270         {
23271             JITDUMP("EH#%u first try block BB%02u not jump to a callfinally; skipping.\n", XTnum, firstTryBlock->bbNum);
23272             XTnum++;
23273             continue;
23274         }
23275
23276         BasicBlock* const callFinally = firstTryBlock->bbJumpDest;
23277
23278         // Look for call always pair. Note this will also disqualify
23279         // empty try removal in cases where the finally doesn't
23280         // return.
23281         if (!callFinally->isBBCallAlwaysPair() || (callFinally->bbJumpDest != firstHandlerBlock))
23282         {
23283             JITDUMP("EH#%u first try block BB%02u always jumps but not to a callfinally; skipping.\n", XTnum,
23284                     firstTryBlock->bbNum);
23285             XTnum++;
23286             continue;
23287         }
23288
23289         // Try itself must be a single block.
23290         if (firstTryBlock != lastTryBlock)
23291         {
23292             JITDUMP("EH#%u first try block BB%02u not only block in try; skipping.\n", XTnum,
23293                     firstTryBlock->bbNext->bbNum);
23294             XTnum++;
23295             continue;
23296         }
23297
23298 #else
23299         // Look for call always pair within the try itself. Note this
23300         // will also disqualify empty try removal in cases where the
23301         // finally doesn't return.
23302         if (!firstTryBlock->isBBCallAlwaysPair() || (firstTryBlock->bbJumpDest != firstHandlerBlock))
23303         {
23304             JITDUMP("EH#%u first try block BB%02u not a callfinally; skipping.\n", XTnum, firstTryBlock->bbNum);
23305             XTnum++;
23306             continue;
23307         }
23308
23309         BasicBlock* const callFinally = firstTryBlock;
23310
23311         // Try must be a callalways pair of blocks.
23312         if (firstTryBlock->bbNext != lastTryBlock)
23313         {
23314             JITDUMP("EH#%u block BB%02u not last block in try; skipping.\n", XTnum, firstTryBlock->bbNext->bbNum);
23315             XTnum++;
23316             continue;
23317         }
23318
23319 #endif // FEATURE_EH_CALLFINALLY_THUNKS
23320
23321         JITDUMP("EH#%u has empty try, removing the try region and promoting the finally.\n", XTnum);
23322
23323         // There should be just one callfinally that invokes this
23324         // finally, the one we found above. Verify this.
23325         BasicBlock* firstCallFinallyRangeBlock = nullptr;
23326         BasicBlock* endCallFinallyRangeBlock   = nullptr;
23327         bool        verifiedSingleCallfinally  = true;
23328         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
23329
23330         for (BasicBlock* block = firstCallFinallyRangeBlock; block != endCallFinallyRangeBlock; block = block->bbNext)
23331         {
23332             if ((block->bbJumpKind == BBJ_CALLFINALLY) && (block->bbJumpDest == firstHandlerBlock))
23333             {
23334                 assert(block->isBBCallAlwaysPair());
23335
23336                 if (block != callFinally)
23337                 {
23338                     JITDUMP("EH#%u found unexpected callfinally BB%02u; skipping.\n");
23339                     verifiedSingleCallfinally = false;
23340                     break;
23341                 }
23342
23343                 block = block->bbNext;
23344             }
23345         }
23346
23347         if (!verifiedSingleCallfinally)
23348         {
23349             JITDUMP("EH#%u -- unexpectedly -- has multiple callfinallys; skipping.\n");
23350             XTnum++;
23351             assert(verifiedSingleCallfinally);
23352             continue;
23353         }
23354
23355         // Time to optimize.
23356         //
23357         // (1) Convert the callfinally to a normal jump to the handler
23358         callFinally->bbJumpKind = BBJ_ALWAYS;
23359
23360         // Identify the leave block and the continuation
23361         BasicBlock* const leave        = callFinally->bbNext;
23362         BasicBlock* const continuation = leave->bbJumpDest;
23363
23364         // (2) Cleanup the leave so it can be deleted by subsequent opts
23365         assert((leave->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
23366         leave->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
23367
23368         // (3) Cleanup the continuation
23369         fgCleanupContinuation(continuation);
23370
23371         // (4) Find enclosing try region for the try, if any, and
23372         // update the try region for the blocks in the try. Note the
23373         // handler region (if any) won't change.
23374         //
23375         // Kind of overkill to loop here, but hey.
23376         for (BasicBlock* block = firstTryBlock; block != nullptr; block = block->bbNext)
23377         {
23378             // Look for blocks directly contained in this try, and
23379             // update the try region appropriately.
23380             //
23381             // The try region for blocks transitively contained (say in a
23382             // child try) will get updated by the subsequent call to
23383             // fgRemoveEHTableEntry.
23384             if (block->getTryIndex() == XTnum)
23385             {
23386                 if (firstHandlerBlock->hasTryIndex())
23387                 {
23388                     block->setTryIndex(firstHandlerBlock->getTryIndex());
23389                 }
23390                 else
23391                 {
23392                     block->clearTryIndex();
23393                 }
23394             }
23395
23396             if (block == firstTryBlock)
23397             {
23398                 assert((block->bbFlags & BBF_TRY_BEG) != 0);
23399                 block->bbFlags &= ~BBF_TRY_BEG;
23400             }
23401
23402             if (block == lastTryBlock)
23403             {
23404                 break;
23405             }
23406         }
23407
23408         // (5) Update the directly contained handler blocks' handler index.
23409         // Handler index of any nested blocks will update when we
23410         // remove the EH table entry.  Change handler exits to jump to
23411         // the continuation.  Clear catch type on handler entry.
23412         // Decrement nesting level of enclosed GT_END_LFINs.
23413         for (BasicBlock* block = firstHandlerBlock; block != endHandlerBlock; block = block->bbNext)
23414         {
23415             if (block == firstHandlerBlock)
23416             {
23417                 block->bbCatchTyp = BBCT_NONE;
23418             }
23419
23420             if (block->getHndIndex() == XTnum)
23421             {
23422                 if (firstTryBlock->hasHndIndex())
23423                 {
23424                     block->setHndIndex(firstTryBlock->getHndIndex());
23425                 }
23426                 else
23427                 {
23428                     block->clearHndIndex();
23429                 }
23430
23431                 if (block->bbJumpKind == BBJ_EHFINALLYRET)
23432                 {
23433                     GenTreeStmt* finallyRet     = block->lastStmt();
23434                     GenTreePtr   finallyRetExpr = finallyRet->gtStmtExpr;
23435                     assert(finallyRetExpr->gtOper == GT_RETFILT);
23436                     fgRemoveStmt(block, finallyRet);
23437                     block->bbJumpKind = BBJ_ALWAYS;
23438                     block->bbJumpDest = continuation;
23439                     fgAddRefPred(continuation, block);
23440                 }
23441             }
23442
23443 #if !FEATURE_EH_FUNCLETS
23444             // If we're in a non-funclet model, decrement the nesting
23445             // level of any GT_END_LFIN we find in the handler region,
23446             // since we're removing the enclosing handler.
23447             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
23448             {
23449                 GenTreePtr expr = stmt->gtStmtExpr;
23450                 if (expr->gtOper == GT_END_LFIN)
23451                 {
23452                     const unsigned nestLevel = expr->gtVal.gtVal1;
23453                     assert(nestLevel > 0);
23454                     expr->gtVal.gtVal1 = nestLevel - 1;
23455                 }
23456             }
23457 #endif // !FEATURE_EH_FUNCLETS
23458         }
23459
23460         // (6) Remove the try-finally EH region. This will compact the
23461         // EH table so XTnum now points at the next entry and will update
23462         // the EH region indices of any nested EH in the (former) handler.
23463         fgRemoveEHTableEntry(XTnum);
23464
23465         // Another one bites the dust...
23466         emptyCount++;
23467     }
23468
23469     if (emptyCount > 0)
23470     {
23471         JITDUMP("fgRemoveEmptyTry() optimized %u empty-try try-finally clauses\n", emptyCount);
23472         fgOptimizedFinally = true;
23473
23474 #ifdef DEBUG
23475         if (verbose)
23476         {
23477             printf("\n*************** After fgRemoveEmptyTry()\n");
23478             fgDispBasicBlocks();
23479             fgDispHandlerTab();
23480             printf("\n");
23481         }
23482
23483         fgVerifyHandlerTab();
23484         fgDebugCheckBBlist(false, false);
23485
23486 #endif // DEBUG
23487     }
23488 }
23489
23490 //------------------------------------------------------------------------
23491 // fgCloneFinally: Optimize normal exit path from a try/finally
23492 //
23493 // Notes:
23494 //    Handles finallys that are not enclosed by or enclosing other
23495 //    handler regions.
23496 //
23497 //    Converts the "normal exit" callfinally to a jump to a cloned copy
23498 //    of the finally, which in turn jumps to the finally continuation.
23499 //
23500 //    If all callfinallys for a given finally are converted to jump to
23501 //    the clone, the try-finally is modified into a try-fault,
23502 //    distingushable from organic try-faults by handler type
23503 //    EH_HANDLER_FAULT_WAS_FINALLY vs the organic EH_HANDLER_FAULT.
23504 //
23505 //    Does not yet handle thread abort. The open issues here are how
23506 //    to maintain the proper description of the cloned finally blocks
23507 //    as a handler (for thread abort purposes), how to prevent code
23508 //    motion in or out of these blocks, and how to report this cloned
23509 //    handler to the runtime. Some building blocks for thread abort
23510 //    exist (see below) but more work needed.
23511 //
23512 //    The first and last blocks of the cloned finally are marked with
23513 //    BBF_CLONED_FINALLY_BEGIN and BBF_CLONED_FINALLY_END. However
23514 //    these markers currently can get lost during subsequent
23515 //    optimizations.
23516
23517 void Compiler::fgCloneFinally()
23518 {
23519     JITDUMP("\n*************** In fgCloneFinally()\n");
23520
23521 #if FEATURE_EH_FUNCLETS
23522     // We need to do this transformation before funclets are created.
23523     assert(!fgFuncletsCreated);
23524 #endif // FEATURE_EH_FUNCLETS
23525
23526     // Assume we don't need to update the bbPreds lists.
23527     assert(!fgComputePredsDone);
23528
23529 #ifdef FEATURE_CORECLR
23530     bool enableCloning = true;
23531 #else
23532     // Finally cloning currently doesn't provide sufficient protection
23533     // for the cloned code in the presence of thread abort.
23534     bool enableCloning = false;
23535 #endif // FEATURE_CORECLR
23536
23537 #ifdef DEBUG
23538     // Allow override to enable/disable.
23539     enableCloning = (JitConfig.JitEnableFinallyCloning() == 1);
23540 #endif // DEBUG
23541
23542     if (!enableCloning)
23543     {
23544         JITDUMP("Finally cloning disabled.\n");
23545         return;
23546     }
23547
23548     if (compHndBBtabCount == 0)
23549     {
23550         JITDUMP("No EH in this method, no cloning.\n");
23551         return;
23552     }
23553
23554     if (opts.MinOpts())
23555     {
23556         JITDUMP("Method compiled with minOpts, no cloning.\n");
23557         return;
23558     }
23559
23560     if (opts.compDbgCode)
23561     {
23562         JITDUMP("Method compiled with debug codegen, no cloning.\n");
23563         return;
23564     }
23565
23566 #ifdef DEBUG
23567     if (verbose)
23568     {
23569         printf("\n*************** Before fgCloneFinally()\n");
23570         fgDispBasicBlocks();
23571         fgDispHandlerTab();
23572         printf("\n");
23573     }
23574
23575     // Verify try-finally exits look good before we start.
23576     fgDebugCheckTryFinallyExits();
23577
23578 #endif // DEBUG
23579
23580     // Look for finallys that are not contained within other handlers,
23581     // and which do not themselves contain EH.
23582     //
23583     // Note these cases potentially could be handled, but are less
23584     // obviously profitable and require modification of the handler
23585     // table.
23586     unsigned  XTnum      = 0;
23587     EHblkDsc* HBtab      = compHndBBtab;
23588     unsigned  cloneCount = 0;
23589     for (; XTnum < compHndBBtabCount; XTnum++, HBtab++)
23590     {
23591         // Check if this is a try/finally
23592         if (!HBtab->HasFinallyHandler())
23593         {
23594             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
23595             continue;
23596         }
23597
23598         // Check if enclosed by another handler.
23599         const unsigned enclosingHandlerRegion = ehGetEnclosingHndIndex(XTnum);
23600
23601         if (enclosingHandlerRegion != EHblkDsc::NO_ENCLOSING_INDEX)
23602         {
23603             JITDUMP("EH#%u is enclosed by handler EH#%u; skipping.\n", XTnum, enclosingHandlerRegion);
23604             continue;
23605         }
23606
23607         bool     containsEH                   = false;
23608         unsigned exampleEnclosedHandlerRegion = 0;
23609
23610         // Only need to look at lower numbered regions because the
23611         // handler table is ordered by nesting.
23612         for (unsigned i = 0; i < XTnum; i++)
23613         {
23614             if (ehGetEnclosingHndIndex(i) == XTnum)
23615             {
23616                 exampleEnclosedHandlerRegion = i;
23617                 containsEH                   = true;
23618                 break;
23619             }
23620         }
23621
23622         if (containsEH)
23623         {
23624             JITDUMP("Finally for EH#%u encloses handler EH#%u; skipping.\n", XTnum, exampleEnclosedHandlerRegion);
23625             continue;
23626         }
23627
23628         // Look at blocks involved.
23629         BasicBlock* const firstBlock = HBtab->ebdHndBeg;
23630         BasicBlock* const lastBlock  = HBtab->ebdHndLast;
23631         assert(firstBlock != nullptr);
23632         assert(lastBlock != nullptr);
23633         BasicBlock* nextBlock       = lastBlock->bbNext;
23634         unsigned    regionBBCount   = 0;
23635         unsigned    regionStmtCount = 0;
23636         bool        hasFinallyRet   = false;
23637         bool        isAllRare       = true;
23638         bool        hasSwitch       = false;
23639
23640         for (const BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
23641         {
23642             if (block->bbJumpKind == BBJ_SWITCH)
23643             {
23644                 hasSwitch = true;
23645                 break;
23646             }
23647
23648             regionBBCount++;
23649
23650             // Should we compute statement cost here, or is it
23651             // premature...? For now just count statements I guess.
23652             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
23653             {
23654                 regionStmtCount++;
23655             }
23656
23657             hasFinallyRet = hasFinallyRet || (block->bbJumpKind == BBJ_EHFINALLYRET);
23658             isAllRare     = isAllRare && block->isRunRarely();
23659         }
23660
23661         // Skip cloning if the finally has a switch.
23662         if (hasSwitch)
23663         {
23664             JITDUMP("Finally in EH#%u has a switch; skipping.\n", XTnum);
23665             continue;
23666         }
23667
23668         // Skip cloning if the finally must throw.
23669         if (!hasFinallyRet)
23670         {
23671             JITDUMP("Finally in EH#%u does not return; skipping.\n", XTnum);
23672             continue;
23673         }
23674
23675         // Skip cloning if the finally is rarely run code.
23676         if (isAllRare)
23677         {
23678             JITDUMP("Finally in EH#%u is run rarely; skipping.\n", XTnum);
23679             continue;
23680         }
23681
23682         // Empirical studies from CoreCLR and CoreFX show that less
23683         // that 1% of finally regions have more than 15
23684         // statements. So, to avoid potentially excessive code growth,
23685         // only clone finallys that have 15 or fewer statements.
23686         const unsigned stmtCountLimit = 15;
23687         if (regionStmtCount > stmtCountLimit)
23688         {
23689             JITDUMP("Finally in EH#%u has %u statements, limit is %u; skipping.\n", XTnum, regionStmtCount,
23690                     stmtCountLimit);
23691             continue;
23692         }
23693
23694         JITDUMP("EH#%u is a candidate for finally cloning:"
23695                 " %u blocks, %u statements\n",
23696                 XTnum, regionBBCount, regionStmtCount);
23697
23698         // Walk the try region backwards looking for the last block
23699         // that transfers control to a callfinally.
23700         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
23701         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
23702         assert(firstTryBlock->getTryIndex() == XTnum);
23703         assert(bbInTryRegions(XTnum, lastTryBlock));
23704         BasicBlock* const beforeTryBlock = firstTryBlock->bbPrev;
23705
23706         BasicBlock* normalCallFinallyBlock   = nullptr;
23707         BasicBlock* normalCallFinallyReturn  = nullptr;
23708         BasicBlock* cloneInsertAfter         = HBtab->ebdTryLast;
23709         bool        tryToRelocateCallFinally = false;
23710
23711         for (BasicBlock* block = lastTryBlock; block != beforeTryBlock; block = block->bbPrev)
23712         {
23713 #if FEATURE_EH_CALLFINALLY_THUNKS
23714             // Look for blocks that are always jumps to a call finally
23715             // pair that targets our finally.
23716             if (block->bbJumpKind != BBJ_ALWAYS)
23717             {
23718                 continue;
23719             }
23720
23721             BasicBlock* const jumpDest = block->bbJumpDest;
23722
23723             if (!jumpDest->isBBCallAlwaysPair() || (jumpDest->bbJumpDest != firstBlock))
23724             {
23725                 continue;
23726             }
23727 #else
23728             // Look for call finally pair directly within the try
23729             if (!block->isBBCallAlwaysPair() || (block->bbJumpDest != firstBlock))
23730             {
23731                 continue;
23732             }
23733
23734             BasicBlock* const jumpDest = block;
23735 #endif // FEATURE_EH_CALLFINALLY_THUNKS
23736
23737             // Found our block.
23738             BasicBlock* const finallyReturnBlock  = jumpDest->bbNext;
23739             BasicBlock* const postTryFinallyBlock = finallyReturnBlock->bbJumpDest;
23740
23741             normalCallFinallyBlock  = jumpDest;
23742             normalCallFinallyReturn = postTryFinallyBlock;
23743
23744 #if FEATURE_EH_CALLFINALLY_THUNKS
23745             // When there are callfinally thunks, we don't expect to see the
23746             // callfinally within a handler region either.
23747             assert(!jumpDest->hasHndIndex());
23748
23749             // Update the clone insertion point to just after the
23750             // call always pair.
23751             cloneInsertAfter = finallyReturnBlock;
23752
23753             // We will consider moving the callfinally so we can fall
23754             // through from the try into the clone.
23755             tryToRelocateCallFinally = true;
23756
23757             JITDUMP("Chose path to clone: try block BB%02u jumps to callfinally at BB%02u;"
23758                     " the call returns to BB%02u which jumps to BB%02u\n",
23759                     block->bbNum, jumpDest->bbNum, finallyReturnBlock->bbNum, postTryFinallyBlock->bbNum);
23760 #else
23761             JITDUMP("Chose path to clone: try block BB%02u is a callfinally;"
23762                     " the call returns to BB%02u which jumps to BB%02u\n",
23763                     block->bbNum, finallyReturnBlock->bbNum, postTryFinallyBlock->bbNum);
23764 #endif // FEATURE_EH_CALLFINALLY_THUNKS
23765
23766             break;
23767         }
23768
23769         // If there is no call to the finally, don't clone.
23770         if (normalCallFinallyBlock == nullptr)
23771         {
23772             JITDUMP("EH#%u: no calls from the try to the finally, skipping.\n", XTnum);
23773             continue;
23774         }
23775
23776         JITDUMP("Will update callfinally block BB%02u to jump to the clone;"
23777                 " clone will jump to BB%02u\n",
23778                 normalCallFinallyBlock->bbNum, normalCallFinallyReturn->bbNum);
23779
23780         // If there are multiple callfinallys and we're in the
23781         // callfinally thunk model, all the callfinallys are placed
23782         // just outside the try region. We'd like our chosen
23783         // callfinally to come first after the try, so we can fall out of the try
23784         // into the clone.
23785         BasicBlock* firstCallFinallyRangeBlock = nullptr;
23786         BasicBlock* endCallFinallyRangeBlock   = nullptr;
23787         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
23788
23789         if (tryToRelocateCallFinally)
23790         {
23791             BasicBlock* firstCallFinallyBlock = nullptr;
23792
23793             for (BasicBlock* block = firstCallFinallyRangeBlock; block != endCallFinallyRangeBlock;
23794                  block             = block->bbNext)
23795             {
23796                 if (block->isBBCallAlwaysPair())
23797                 {
23798                     if (block->bbJumpDest == firstBlock)
23799                     {
23800                         firstCallFinallyBlock = block;
23801                         break;
23802                     }
23803                 }
23804             }
23805
23806             // We better have found at least one call finally.
23807             assert(firstCallFinallyBlock != nullptr);
23808
23809             // If there is more than one callfinally, move the one we are
23810             // going to retarget to be first in the callfinally range.
23811             if (firstCallFinallyBlock != normalCallFinallyBlock)
23812             {
23813                 JITDUMP("Moving callfinally BB%02u to be first in line, before BB%02u\n", normalCallFinallyBlock->bbNum,
23814                         firstCallFinallyBlock->bbNum);
23815
23816                 BasicBlock* const firstToMove      = normalCallFinallyBlock;
23817                 BasicBlock* const lastToMove       = normalCallFinallyBlock->bbNext;
23818                 BasicBlock* const placeToMoveAfter = firstCallFinallyBlock->bbPrev;
23819
23820                 fgUnlinkRange(firstToMove, lastToMove);
23821                 fgMoveBlocksAfter(firstToMove, lastToMove, placeToMoveAfter);
23822
23823 #ifdef DEBUG
23824                 // Sanity checks
23825                 fgDebugCheckBBlist(false, false);
23826                 fgVerifyHandlerTab();
23827 #endif // DEBUG
23828
23829                 assert(nextBlock == lastBlock->bbNext);
23830
23831                 // Update where the callfinally range begins, since we might
23832                 // have altered this with callfinally rearrangement, and/or
23833                 // the range begin might have been pretty loose to begin with.
23834                 firstCallFinallyRangeBlock = normalCallFinallyBlock;
23835             }
23836         }
23837
23838         // Clone the finally and retarget the normal return path and
23839         // any other path that happens to share that same return
23840         // point. For instance a construct like:
23841         //
23842         //  try { } catch { } finally { }
23843         //
23844         // will have two call finally blocks, one for the normal exit
23845         // from the try, and the the other for the exit from the
23846         // catch. They'll both pass the same return point which is the
23847         // statement after the finally, so they can share the clone.
23848         //
23849         // Clone the finally body, and splice it into the flow graph
23850         // within in the parent region of the try.
23851         const unsigned  finallyTryIndex = firstBlock->bbTryIndex;
23852         BasicBlock*     insertAfter     = nullptr;
23853         BlockToBlockMap blockMap(getAllocator());
23854         bool            clonedOk     = true;
23855         unsigned        cloneBBCount = 0;
23856
23857         for (BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
23858         {
23859             BasicBlock* newBlock;
23860
23861             if (block == firstBlock)
23862             {
23863                 // Put first cloned finally block into the approprate
23864                 // region, somewhere within or after the range of
23865                 // callfinallys, depending on the EH implementation.
23866                 const unsigned    hndIndex = 0;
23867                 BasicBlock* const nearBlk  = cloneInsertAfter;
23868                 newBlock                   = fgNewBBinRegion(block->bbJumpKind, finallyTryIndex, hndIndex, nearBlk);
23869
23870                 // If the clone ends up just after the finally, adjust
23871                 // the stopping point for finally traversal.
23872                 if (newBlock->bbNext == nextBlock)
23873                 {
23874                     assert(newBlock->bbPrev == lastBlock);
23875                     nextBlock = newBlock;
23876                 }
23877             }
23878             else
23879             {
23880                 // Put subsequent blocks in the same region...
23881                 const bool extendRegion = true;
23882                 newBlock                = fgNewBBafter(block->bbJumpKind, insertAfter, extendRegion);
23883             }
23884
23885             cloneBBCount++;
23886             assert(cloneBBCount <= regionBBCount);
23887
23888             insertAfter = newBlock;
23889             blockMap.Set(block, newBlock);
23890
23891             clonedOk = BasicBlock::CloneBlockState(this, newBlock, block);
23892
23893             if (!clonedOk)
23894             {
23895                 break;
23896             }
23897
23898             // Update block flags. Note a block can be both first and last.
23899             if (block == firstBlock)
23900             {
23901                 // Mark the block as the start of the cloned finally.
23902                 newBlock->bbFlags |= BBF_CLONED_FINALLY_BEGIN;
23903             }
23904
23905             if (block == lastBlock)
23906             {
23907                 // Mark the block as the end of the cloned finally.
23908                 newBlock->bbFlags |= BBF_CLONED_FINALLY_END;
23909             }
23910
23911             // Make sure clone block state hasn't munged the try region.
23912             assert(newBlock->bbTryIndex == finallyTryIndex);
23913
23914             // Cloned handler block is no longer within the handler.
23915             newBlock->clearHndIndex();
23916
23917             // Jump dests are set in a post-pass; make sure CloneBlockState hasn't tried to set them.
23918             assert(newBlock->bbJumpDest == nullptr);
23919         }
23920
23921         if (!clonedOk)
23922         {
23923             // TODO: cleanup the partial clone?
23924             JITDUMP("Unable to clone the finally; skipping.\n");
23925             continue;
23926         }
23927
23928         // We should have cloned all the finally region blocks.
23929         assert(cloneBBCount == regionBBCount);
23930
23931         JITDUMP("Cloned finally blocks are: BB%2u ... BB%2u\n", blockMap[firstBlock]->bbNum,
23932                 blockMap[lastBlock]->bbNum);
23933
23934         // Redirect redirect any branches within the newly-cloned
23935         // finally, and any finally returns to jump to the return
23936         // point.
23937         for (BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
23938         {
23939             BasicBlock* newBlock = blockMap[block];
23940
23941             if (block->bbJumpKind == BBJ_EHFINALLYRET)
23942             {
23943                 GenTreeStmt* finallyRet     = newBlock->lastStmt();
23944                 GenTreePtr   finallyRetExpr = finallyRet->gtStmtExpr;
23945                 assert(finallyRetExpr->gtOper == GT_RETFILT);
23946                 fgRemoveStmt(newBlock, finallyRet);
23947                 newBlock->bbJumpKind = BBJ_ALWAYS;
23948                 newBlock->bbJumpDest = normalCallFinallyReturn;
23949
23950                 fgAddRefPred(normalCallFinallyReturn, newBlock);
23951             }
23952             else
23953             {
23954                 optCopyBlkDest(block, newBlock);
23955                 optRedirectBlock(newBlock, &blockMap);
23956             }
23957         }
23958
23959         // Modify the targeting call finallys to branch to the cloned
23960         // finally. Make a note if we see some calls that can't be
23961         // retargeted (since they want to return to other places).
23962         BasicBlock* const firstCloneBlock    = blockMap[firstBlock];
23963         bool              retargetedAllCalls = true;
23964         BasicBlock*       currentBlock       = firstCallFinallyRangeBlock;
23965
23966         while (currentBlock != endCallFinallyRangeBlock)
23967         {
23968             BasicBlock* nextBlockToScan = currentBlock->bbNext;
23969
23970             if (currentBlock->isBBCallAlwaysPair())
23971             {
23972                 if (currentBlock->bbJumpDest == firstBlock)
23973                 {
23974                     BasicBlock* const leaveBlock          = currentBlock->bbNext;
23975                     BasicBlock* const postTryFinallyBlock = leaveBlock->bbJumpDest;
23976
23977                     // Note we must retarget all callfinallies that have this
23978                     // continuation, or we can't clean up the continuation
23979                     // block properly below, since it will be reachable both
23980                     // by the cloned finally and by the called finally.
23981                     if (postTryFinallyBlock == normalCallFinallyReturn)
23982                     {
23983                         // This call returns to the expected spot, so
23984                         // retarget it to branch to the clone.
23985                         currentBlock->bbJumpDest = firstCloneBlock;
23986                         currentBlock->bbJumpKind = BBJ_ALWAYS;
23987
23988                         // Ref count updates.
23989                         fgAddRefPred(firstCloneBlock, currentBlock);
23990                         // fgRemoveRefPred(firstBlock, currentBlock);
23991
23992                         // Delete the leave block, which should be marked as
23993                         // keep always.
23994                         assert((leaveBlock->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
23995                         nextBlock = leaveBlock->bbNext;
23996
23997                         leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
23998                         fgRemoveBlock(leaveBlock, true);
23999
24000                         // Make sure iteration isn't going off the deep end.
24001                         assert(leaveBlock != endCallFinallyRangeBlock);
24002                     }
24003                     else
24004                     {
24005                         // We can't retarget this call since it
24006                         // returns somewhere else.
24007                         retargetedAllCalls = false;
24008                     }
24009                 }
24010             }
24011
24012             currentBlock = nextBlockToScan;
24013         }
24014
24015         // If we retargeted all calls, modify EH descriptor to be
24016         // try-fault instead of try-finally, and then non-cloned
24017         // finally catch type to be fault.
24018         if (retargetedAllCalls)
24019         {
24020             JITDUMP("All callfinallys retargeted; changing finally to fault.\n");
24021             HBtab->ebdHandlerType  = EH_HANDLER_FAULT_WAS_FINALLY;
24022             firstBlock->bbCatchTyp = BBCT_FAULT;
24023         }
24024         else
24025         {
24026             JITDUMP("Some callfinallys *not* retargeted, so region must remain as a finally.\n");
24027         }
24028
24029         // Modify first block of cloned finally to be a "normal" block.
24030         BasicBlock* firstClonedBlock = blockMap[firstBlock];
24031         firstClonedBlock->bbCatchTyp = BBCT_NONE;
24032
24033         // Cleanup the continuation
24034         fgCleanupContinuation(normalCallFinallyReturn);
24035
24036         // Todo -- mark cloned blocks as a cloned finally....
24037
24038         // Done!
24039         JITDUMP("\nDone with EH#%u\n\n", XTnum);
24040         cloneCount++;
24041     }
24042
24043     if (cloneCount > 0)
24044     {
24045         JITDUMP("fgCloneFinally() cloned %u finally handlers\n", cloneCount);
24046         fgOptimizedFinally = true;
24047
24048 #ifdef DEBUG
24049         if (verbose)
24050         {
24051             printf("\n*************** After fgCloneFinally()\n");
24052             fgDispBasicBlocks();
24053             fgDispHandlerTab();
24054             printf("\n");
24055         }
24056
24057         fgVerifyHandlerTab();
24058         fgDebugCheckBBlist(false, false);
24059         fgDebugCheckTryFinallyExits();
24060
24061 #endif // DEBUG
24062     }
24063 }
24064
24065 #ifdef DEBUG
24066
24067 //------------------------------------------------------------------------
24068 // fgDebugCheckTryFinallyExits: validate normal flow from try-finally
24069 // or try-fault-was-finally.
24070 //
24071 // Notes:
24072 //
24073 // Normal control flow exiting the try block of a try-finally must
24074 // pass through the finally. This checker attempts to verify that by
24075 // looking at the control flow graph.
24076 //
24077 // Each path that exits the try of a try-finally (including try-faults
24078 // that were optimized into try-finallys by fgCloneFinally) should
24079 // thus either execute a callfinally to the associated finally or else
24080 // jump to a block with the BBF_CLONED_FINALLY_BEGIN flag set.
24081 //
24082 // Depending on when this check is done, there may also be an empty
24083 // block along the path.
24084 //
24085 // Depending on the model for invoking finallys, the callfinallies may
24086 // lie within the try region (callfinally thunks) or in the enclosing
24087 // region.
24088
24089 void Compiler::fgDebugCheckTryFinallyExits()
24090 {
24091     unsigned  XTnum            = 0;
24092     EHblkDsc* HBtab            = compHndBBtab;
24093     unsigned  cloneCount       = 0;
24094     bool      allTryExitsValid = true;
24095     for (; XTnum < compHndBBtabCount; XTnum++, HBtab++)
24096     {
24097         const EHHandlerType handlerType = HBtab->ebdHandlerType;
24098         const bool          isFinally   = (handlerType == EH_HANDLER_FINALLY);
24099         const bool          wasFinally  = (handlerType == EH_HANDLER_FAULT_WAS_FINALLY);
24100
24101         // Screen out regions that are or were not finallys.
24102         if (!isFinally && !wasFinally)
24103         {
24104             continue;
24105         }
24106
24107         // Walk blocks of the try, looking for normal control flow to
24108         // an ancestor region.
24109
24110         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
24111         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
24112         assert(firstTryBlock->getTryIndex() <= XTnum);
24113         assert(lastTryBlock->getTryIndex() <= XTnum);
24114         BasicBlock* const afterTryBlock = lastTryBlock->bbNext;
24115         BasicBlock* const finallyBlock  = isFinally ? HBtab->ebdHndBeg : nullptr;
24116
24117         for (BasicBlock* block = firstTryBlock; block != afterTryBlock; block = block->bbNext)
24118         {
24119             // Only check the directly contained blocks.
24120             assert(block->hasTryIndex());
24121
24122             if (block->getTryIndex() != XTnum)
24123             {
24124                 continue;
24125             }
24126
24127             // Look at each of the normal control flow possibilities.
24128             const unsigned numSuccs = block->NumSucc();
24129
24130             for (unsigned i = 0; i < numSuccs; i++)
24131             {
24132                 BasicBlock* const succBlock = block->GetSucc(i);
24133
24134                 if (succBlock->hasTryIndex() && succBlock->getTryIndex() <= XTnum)
24135                 {
24136                     // Successor does not exit this try region.
24137                     continue;
24138                 }
24139
24140 #if FEATURE_EH_CALLFINALLY_THUNKS
24141
24142                 // When there are callfinally thunks, callfinallies
24143                 // logically "belong" to a child region and the exit
24144                 // path validity will be checked when looking at the
24145                 // try blocks in that region.
24146                 if (block->bbJumpKind == BBJ_CALLFINALLY)
24147                 {
24148                     continue;
24149                 }
24150
24151 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24152
24153                 // Now we know block lies directly within the try of a
24154                 // try-finally, and succBlock is in an enclosing
24155                 // region (possibly the method region). So this path
24156                 // represents flow out of the try and should be
24157                 // checked.
24158                 //
24159                 // There are various ways control can properly leave a
24160                 // try-finally (or try-fault-was-finally):
24161                 //
24162                 // (a1) via a jump to a callfinally (only for finallys, only for call finally thunks)
24163                 // (a2) via a callfinally (only for finallys, only for !call finally thunks)
24164                 // (b) via a jump to a begin finally clone block
24165                 // (c) via a jump to an empty block to (b)
24166                 // (d) via a fallthrough to an empty block to (b)
24167                 // (e) via the always half of a callfinally pair
24168                 // (f) via an always jump clonefinally exit
24169                 bool isCallToFinally = false;
24170
24171 #if FEATURE_EH_CALLFINALLY_THUNKS
24172                 if (succBlock->bbJumpKind == BBJ_CALLFINALLY)
24173                 {
24174                     // case (a1)
24175                     isCallToFinally = isFinally && (succBlock->bbJumpDest == finallyBlock);
24176                 }
24177 #else
24178                 if (block->bbJumpKind == BBJ_CALLFINALLY)
24179                 {
24180                     // case (a2)
24181                     isCallToFinally = isFinally && (block->bbJumpDest == finallyBlock);
24182                 }
24183 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24184
24185                 bool isJumpToClonedFinally = false;
24186
24187                 if (succBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24188                 {
24189                     // case (b)
24190                     isJumpToClonedFinally = true;
24191                 }
24192                 else if (succBlock->bbJumpKind == BBJ_ALWAYS)
24193                 {
24194                     if (succBlock->isEmpty())
24195                     {
24196                         // case (c)
24197                         BasicBlock* const succSuccBlock = succBlock->bbJumpDest;
24198
24199                         if (succSuccBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24200                         {
24201                             isJumpToClonedFinally = true;
24202                         }
24203                     }
24204                 }
24205                 else if (succBlock->bbJumpKind == BBJ_NONE)
24206                 {
24207                     if (succBlock->isEmpty())
24208                     {
24209                         BasicBlock* const succSuccBlock = succBlock->bbNext;
24210
24211                         // case (d)
24212                         if (succSuccBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24213                         {
24214                             isJumpToClonedFinally = true;
24215                         }
24216                     }
24217                 }
24218
24219                 bool isReturnFromFinally = false;
24220
24221                 // Case (e). Ideally we'd have something stronger to
24222                 // check here -- eg that we are returning from a call
24223                 // to the right finally -- but there are odd cases
24224                 // like orphaned second halves of callfinally pairs
24225                 // that we need to tolerate.
24226                 if (block->bbFlags & BBF_KEEP_BBJ_ALWAYS)
24227                 {
24228                     isReturnFromFinally = true;
24229                 }
24230
24231                 // Case (f)
24232                 if (block->bbFlags & BBF_CLONED_FINALLY_END)
24233                 {
24234                     isReturnFromFinally = true;
24235                 }
24236
24237                 const bool thisExitValid = isCallToFinally || isJumpToClonedFinally || isReturnFromFinally;
24238
24239                 if (!thisExitValid)
24240                 {
24241                     JITDUMP("fgCheckTryFinallyExitS: EH#%u exit via BB%02u -> BB%02u is invalid\n", XTnum, block->bbNum,
24242                             succBlock->bbNum);
24243                 }
24244
24245                 allTryExitsValid = allTryExitsValid & thisExitValid;
24246             }
24247         }
24248     }
24249
24250     if (!allTryExitsValid)
24251     {
24252         JITDUMP("fgCheckTryFinallyExits: method contains invalid try exit paths\n");
24253         assert(allTryExitsValid);
24254     }
24255 }
24256
24257 #endif // DEBUG
24258
24259 //------------------------------------------------------------------------
24260 // fgCleanupContinuation: cleanup a finally continuation after a
24261 // finally is removed or converted to normal control flow.
24262 //
24263 // Notes:
24264 //    The continuation is the block targeted by the second half of
24265 //    a callfinally/always pair.
24266 //
24267 //    Used by finally cloning, empty try removal, and empty
24268 //    finally removal.
24269 //
24270 //    BBF_FINALLY_TARGET bbFlag is left unchanged by this method
24271 //    since it cannot be incrementally updated. Proper updates happen
24272 //    when fgUpdateFinallyTargetFlags runs after all finally optimizations.
24273
24274 void Compiler::fgCleanupContinuation(BasicBlock* continuation)
24275 {
24276     // The continuation may be a finalStep block.
24277     // It is now a normal block, so clear the special keep
24278     // always flag.
24279     continuation->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
24280
24281 #if !FEATURE_EH_FUNCLETS
24282     // Remove the GT_END_LFIN from the continuation,
24283     // Note we only expect to see one such statement.
24284     bool foundEndLFin = false;
24285     for (GenTreeStmt* stmt = continuation->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
24286     {
24287         GenTreePtr expr = stmt->gtStmtExpr;
24288         if (expr->gtOper == GT_END_LFIN)
24289         {
24290             assert(!foundEndLFin);
24291             fgRemoveStmt(continuation, stmt);
24292             foundEndLFin = true;
24293         }
24294     }
24295     assert(foundEndLFin);
24296 #endif // !FEATURE_EH_FUNCLETS
24297 }
24298
24299 //------------------------------------------------------------------------
24300 // fgUpdateFinallyTargetFlags: recompute BBF_FINALLY_TARGET bits for all blocks
24301 // after finally optimizations have run.
24302
24303 void Compiler::fgUpdateFinallyTargetFlags()
24304 {
24305 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
24306
24307     // Any fixup required?
24308     if (!fgOptimizedFinally)
24309     {
24310         JITDUMP("In fgUpdateFinallyTargetFlags - no finally opts, no fixup required\n");
24311         return;
24312     }
24313
24314     JITDUMP("In fgUpdateFinallyTargetFlags, updating finally target flag bits\n");
24315
24316     // Walk all blocks, and reset the target bits.
24317     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
24318     {
24319         block->bbFlags &= ~BBF_FINALLY_TARGET;
24320     }
24321
24322     // Walk all blocks again, and set the target bits.
24323     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
24324     {
24325         if (block->isBBCallAlwaysPair())
24326         {
24327             BasicBlock* const leave        = block->bbNext;
24328             BasicBlock* const continuation = leave->bbJumpDest;
24329
24330             if ((continuation->bbFlags & BBF_FINALLY_TARGET) == 0)
24331             {
24332                 JITDUMP("Found callfinally BB%02u; setting finally target bit on BB%02u\n", block->bbNum,
24333                         continuation->bbNum);
24334
24335                 continuation->bbFlags |= BBF_FINALLY_TARGET;
24336             }
24337         }
24338     }
24339 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
24340 }
24341
24342 //------------------------------------------------------------------------
24343 // fgMergeFinallyChains: tail merge finally invocations
24344 //
24345 // Notes:
24346 //
24347 //    Looks for common suffixes in chains of finally invocations
24348 //    (callfinallys) and merges them. These typically arise from
24349 //    try-finallys where there are multiple exit points in the try
24350 //    that have the same target.
24351
24352 void Compiler::fgMergeFinallyChains()
24353 {
24354     JITDUMP("\n*************** In fgMergeFinallyChains()\n");
24355
24356 #if FEATURE_EH_FUNCLETS
24357     // We need to do this transformation before funclets are created.
24358     assert(!fgFuncletsCreated);
24359 #endif // FEATURE_EH_FUNCLETS
24360
24361     // Assume we don't need to update the bbPreds lists.
24362     assert(!fgComputePredsDone);
24363
24364     if (compHndBBtabCount == 0)
24365     {
24366         JITDUMP("No EH in this method, nothing to merge.\n");
24367         return;
24368     }
24369
24370     if (opts.MinOpts())
24371     {
24372         JITDUMP("Method compiled with minOpts, no merging.\n");
24373         return;
24374     }
24375
24376     if (opts.compDbgCode)
24377     {
24378         JITDUMP("Method compiled with debug codegen, no merging.\n");
24379         return;
24380     }
24381
24382     bool enableMergeFinallyChains = true;
24383
24384 #if !FEATURE_EH_FUNCLETS
24385     // For non-funclet models (x86) the callfinallys may contain
24386     // statements and the continuations contain GT_END_LFINs.  So no
24387     // merging is possible until the GT_END_LFIN blocks can be merged
24388     // and merging is not safe unless the callfinally blocks are split.
24389     JITDUMP("EH using non-funclet model; merging not yet implemented.\n");
24390     enableMergeFinallyChains = false;
24391 #endif // !FEATURE_EH_FUNCLETS
24392
24393 #if !FEATURE_EH_CALLFINALLY_THUNKS
24394     // For non-thunk EH models (arm32) the callfinallys may contain
24395     // statements, and merging is not safe unless the callfinally
24396     // blocks are split.
24397     JITDUMP("EH using non-callfinally thunk model; merging not yet implemented.\n");
24398     enableMergeFinallyChains = false;
24399 #endif
24400
24401     if (!enableMergeFinallyChains)
24402     {
24403         JITDUMP("fgMergeFinallyChains disabled\n");
24404         return;
24405     }
24406
24407 #ifdef DEBUG
24408     if (verbose)
24409     {
24410         printf("\n*************** Before fgMergeFinallyChains()\n");
24411         fgDispBasicBlocks();
24412         fgDispHandlerTab();
24413         printf("\n");
24414     }
24415 #endif // DEBUG
24416
24417     // Look for finallys.
24418     bool hasFinally = false;
24419     for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
24420     {
24421         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
24422
24423         // Check if this is a try/finally.
24424         if (HBtab->HasFinallyHandler())
24425         {
24426             hasFinally = true;
24427             break;
24428         }
24429     }
24430
24431     if (!hasFinally)
24432     {
24433         JITDUMP("Method does not have any try-finallys; no merging.\n");
24434         return;
24435     }
24436
24437     // Process finallys from outside in, merging as we go. This gives
24438     // us the desired bottom-up tail merge order for callfinally
24439     // chains: outer merges may enable inner merges.
24440     bool            canMerge = false;
24441     bool            didMerge = false;
24442     BlockToBlockMap continuationMap(getAllocator());
24443
24444     // Note XTnum is signed here so we can count down.
24445     for (int XTnum = compHndBBtabCount - 1; XTnum >= 0; XTnum--)
24446     {
24447         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
24448
24449         // Screen out non-finallys
24450         if (!HBtab->HasFinallyHandler())
24451         {
24452             continue;
24453         }
24454
24455         JITDUMP("Examining callfinallys for EH#%d.\n", XTnum);
24456
24457         // Find all the callfinallys that invoke this finally.
24458         BasicBlock* firstCallFinallyRangeBlock = nullptr;
24459         BasicBlock* endCallFinallyRangeBlock   = nullptr;
24460         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
24461
24462         // Clear out any stale entries in the continuation map
24463         continuationMap.RemoveAll();
24464
24465         // Build a map from each continuation to the "canonical"
24466         // callfinally for that continuation.
24467         unsigned          callFinallyCount  = 0;
24468         BasicBlock* const beginHandlerBlock = HBtab->ebdHndBeg;
24469
24470         for (BasicBlock* currentBlock = firstCallFinallyRangeBlock; currentBlock != endCallFinallyRangeBlock;
24471              currentBlock             = currentBlock->bbNext)
24472         {
24473             // Ignore "retless" callfinallys (where the finally doesn't return).
24474             if (currentBlock->isBBCallAlwaysPair() && (currentBlock->bbJumpDest == beginHandlerBlock))
24475             {
24476                 // The callfinally must be empty, so that we can
24477                 // safely retarget anything that branches here to
24478                 // another callfinally with the same contiuation.
24479                 assert(currentBlock->isEmpty());
24480
24481                 // This callfinally invokes the finally for this try.
24482                 callFinallyCount++;
24483
24484                 // Locate the continuation
24485                 BasicBlock* const leaveBlock        = currentBlock->bbNext;
24486                 BasicBlock* const continuationBlock = leaveBlock->bbJumpDest;
24487
24488                 // If this is the first time we've seen this
24489                 // continuation, register this callfinally as the
24490                 // canonical one.
24491                 if (!continuationMap.Lookup(continuationBlock))
24492                 {
24493                     continuationMap.Set(continuationBlock, currentBlock);
24494                 }
24495             }
24496         }
24497
24498         // Now we've seen all the callfinallys and their continuations.
24499         JITDUMP("EH#%i has %u callfinallys, %u continuations\n", XTnum, callFinallyCount, continuationMap.GetCount());
24500
24501         // If there are more callfinallys than continuations, some of the
24502         // callfinallys must share a continuation, and we can merge them.
24503         const bool tryMerge = callFinallyCount > continuationMap.GetCount();
24504
24505         if (!tryMerge)
24506         {
24507             JITDUMP("EH#%i does not have any mergeable callfinallys\n", XTnum);
24508             continue;
24509         }
24510
24511         canMerge = true;
24512
24513         // Walk the callfinally region, looking for blocks that jump
24514         // to a callfinally that invokes this try's finally, and make
24515         // sure they all jump to the appropriate canonical
24516         // callfinally.
24517         for (BasicBlock* currentBlock = firstCallFinallyRangeBlock; currentBlock != endCallFinallyRangeBlock;
24518              currentBlock             = currentBlock->bbNext)
24519         {
24520             bool merged = fgRetargetBranchesToCanonicalCallFinally(currentBlock, beginHandlerBlock, continuationMap);
24521             didMerge    = didMerge || merged;
24522         }
24523     }
24524
24525     if (!canMerge)
24526     {
24527         JITDUMP("Method had try-finallys, but did not have any mergeable finally chains.\n");
24528     }
24529     else
24530     {
24531         if (didMerge)
24532         {
24533             JITDUMP("Method had mergeable try-finallys and some callfinally merges were performed.\n");
24534
24535 #if DEBUG
24536             if (verbose)
24537             {
24538                 printf("\n*************** After fgMergeFinallyChains()\n");
24539                 fgDispBasicBlocks();
24540                 fgDispHandlerTab();
24541                 printf("\n");
24542             }
24543
24544 #endif // DEBUG
24545         }
24546         else
24547         {
24548             // We may not end up doing any merges, because we are only
24549             // merging continuations for callfinallys that can
24550             // actually be invoked, and the importer may leave
24551             // unreachable callfinallys around (for instance, if it
24552             // is forced to re-import a leave).
24553             JITDUMP("Method had mergeable try-finallys but no callfinally merges were performed,\n"
24554                     "likely the non-canonical callfinallys were unreachable\n");
24555         }
24556     }
24557 }
24558
24559 //------------------------------------------------------------------------
24560 // fgRetargetBranchesToCanonicalCallFinally: find non-canonical callfinally
24561 // invocations and make them canonical.
24562 //
24563 // Arguments:
24564 //     block -- block to examine for call finally invocation
24565 //     handler -- start of the finally region for the try
24566 //     continuationMap -- map giving the canonical callfinally for
24567 //        each continuation
24568 //
24569 // Returns:
24570 //     true iff the block's branch was retargeted.
24571
24572 bool Compiler::fgRetargetBranchesToCanonicalCallFinally(BasicBlock*      block,
24573                                                         BasicBlock*      handler,
24574                                                         BlockToBlockMap& continuationMap)
24575 {
24576     // We expect callfinallys to be invoked by a BBJ_ALWAYS at this
24577     // stage in compilation.
24578     if (block->bbJumpKind != BBJ_ALWAYS)
24579     {
24580         // Possible paranoia assert here -- no flow successor of
24581         // this block should be a callfinally for this try.
24582         return false;
24583     }
24584
24585     // Screen out cases that are not callfinallys to the right
24586     // handler.
24587     BasicBlock* const callFinally = block->bbJumpDest;
24588
24589     if (!callFinally->isBBCallAlwaysPair())
24590     {
24591         return false;
24592     }
24593
24594     if (callFinally->bbJumpDest != handler)
24595     {
24596         return false;
24597     }
24598
24599     // Ok, this is a callfinally that invokes the right handler.
24600     // Get its continuation.
24601     BasicBlock* const leaveBlock        = callFinally->bbNext;
24602     BasicBlock* const continuationBlock = leaveBlock->bbJumpDest;
24603
24604     // Find the canonical callfinally for that continuation.
24605     BasicBlock* const canonicalCallFinally = continuationMap[continuationBlock];
24606     assert(canonicalCallFinally != nullptr);
24607
24608     // If the block already jumps to the canoncial call finally, no work needed.
24609     if (block->bbJumpDest == canonicalCallFinally)
24610     {
24611         JITDUMP("BB%02u already canonical\n", block->bbNum);
24612         return false;
24613     }
24614
24615     // Else, retarget it so that it does...
24616     JITDUMP("Redirecting branch in BB%02u from BB%02u to BB%02u.\n", block->bbNum, callFinally->bbNum,
24617             canonicalCallFinally->bbNum);
24618
24619     block->bbJumpDest = canonicalCallFinally;
24620     fgAddRefPred(canonicalCallFinally, block);
24621     assert(callFinally->bbRefs > 0);
24622     fgRemoveRefPred(callFinally, block);
24623
24624     return true;
24625 }
24626
24627 // FatCalliTransformer transforms calli that can use fat function pointer.
24628 // Fat function pointer is pointer with the second least significant bit set,
24629 // if the bit is set, the pointer (after clearing the bit) actually points to
24630 // a tuple <method pointer, instantiation argument pointer> where
24631 // instantiationArgument is a hidden first argument required by method pointer.
24632 //
24633 // Fat pointers are used in CoreRT as a replacement for instantiating stubs,
24634 // because CoreRT can't generate stubs in runtime.
24635 //
24636 // Jit is responsible for the checking the bit, do the regular call if it is not set
24637 // or load hidden argument, fix the pointer and make a call with the fixed pointer and
24638 // the instantiation argument.
24639 //
24640 // before:
24641 //   current block
24642 //   {
24643 //     previous statements
24644 //     transforming statement
24645 //     {
24646 //       call with GTF_CALL_M_FAT_POINTER_CHECK flag set in function ptr
24647 //     }
24648 //     subsequent statements
24649 //   }
24650 //
24651 // after:
24652 //   current block
24653 //   {
24654 //     previous statements
24655 //   } BBJ_NONE check block
24656 //   check block
24657 //   {
24658 //     jump to else if function ptr has GTF_CALL_M_FAT_POINTER_CHECK set.
24659 //   } BBJ_COND then block, else block
24660 //   then block
24661 //   {
24662 //     original statement
24663 //   } BBJ_ALWAYS remainder block
24664 //   else block
24665 //   {
24666 //     unset GTF_CALL_M_FAT_POINTER_CHECK
24667 //     load actual function pointer
24668 //     load instantiation argument
24669 //     create newArgList = (instantiation argument, original argList)
24670 //     call (actual function pointer, newArgList)
24671 //   } BBJ_NONE remainder block
24672 //   remainder block
24673 //   {
24674 //     subsequent statements
24675 //   }
24676 //
24677 class FatCalliTransformer
24678 {
24679 public:
24680     FatCalliTransformer(Compiler* compiler) : compiler(compiler)
24681     {
24682     }
24683
24684     //------------------------------------------------------------------------
24685     // Run: run transformation for each block.
24686     //
24687     void Run()
24688     {
24689         for (BasicBlock* block = compiler->fgFirstBB; block != nullptr; block = block->bbNext)
24690         {
24691             TransformBlock(block);
24692         }
24693     }
24694
24695 private:
24696     //------------------------------------------------------------------------
24697     // TransformBlock: look through statements and transform statements with fat pointer calls.
24698     //
24699     void TransformBlock(BasicBlock* block)
24700     {
24701         for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
24702         {
24703             if (ContainsFatCalli(stmt))
24704             {
24705                 StatementTransformer stmtTransformer(compiler, block, stmt);
24706                 stmtTransformer.Run();
24707             }
24708         }
24709     }
24710
24711     //------------------------------------------------------------------------
24712     // ContainsFatCalli: check does this statement contain fat pointer call.
24713     //
24714     // Checks fatPointerCandidate in form of call() or lclVar = call().
24715     //
24716     // Return Value:
24717     //    true if contains, false otherwise.
24718     //
24719     bool ContainsFatCalli(GenTreeStmt* stmt)
24720     {
24721         GenTreePtr fatPointerCandidate = stmt->gtStmtExpr;
24722         if (fatPointerCandidate->OperIsAssignment())
24723         {
24724             fatPointerCandidate = fatPointerCandidate->gtGetOp2();
24725         }
24726         return fatPointerCandidate->IsCall() && fatPointerCandidate->AsCall()->IsFatPointerCandidate();
24727     }
24728
24729     class StatementTransformer
24730     {
24731     public:
24732         StatementTransformer(Compiler* compiler, BasicBlock* block, GenTreeStmt* stmt)
24733             : compiler(compiler), currBlock(block), stmt(stmt)
24734         {
24735             remainderBlock  = nullptr;
24736             checkBlock      = nullptr;
24737             thenBlock       = nullptr;
24738             elseBlock       = nullptr;
24739             doesReturnValue = stmt->gtStmtExpr->OperIsAssignment();
24740             origCall        = GetCall(stmt);
24741             fptrAddress     = origCall->gtCallAddr;
24742             pointerType     = fptrAddress->TypeGet();
24743         }
24744
24745         //------------------------------------------------------------------------
24746         // Run: transform the statement as described above.
24747         //
24748         void Run()
24749         {
24750             ClearFatFlag();
24751             CreateRemainder();
24752             CreateCheck();
24753             CreateThen();
24754             CreateElse();
24755
24756             RemoveOldStatement();
24757             SetWeights();
24758             ChainFlow();
24759         }
24760
24761     private:
24762         //------------------------------------------------------------------------
24763         // GetCall: find a call in a statement.
24764         //
24765         // Arguments:
24766         //    callStmt - the statement with the call inside.
24767         //
24768         // Return Value:
24769         //    call tree node pointer.
24770         GenTreeCall* GetCall(GenTreeStmt* callStmt)
24771         {
24772             GenTreePtr   tree = callStmt->gtStmtExpr;
24773             GenTreeCall* call = nullptr;
24774             if (doesReturnValue)
24775             {
24776                 assert(tree->OperIsAssignment());
24777                 call = tree->gtGetOp2()->AsCall();
24778             }
24779             else
24780             {
24781                 call = tree->AsCall(); // call with void return type.
24782             }
24783             return call;
24784         }
24785
24786         //------------------------------------------------------------------------
24787         // ClearFatFlag: clear fat pointer candidate flag from the original call.
24788         //
24789         void ClearFatFlag()
24790         {
24791             origCall->ClearFatPointerCandidate();
24792         }
24793
24794         //------------------------------------------------------------------------
24795         // CreateRemainder: split current block at the fat call stmt and
24796         // insert statements after the call into remainderBlock.
24797         //
24798         void CreateRemainder()
24799         {
24800             remainderBlock          = compiler->fgSplitBlockAfterStatement(currBlock, stmt);
24801             unsigned propagateFlags = currBlock->bbFlags & BBF_GC_SAFE_POINT;
24802             remainderBlock->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL | propagateFlags;
24803         }
24804
24805         //------------------------------------------------------------------------
24806         // CreateCheck: create check block, that checks fat pointer bit set.
24807         //
24808         void CreateCheck()
24809         {
24810             checkBlock                 = CreateAndInsertBasicBlock(BBJ_COND, currBlock);
24811             GenTreePtr fatPointerMask  = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, FAT_POINTER_MASK);
24812             GenTreePtr fptrAddressCopy = compiler->gtCloneExpr(fptrAddress);
24813             GenTreePtr fatPointerAnd   = compiler->gtNewOperNode(GT_AND, TYP_I_IMPL, fptrAddressCopy, fatPointerMask);
24814             GenTreePtr zero            = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, 0);
24815             GenTreePtr fatPointerCmp   = compiler->gtNewOperNode(GT_NE, TYP_INT, fatPointerAnd, zero);
24816             GenTreePtr jmpTree         = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, fatPointerCmp);
24817             GenTreePtr jmpStmt         = compiler->fgNewStmtFromTree(jmpTree, stmt->gtStmt.gtStmtILoffsx);
24818             compiler->fgInsertStmtAtEnd(checkBlock, jmpStmt);
24819         }
24820
24821         //------------------------------------------------------------------------
24822         // CreateCheck: create then block, that is executed if call address is not fat pointer.
24823         //
24824         void CreateThen()
24825         {
24826             thenBlock                 = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock);
24827             GenTreePtr nonFatCallStmt = compiler->gtCloneExpr(stmt)->AsStmt();
24828             compiler->fgInsertStmtAtEnd(thenBlock, nonFatCallStmt);
24829         }
24830
24831         //------------------------------------------------------------------------
24832         // CreateCheck: create else block, that is executed if call address is fat pointer.
24833         //
24834         void CreateElse()
24835         {
24836             elseBlock = CreateAndInsertBasicBlock(BBJ_NONE, thenBlock);
24837
24838             GenTreePtr fixedFptrAddress  = GetFixedFptrAddress();
24839             GenTreePtr actualCallAddress = compiler->gtNewOperNode(GT_IND, pointerType, fixedFptrAddress);
24840             GenTreePtr hiddenArgument    = GetHiddenArgument(fixedFptrAddress);
24841
24842             GenTreeStmt* fatStmt = CreateFatCallStmt(actualCallAddress, hiddenArgument);
24843             compiler->fgInsertStmtAtEnd(elseBlock, fatStmt);
24844         }
24845
24846         //------------------------------------------------------------------------
24847         // CreateAndInsertBasicBlock: ask compiler to create new basic block.
24848         // and insert in into the basic block list.
24849         //
24850         // Arguments:
24851         //    jumpKind - jump kind for the new basic block
24852         //    insertAfter - basic block, after which compiler has to insert the new one.
24853         //
24854         // Return Value:
24855         //    new basic block.
24856         BasicBlock* CreateAndInsertBasicBlock(BBjumpKinds jumpKind, BasicBlock* insertAfter)
24857         {
24858             BasicBlock* block = compiler->fgNewBBafter(jumpKind, insertAfter, true);
24859             if ((insertAfter->bbFlags & BBF_INTERNAL) == 0)
24860             {
24861                 block->bbFlags &= ~BBF_INTERNAL;
24862                 block->bbFlags |= BBF_IMPORTED;
24863             }
24864             return block;
24865         }
24866
24867         //------------------------------------------------------------------------
24868         // GetFixedFptrAddress: clear fat pointer bit from fat pointer address.
24869         //
24870         // Return Value:
24871         //    address without fat pointer bit set.
24872         GenTreePtr GetFixedFptrAddress()
24873         {
24874             GenTreePtr fptrAddressCopy = compiler->gtCloneExpr(fptrAddress);
24875             GenTreePtr fatPointerMask  = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, FAT_POINTER_MASK);
24876             return compiler->gtNewOperNode(GT_XOR, pointerType, fptrAddressCopy, fatPointerMask);
24877         }
24878
24879         //------------------------------------------------------------------------
24880         // GetHiddenArgument: load hidden argument.
24881         //
24882         // Arguments:
24883         //    fixedFptrAddress - pointer to the tuple <methodPointer, instantiationArgumentPointer>
24884         //
24885         // Return Value:
24886         //    generic context hidden argument.
24887         GenTreePtr GetHiddenArgument(GenTreePtr fixedFptrAddress)
24888         {
24889             GenTreePtr fixedFptrAddressCopy = compiler->gtCloneExpr(fixedFptrAddress);
24890             GenTreePtr wordSize = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, genTypeSize(TYP_I_IMPL));
24891             GenTreePtr hiddenArgumentPtrPtr =
24892                 compiler->gtNewOperNode(GT_ADD, pointerType, fixedFptrAddressCopy, wordSize);
24893             GenTreePtr hiddenArgumentPtr = compiler->gtNewOperNode(GT_IND, pointerType, hiddenArgumentPtrPtr);
24894             return compiler->gtNewOperNode(GT_IND, fixedFptrAddressCopy->TypeGet(), hiddenArgumentPtr);
24895         }
24896
24897         //------------------------------------------------------------------------
24898         // CreateFatCallStmt: create call with fixed call address and hidden argument in the args list.
24899         //
24900         // Arguments:
24901         //    actualCallAddress - fixed call address
24902         //    hiddenArgument - generic context hidden argument
24903         //
24904         // Return Value:
24905         //    created call node.
24906         GenTreeStmt* CreateFatCallStmt(GenTreePtr actualCallAddress, GenTreePtr hiddenArgument)
24907         {
24908             GenTreeStmt* fatStmt = compiler->gtCloneExpr(stmt)->AsStmt();
24909             GenTreePtr   fatTree = fatStmt->gtStmtExpr;
24910             GenTreeCall* fatCall = GetCall(fatStmt);
24911             fatCall->gtCallAddr  = actualCallAddress;
24912             AddHiddenArgument(fatCall, hiddenArgument);
24913             return fatStmt;
24914         }
24915
24916         //------------------------------------------------------------------------
24917         // AddHiddenArgument: add hidden argument to the call argument list.
24918         //
24919         // Arguments:
24920         //    fatCall - fat call node
24921         //    hiddenArgument - generic context hidden argument
24922         //
24923         void AddHiddenArgument(GenTreeCall* fatCall, GenTreePtr hiddenArgument)
24924         {
24925             GenTreeArgList* oldArgs = fatCall->gtCallArgs;
24926             GenTreeArgList* newArgs;
24927 #if USER_ARGS_COME_LAST
24928             if (fatCall->HasRetBufArg())
24929             {
24930                 GenTreePtr      retBuffer = oldArgs->Current();
24931                 GenTreeArgList* rest      = oldArgs->Rest();
24932                 newArgs                   = compiler->gtNewListNode(hiddenArgument, rest);
24933                 newArgs                   = compiler->gtNewListNode(retBuffer, newArgs);
24934             }
24935             else
24936             {
24937                 newArgs = compiler->gtNewListNode(hiddenArgument, oldArgs);
24938             }
24939 #else
24940             newArgs = oldArgs;
24941             AddArgumentToTail(newArgs, hiddenArgument);
24942 #endif
24943             fatCall->gtCallArgs = newArgs;
24944         }
24945
24946         //------------------------------------------------------------------------
24947         // AddArgumentToTail: add hidden argument to the tail of the call argument list.
24948         //
24949         // Arguments:
24950         //    argList - fat call node
24951         //    hiddenArgument - generic context hidden argument
24952         //
24953         void AddArgumentToTail(GenTreeArgList* argList, GenTreePtr hiddenArgument)
24954         {
24955             GenTreeArgList* iterator = argList;
24956             while (iterator->Rest() != nullptr)
24957             {
24958                 iterator = iterator->Rest();
24959             }
24960             iterator->Rest() = compiler->gtNewArgList(hiddenArgument);
24961         }
24962
24963         //------------------------------------------------------------------------
24964         // RemoveOldStatement: remove original stmt from current block.
24965         //
24966         void RemoveOldStatement()
24967         {
24968             compiler->fgRemoveStmt(currBlock, stmt);
24969         }
24970
24971         //------------------------------------------------------------------------
24972         // SetWeights: set weights for new blocks.
24973         //
24974         void SetWeights()
24975         {
24976             remainderBlock->inheritWeight(currBlock);
24977             checkBlock->inheritWeight(currBlock);
24978             thenBlock->inheritWeightPercentage(currBlock, HIGH_PROBABILITY);
24979             elseBlock->inheritWeightPercentage(currBlock, 100 - HIGH_PROBABILITY);
24980         }
24981
24982         //------------------------------------------------------------------------
24983         // ChainFlow: link new blocks into correct cfg.
24984         //
24985         void ChainFlow()
24986         {
24987             assert(!compiler->fgComputePredsDone);
24988             checkBlock->bbJumpDest = elseBlock;
24989             thenBlock->bbJumpDest  = remainderBlock;
24990         }
24991
24992         Compiler*    compiler;
24993         BasicBlock*  currBlock;
24994         BasicBlock*  remainderBlock;
24995         BasicBlock*  checkBlock;
24996         BasicBlock*  thenBlock;
24997         BasicBlock*  elseBlock;
24998         GenTreeStmt* stmt;
24999         GenTreeCall* origCall;
25000         GenTreePtr   fptrAddress;
25001         var_types    pointerType;
25002         bool         doesReturnValue;
25003
25004         const int FAT_POINTER_MASK = 0x2;
25005         const int HIGH_PROBABILITY = 80;
25006     };
25007
25008     Compiler* compiler;
25009 };
25010
25011 #ifdef DEBUG
25012
25013 //------------------------------------------------------------------------
25014 // fgDebugCheckFatPointerCandidates: callback to make sure there are no more GTF_CALL_M_FAT_POINTER_CHECK calls.
25015 //
25016 Compiler::fgWalkResult Compiler::fgDebugCheckFatPointerCandidates(GenTreePtr* pTree, fgWalkData* data)
25017 {
25018     GenTreePtr tree = *pTree;
25019     if (tree->IsCall())
25020     {
25021         assert(!tree->AsCall()->IsFatPointerCandidate());
25022     }
25023     return WALK_CONTINUE;
25024 }
25025
25026 //------------------------------------------------------------------------
25027 // CheckNoFatPointerCandidatesLeft: walk through blocks and check that there are no fat pointer candidates left.
25028 //
25029 void Compiler::CheckNoFatPointerCandidatesLeft()
25030 {
25031     assert(!doesMethodHaveFatPointer());
25032     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25033     {
25034         for (GenTreeStmt* stmt = fgFirstBB->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
25035         {
25036             fgWalkTreePre(&stmt->gtStmtExpr, fgDebugCheckFatPointerCandidates);
25037         }
25038     }
25039 }
25040 #endif
25041
25042 //------------------------------------------------------------------------
25043 // fgTransformFatCalli: find and transform fat calls.
25044 //
25045 void Compiler::fgTransformFatCalli()
25046 {
25047     assert(IsTargetAbi(CORINFO_CORERT_ABI));
25048     FatCalliTransformer fatCalliTransformer(this);
25049     fatCalliTransformer.Run();
25050     clearMethodHasFatPointer();
25051 #ifdef DEBUG
25052     CheckNoFatPointerCandidatesLeft();
25053 #endif
25054 }
25055
25056 //------------------------------------------------------------------------
25057 // fgMeasureIR: count and return the number of IR nodes in the function.
25058 //
25059 unsigned Compiler::fgMeasureIR()
25060 {
25061     unsigned nodeCount = 0;
25062
25063     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25064     {
25065         if (!block->IsLIR())
25066         {
25067             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt())
25068             {
25069                 fgWalkTreePre(&stmt->gtStmtExpr,
25070                               [](GenTree** slot, fgWalkData* data) -> Compiler::fgWalkResult {
25071                                   (*reinterpret_cast<unsigned*>(data->pCallbackData))++;
25072                                   return Compiler::WALK_CONTINUE;
25073                               },
25074                               &nodeCount);
25075             }
25076         }
25077         else
25078         {
25079             for (GenTree* node : LIR::AsRange(block))
25080             {
25081                 nodeCount++;
25082             }
25083         }
25084     }
25085
25086     return nodeCount;
25087 }
25088
25089 //------------------------------------------------------------------------
25090 // fgCompDominatedByExceptionalEntryBlocks: compute blocks that are
25091 // dominated by not normal entry.
25092 //
25093 void Compiler::fgCompDominatedByExceptionalEntryBlocks()
25094 {
25095     assert(fgEnterBlksSetValid);
25096     if (BlockSetOps::Count(this, fgEnterBlks) != 1) // There are exception entries.
25097     {
25098         for (unsigned i = 1; i <= fgBBNumMax; ++i)
25099         {
25100             BasicBlock* block = fgBBInvPostOrder[i];
25101             if (BlockSetOps::IsMember(this, fgEnterBlks, block->bbNum))
25102             {
25103                 if (fgFirstBB != block) // skip the normal entry.
25104                 {
25105                     block->SetDominatedByExceptionalEntryFlag();
25106                 }
25107             }
25108             else if (block->bbIDom->IsDominatedByExceptionalEntryFlag())
25109             {
25110                 block->SetDominatedByExceptionalEntryFlag();
25111             }
25112         }
25113     }
25114 }