Fix reading Time zone rules using Julian days (#17672)
[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 #ifndef LEGACY_BACKEND
21 #include "lower.h" // for LowerRange()
22 #endif
23
24 /*****************************************************************************/
25
26 void Compiler::fgInit()
27 {
28     impInit();
29
30     /* Initialization for fgWalkTreePre() and fgWalkTreePost() */
31
32     fgFirstBBScratch = nullptr;
33
34 #ifdef DEBUG
35     fgPrintInlinedMethods = JitConfig.JitPrintInlinedMethods() == 1;
36 #endif // DEBUG
37
38     /* We haven't yet computed the bbPreds lists */
39     fgComputePredsDone = false;
40
41     /* We haven't yet computed the bbCheapPreds lists */
42     fgCheapPredsValid = false;
43
44     /* We haven't yet computed the edge weight */
45     fgEdgeWeightsComputed    = false;
46     fgHaveValidEdgeWeights   = false;
47     fgSlopUsedInEdgeWeights  = false;
48     fgRangeUsedInEdgeWeights = true;
49     fgNeedsUpdateFlowGraph   = false;
50     fgCalledCount            = BB_ZERO_WEIGHT;
51
52     /* We haven't yet computed the dominator sets */
53     fgDomsComputed = false;
54
55 #ifdef DEBUG
56     fgReachabilitySetsValid = false;
57 #endif // DEBUG
58
59     /* We don't know yet which loops will always execute calls */
60     fgLoopCallMarked = false;
61
62     /* We haven't created GC Poll blocks yet. */
63     fgGCPollsCreated = false;
64
65     /* Initialize the basic block list */
66
67     fgFirstBB        = nullptr;
68     fgLastBB         = nullptr;
69     fgFirstColdBlock = nullptr;
70
71 #if FEATURE_EH_FUNCLETS
72     fgFirstFuncletBB  = nullptr;
73     fgFuncletsCreated = false;
74 #endif // FEATURE_EH_FUNCLETS
75
76     fgBBcount = 0;
77
78 #ifdef DEBUG
79     fgBBcountAtCodegen = 0;
80 #endif // DEBUG
81
82     fgBBNumMax        = 0;
83     fgEdgeCount       = 0;
84     fgDomBBcount      = 0;
85     fgBBVarSetsInited = false;
86     fgReturnCount     = 0;
87
88     // Initialize BlockSet data.
89     fgCurBBEpoch             = 0;
90     fgCurBBEpochSize         = 0;
91     fgBBSetCountInSizeTUnits = 0;
92
93     genReturnBB = nullptr;
94
95     /* We haven't reached the global morphing phase */
96     fgGlobalMorph = false;
97     fgModified    = false;
98
99 #ifdef DEBUG
100     fgSafeBasicBlockCreation = true;
101 #endif // DEBUG
102
103     fgLocalVarLivenessDone = false;
104
105     /* Statement list is not threaded yet */
106
107     fgStmtListThreaded = false;
108
109     // Initialize the logic for adding code. This is used to insert code such
110     // as the code that raises an exception when an array range check fails.
111
112     fgAddCodeList = nullptr;
113     fgAddCodeModf = false;
114
115     for (int i = 0; i < SCK_COUNT; i++)
116     {
117         fgExcptnTargetCache[i] = nullptr;
118     }
119
120     /* Keep track of the max count of pointer arguments */
121
122     fgPtrArgCntCur = 0;
123     fgPtrArgCntMax = 0;
124
125     /* This global flag is set whenever we remove a statement */
126     fgStmtRemoved = false;
127
128     /* This global flag is set whenever we add a throw block for a RngChk */
129     fgRngChkThrowAdded = false; /* reset flag for fgIsCodeAdded() */
130
131     fgIncrCount = 0;
132
133     /* We will record a list of all BBJ_RETURN blocks here */
134     fgReturnBlocks = nullptr;
135
136     /* This is set by fgComputeReachability */
137     fgEnterBlks = BlockSetOps::UninitVal();
138
139 #ifdef DEBUG
140     fgEnterBlksSetValid = false;
141 #endif // DEBUG
142
143 #if !FEATURE_EH_FUNCLETS
144     ehMaxHndNestingCount = 0;
145 #endif // !FEATURE_EH_FUNCLETS
146
147     /* Init the fgBigOffsetMorphingTemps to be BAD_VAR_NUM. */
148     for (int i = 0; i < TYP_COUNT; i++)
149     {
150         fgBigOffsetMorphingTemps[i] = BAD_VAR_NUM;
151     }
152
153     fgNoStructPromotion      = false;
154     fgNoStructParamPromotion = false;
155
156     optValnumCSE_phase = false; // referenced in fgMorphSmpOp()
157
158 #ifdef DEBUG
159     fgNormalizeEHDone = false;
160 #endif // DEBUG
161
162 #ifdef DEBUG
163     if (!compIsForInlining())
164     {
165         if ((JitConfig.JitNoStructPromotion() & 1) == 1)
166         {
167             fgNoStructPromotion = true;
168         }
169         if ((JitConfig.JitNoStructPromotion() & 2) == 2)
170         {
171             fgNoStructParamPromotion = true;
172         }
173     }
174 #endif // DEBUG
175
176     if (!compIsForInlining())
177     {
178         m_promotedStructDeathVars = nullptr;
179     }
180 #ifdef FEATURE_SIMD
181     fgPreviousCandidateSIMDFieldAsgStmt = nullptr;
182 #endif
183 }
184
185 bool Compiler::fgHaveProfileData()
186 {
187     if (compIsForInlining() || compIsForImportOnly())
188     {
189         return false;
190     }
191
192     return (fgProfileBuffer != nullptr);
193 }
194
195 bool Compiler::fgGetProfileWeightForBasicBlock(IL_OFFSET offset, unsigned* weightWB)
196 {
197     noway_assert(weightWB != nullptr);
198     unsigned weight = 0;
199
200 #ifdef DEBUG
201     unsigned hashSeed = fgStressBBProf();
202     if (hashSeed != 0)
203     {
204         unsigned hash = (info.compMethodHash() * hashSeed) ^ (offset * 1027);
205
206         // We need to especially stress the procedure splitting codepath.  Therefore
207         // one third the time we should return a weight of zero.
208         // Otherwise we should return some random weight (usually between 0 and 288).
209         // The below gives a weight of zero, 44% of the time
210
211         if (hash % 3 == 0)
212         {
213             weight = 0;
214         }
215         else if (hash % 11 == 0)
216         {
217             weight = (hash % 23) * (hash % 29) * (hash % 31);
218         }
219         else
220         {
221             weight = (hash % 17) * (hash % 19);
222         }
223
224         // The first block is never given a weight of zero
225         if ((offset == 0) && (weight == 0))
226         {
227             weight = 1 + (hash % 5);
228         }
229
230         *weightWB = weight;
231         return true;
232     }
233 #endif // DEBUG
234
235     if (fgHaveProfileData() == false)
236     {
237         return false;
238     }
239
240     noway_assert(!compIsForInlining());
241     for (unsigned i = 0; i < fgProfileBufferCount; i++)
242     {
243         if (fgProfileBuffer[i].ILOffset == offset)
244         {
245             weight = fgProfileBuffer[i].ExecutionCount;
246
247             *weightWB = weight;
248             return true;
249         }
250     }
251
252     *weightWB = 0;
253     return true;
254 }
255
256 void Compiler::fgInstrumentMethod()
257 {
258     noway_assert(!compIsForInlining());
259
260     // Count the number of basic blocks in the method
261
262     int         countOfBlocks = 0;
263     BasicBlock* block;
264     for (block = fgFirstBB; (block != nullptr); block = block->bbNext)
265     {
266         if (!(block->bbFlags & BBF_IMPORTED) || (block->bbFlags & BBF_INTERNAL))
267         {
268             continue;
269         }
270         countOfBlocks++;
271     }
272
273     // Allocate the profile buffer
274
275     ICorJitInfo::ProfileBuffer* bbProfileBufferStart;
276
277     HRESULT res = info.compCompHnd->allocBBProfileBuffer(countOfBlocks, &bbProfileBufferStart);
278
279     GenTree* 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             GenTree*        call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, 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         // For each BasicBlock (non-Internal)
302         //  1. Assign the blocks bbCodeOffs to the ILOffset field of this blocks profile data.
303         //  2. Add an operation that increments the ExecutionCount field at the beginning of the block.
304
305         // Each (non-Internal) block has it own ProfileBuffer tuple [ILOffset, ExecutionCount]
306         // To start we initialize our current one with the first one that we allocated
307         //
308         ICorJitInfo::ProfileBuffer* bbCurrentBlockProfileBuffer = bbProfileBufferStart;
309
310         for (block = fgFirstBB; (block != nullptr); block = block->bbNext)
311         {
312             if (!(block->bbFlags & BBF_IMPORTED) || (block->bbFlags & BBF_INTERNAL))
313             {
314                 continue;
315             }
316
317             // Assign the current block's IL offset into the profile data
318             bbCurrentBlockProfileBuffer->ILOffset = block->bbCodeOffs;
319             assert(bbCurrentBlockProfileBuffer->ExecutionCount == 0); // This value should already be zero-ed out
320
321             size_t addrOfCurrentExecutionCount = (size_t)&bbCurrentBlockProfileBuffer->ExecutionCount;
322
323             // Read Basic-Block count value
324             GenTree* valueNode =
325                 gtNewIndOfIconHandleNode(TYP_INT, addrOfCurrentExecutionCount, GTF_ICON_BBC_PTR, false);
326
327             // Increment value by 1
328             GenTree* rhsNode = gtNewOperNode(GT_ADD, TYP_INT, valueNode, gtNewIconNode(1));
329
330             // Write new Basic-Block count value
331             GenTree* lhsNode = gtNewIndOfIconHandleNode(TYP_INT, addrOfCurrentExecutionCount, GTF_ICON_BBC_PTR, false);
332             GenTree* asgNode = gtNewAssignNode(lhsNode, rhsNode);
333
334             fgInsertStmtAtBeg(block, asgNode);
335
336             // Advance to the next ProfileBuffer tuple [ILOffset, ExecutionCount]
337             bbCurrentBlockProfileBuffer++;
338
339             // One less block
340             countOfBlocks--;
341         }
342         // Check that we allocated and initialized the same number of ProfileBuffer tuples
343         noway_assert(countOfBlocks == 0);
344
345         // Add the method entry callback node
346
347         GenTree* arg;
348
349 #ifdef FEATURE_READYTORUN_COMPILER
350         if (opts.IsReadyToRun())
351         {
352             mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd);
353
354             CORINFO_RESOLVED_TOKEN resolvedToken;
355             resolvedToken.tokenContext = MAKE_METHODCONTEXT(info.compMethodHnd);
356             resolvedToken.tokenScope   = info.compScopeHnd;
357             resolvedToken.token        = currentMethodToken;
358             resolvedToken.tokenType    = CORINFO_TOKENKIND_Method;
359
360             info.compCompHnd->resolveToken(&resolvedToken);
361
362             arg = impTokenToHandle(&resolvedToken);
363         }
364         else
365 #endif
366         {
367             arg = gtNewIconEmbMethHndNode(info.compMethodHnd);
368         }
369
370         GenTreeArgList* args = gtNewArgList(arg);
371         GenTree*        call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, args);
372
373         // Get the address of the first blocks ExecutionCount
374         size_t addrOfFirstExecutionCount = (size_t)&bbProfileBufferStart->ExecutionCount;
375
376         // Read Basic-Block count value
377         GenTree* valueNode = gtNewIndOfIconHandleNode(TYP_INT, addrOfFirstExecutionCount, GTF_ICON_BBC_PTR, false);
378
379         // Compare Basic-Block count value against zero
380         GenTree* relop = gtNewOperNode(GT_NE, TYP_INT, valueNode, gtNewIconNode(0, TYP_INT));
381         relop->gtFlags |= GTF_RELOP_QMARK; // TODO-Cleanup: [Simple]  Move this to gtNewQmarkNode
382         GenTree* colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), call);
383         GenTree* cond  = gtNewQmarkNode(TYP_VOID, relop, colon);
384         stmt           = gtNewStmt(cond);
385     }
386
387     fgEnsureFirstBBisScratch();
388
389     fgInsertStmtAtEnd(fgFirstBB, stmt);
390 }
391
392 /*****************************************************************************
393  *
394  *  Create a basic block and append it to the current BB list.
395  */
396
397 BasicBlock* Compiler::fgNewBasicBlock(BBjumpKinds jumpKind)
398 {
399     // This method must not be called after the exception table has been
400     // constructed, because it doesn't not provide support for patching
401     // the exception table.
402
403     noway_assert(compHndBBtabCount == 0);
404
405     BasicBlock* block;
406
407     /* Allocate the block descriptor */
408
409     block = bbNewBasicBlock(jumpKind);
410     noway_assert(block->bbJumpKind == jumpKind);
411
412     /* Append the block to the end of the global basic block list */
413
414     if (fgFirstBB)
415     {
416         fgLastBB->setNext(block);
417     }
418     else
419     {
420         fgFirstBB     = block;
421         block->bbPrev = nullptr;
422     }
423
424     fgLastBB = block;
425
426     return block;
427 }
428
429 /*****************************************************************************
430  *
431  *  Ensures that fgFirstBB is a scratch BasicBlock that we have added.
432  *  This can be used to add initialization code (without worrying
433  *  about other blocks jumping to it).
434  *
435  *  Callers have to be careful that they do not mess up the order of things
436  *  added to fgEnsureFirstBBisScratch in a way as to change semantics.
437  */
438
439 void Compiler::fgEnsureFirstBBisScratch()
440 {
441     // This method does not update predecessor lists and so must only be called before they are computed.
442     assert(!fgComputePredsDone);
443
444     // Have we already allocated a scratch block?
445
446     if (fgFirstBBisScratch())
447     {
448         return;
449     }
450
451     assert(fgFirstBBScratch == nullptr);
452
453     BasicBlock* block = bbNewBasicBlock(BBJ_NONE);
454
455     if (fgFirstBB != nullptr)
456     {
457         // If we have profile data the new block will inherit fgFirstBlock's weight
458         if (fgFirstBB->hasProfileWeight())
459         {
460             block->inheritWeight(fgFirstBB);
461         }
462
463         fgInsertBBbefore(fgFirstBB, block);
464     }
465     else
466     {
467         noway_assert(fgLastBB == nullptr);
468         fgFirstBB = block;
469         fgLastBB  = block;
470     }
471
472     noway_assert(fgLastBB != nullptr);
473
474     block->bbFlags |= (BBF_INTERNAL | BBF_IMPORTED);
475
476     fgFirstBBScratch = fgFirstBB;
477
478 #ifdef DEBUG
479     if (verbose)
480     {
481         printf("New scratch BB%02u\n", block->bbNum);
482     }
483 #endif
484 }
485
486 bool Compiler::fgFirstBBisScratch()
487 {
488     if (fgFirstBBScratch != nullptr)
489     {
490         assert(fgFirstBBScratch == fgFirstBB);
491         assert(fgFirstBBScratch->bbFlags & BBF_INTERNAL);
492         assert(fgFirstBBScratch->countOfInEdges() == 1);
493
494         // Normally, the first scratch block is a fall-through block. However, if the block after it was an empty
495         // BBJ_ALWAYS block, it might get removed, and the code that removes it will make the first scratch block
496         // a BBJ_ALWAYS block.
497         assert((fgFirstBBScratch->bbJumpKind == BBJ_NONE) || (fgFirstBBScratch->bbJumpKind == BBJ_ALWAYS));
498
499         return true;
500     }
501     else
502     {
503         return false;
504     }
505 }
506
507 bool Compiler::fgBBisScratch(BasicBlock* block)
508 {
509     return fgFirstBBisScratch() && (block == fgFirstBB);
510 }
511
512 #ifdef DEBUG
513 // Check to see if block contains a statement but don't spend more than a certain
514 // budget doing this per method compiled.
515 // If the budget is exceeded, return 'answerOnBoundExceeded' as the answer.
516 /* static */
517 bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, bool answerOnBoundExceeded /*= true*/)
518 {
519     const __int64 maxLinks = 1000000000;
520
521     assert(stmt->gtOper == GT_STMT);
522
523     __int64* numTraversed = &JitTls::GetCompiler()->compNumStatementLinksTraversed;
524
525     if (*numTraversed > maxLinks)
526     {
527         return answerOnBoundExceeded;
528     }
529
530     GenTree* curr = block->firstStmt();
531     do
532     {
533         (*numTraversed)++;
534         if (curr == stmt)
535         {
536             break;
537         }
538         curr = curr->gtNext;
539     } while (curr);
540     return curr != nullptr;
541 }
542 #endif // DEBUG
543
544 //------------------------------------------------------------------------
545 // fgInsertStmtAtBeg: Insert the given tree or statement at the start of the given basic block.
546 //
547 // Arguments:
548 //    block     - The block into which 'stmt' will be inserted.
549 //    stmt      - The statement to be inserted.
550 //
551 // Return Value:
552 //    Returns the new (potentially) GT_STMT node.
553 //
554 // Notes:
555 //    If 'stmt' is not already a statement, a new statement is created from it.
556 //    We always insert phi statements at the beginning.
557 //    In other cases, if there are any phi assignments and/or an assignment of
558 //    the GT_CATCH_ARG, we insert after those.
559
560 GenTree* Compiler::fgInsertStmtAtBeg(BasicBlock* block, GenTree* stmt)
561 {
562     if (stmt->gtOper != GT_STMT)
563     {
564         stmt = gtNewStmt(stmt);
565     }
566
567     GenTree* list = block->firstStmt();
568
569     if (!stmt->IsPhiDefnStmt())
570     {
571         GenTree* insertBeforeStmt = block->FirstNonPhiDefOrCatchArgAsg();
572         if (insertBeforeStmt != nullptr)
573         {
574             return fgInsertStmtBefore(block, insertBeforeStmt, stmt);
575         }
576         else if (list != nullptr)
577         {
578             return fgInsertStmtAtEnd(block, stmt);
579         }
580         // Otherwise, we will simply insert at the beginning, below.
581     }
582
583     /* The new tree will now be the first one of the block */
584
585     block->bbTreeList = stmt;
586     stmt->gtNext      = list;
587
588     /* Are there any statements in the block? */
589
590     if (list)
591     {
592         GenTree* last;
593
594         /* There is at least one statement already */
595
596         last = list->gtPrev;
597         noway_assert(last && last->gtNext == nullptr);
598
599         /* Insert the statement in front of the first one */
600
601         list->gtPrev = stmt;
602         stmt->gtPrev = last;
603     }
604     else
605     {
606         /* The block was completely empty */
607
608         stmt->gtPrev = stmt;
609     }
610
611     return stmt;
612 }
613
614 /*****************************************************************************
615  *
616  *  Insert the given tree or statement at the end of the given basic block.
617  *  Returns the (potentially) new GT_STMT node.
618  *  If the block can be a conditional block, use fgInsertStmtNearEnd.
619  */
620
621 GenTreeStmt* Compiler::fgInsertStmtAtEnd(BasicBlock* block, GenTree* node)
622 {
623     GenTree*     list = block->firstStmt();
624     GenTreeStmt* stmt;
625
626     if (node->gtOper != GT_STMT)
627     {
628         stmt = gtNewStmt(node);
629     }
630     else
631     {
632         stmt = node->AsStmt();
633     }
634
635     assert(stmt->gtNext == nullptr); // We don't set it, and it needs to be this after the insert
636
637     if (list)
638     {
639         GenTree* last;
640
641         /* There is at least one statement already */
642
643         last = list->gtPrev;
644         noway_assert(last && last->gtNext == nullptr);
645
646         /* Append the statement after the last one */
647
648         last->gtNext = stmt;
649         stmt->gtPrev = last;
650         list->gtPrev = stmt;
651     }
652     else
653     {
654         /* The block is completely empty */
655
656         block->bbTreeList = stmt;
657         stmt->gtPrev      = stmt;
658     }
659
660     return stmt;
661 }
662
663 /*****************************************************************************
664  *
665  *  Insert the given tree or statement at the end of the given basic block, but before
666  *  the GT_JTRUE, if present.
667  *  Returns the (potentially) new GT_STMT node.
668  */
669
670 GenTreeStmt* Compiler::fgInsertStmtNearEnd(BasicBlock* block, GenTree* node)
671 {
672     GenTreeStmt* stmt;
673
674     // This routine can only be used when in tree order.
675     assert(fgOrder == FGOrderTree);
676
677     if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN))
678     {
679         if (node->gtOper != GT_STMT)
680         {
681             stmt = gtNewStmt(node);
682         }
683         else
684         {
685             stmt = node->AsStmt();
686         }
687
688         GenTreeStmt* first = block->firstStmt();
689         noway_assert(first);
690         GenTreeStmt* last = block->lastStmt();
691         noway_assert(last && last->gtNext == nullptr);
692         GenTree* after = last->gtPrev;
693
694 #if DEBUG
695         if (block->bbJumpKind == BBJ_COND)
696         {
697             noway_assert(last->gtStmtExpr->gtOper == GT_JTRUE);
698         }
699         else if (block->bbJumpKind == BBJ_RETURN)
700         {
701             noway_assert((last->gtStmtExpr->gtOper == GT_RETURN) || (last->gtStmtExpr->gtOper == GT_JMP) ||
702                          // BBJ_RETURN blocks in functions returning void do not get a GT_RETURN node if they
703                          // have a .tail prefix (even if canTailCall returns false for these calls)
704                          // code:Compiler::impImportBlockCode (search for the RET: label)
705                          // Ditto for real tail calls (all code after them has been removed)
706                          ((last->gtStmtExpr->gtOper == GT_CALL) &&
707                           ((info.compRetType == TYP_VOID) || last->gtStmtExpr->AsCall()->IsTailCall())));
708         }
709         else
710         {
711             noway_assert(block->bbJumpKind == BBJ_SWITCH);
712             noway_assert(last->gtStmtExpr->gtOper == GT_SWITCH);
713         }
714 #endif // DEBUG
715
716         /* Append 'stmt' before 'last' */
717
718         stmt->gtNext = last;
719         last->gtPrev = stmt;
720
721         if (first == last)
722         {
723             /* There is only one stmt in the block */
724
725             block->bbTreeList = stmt;
726             stmt->gtPrev      = last;
727         }
728         else
729         {
730             noway_assert(after && (after->gtNext == last));
731
732             /* Append 'stmt' after 'after' */
733
734             after->gtNext = stmt;
735             stmt->gtPrev  = after;
736         }
737
738         return stmt;
739     }
740     else
741     {
742         return fgInsertStmtAtEnd(block, node);
743     }
744 }
745
746 /*****************************************************************************
747  *
748  *  Insert the given statement "stmt" after GT_STMT node "insertionPoint".
749  *  Returns the newly inserted GT_STMT node.
750  *  Note that the gtPrev list of statement nodes is circular, but the gtNext list is not.
751  */
752
753 GenTree* Compiler::fgInsertStmtAfter(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt)
754 {
755     assert(block->bbTreeList != nullptr);
756     noway_assert(insertionPoint->gtOper == GT_STMT);
757     noway_assert(stmt->gtOper == GT_STMT);
758     assert(fgBlockContainsStatementBounded(block, insertionPoint));
759     assert(!fgBlockContainsStatementBounded(block, stmt, false));
760
761     if (insertionPoint->gtNext == nullptr)
762     {
763         // Ok, we want to insert after the last statement of the block.
764         stmt->gtNext = nullptr;
765         stmt->gtPrev = insertionPoint;
766
767         insertionPoint->gtNext = stmt;
768
769         // Update the backward link of the first statement of the block
770         // to point to the new last statement.
771         assert(block->bbTreeList->gtPrev == insertionPoint);
772         block->bbTreeList->gtPrev = stmt;
773     }
774     else
775     {
776         stmt->gtNext = insertionPoint->gtNext;
777         stmt->gtPrev = insertionPoint;
778
779         insertionPoint->gtNext->gtPrev = stmt;
780         insertionPoint->gtNext         = stmt;
781     }
782
783     return stmt;
784 }
785
786 //  Insert the given tree or statement before GT_STMT node "insertionPoint".
787 //  Returns the newly inserted GT_STMT node.
788
789 GenTree* Compiler::fgInsertStmtBefore(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt)
790 {
791     assert(block->bbTreeList != nullptr);
792     noway_assert(insertionPoint->gtOper == GT_STMT);
793     noway_assert(stmt->gtOper == GT_STMT);
794     assert(fgBlockContainsStatementBounded(block, insertionPoint));
795     assert(!fgBlockContainsStatementBounded(block, stmt, false));
796
797     if (insertionPoint == block->bbTreeList)
798     {
799         // We're inserting before the first statement in the block.
800         GenTree* list = block->bbTreeList;
801         GenTree* last = list->gtPrev;
802
803         stmt->gtNext = list;
804         stmt->gtPrev = last;
805
806         block->bbTreeList = stmt;
807         list->gtPrev      = stmt;
808     }
809     else
810     {
811         stmt->gtNext = insertionPoint;
812         stmt->gtPrev = insertionPoint->gtPrev;
813
814         insertionPoint->gtPrev->gtNext = stmt;
815         insertionPoint->gtPrev         = stmt;
816     }
817
818     return stmt;
819 }
820
821 /*****************************************************************************
822  *
823  *  Insert the list of statements stmtList after the stmtAfter in block.
824  *  Return the last statement stmtList.
825  */
826
827 GenTree* Compiler::fgInsertStmtListAfter(BasicBlock* block,     // the block where stmtAfter is in.
828                                          GenTree*    stmtAfter, // the statement where stmtList should be inserted
829                                                                 // after.
830                                          GenTree* stmtList)
831 {
832     // Currently we can handle when stmtAfter and stmtList are non-NULL. This makes everything easy.
833     noway_assert(stmtAfter && stmtAfter->gtOper == GT_STMT);
834     noway_assert(stmtList && stmtList->gtOper == GT_STMT);
835
836     GenTree* stmtLast = stmtList->gtPrev; // Last statement in a non-empty list, circular in the gtPrev list.
837     noway_assert(stmtLast);
838     noway_assert(stmtLast->gtNext == nullptr);
839
840     GenTree* stmtNext = stmtAfter->gtNext;
841
842     if (!stmtNext)
843     {
844         stmtAfter->gtNext         = stmtList;
845         stmtList->gtPrev          = stmtAfter;
846         block->bbTreeList->gtPrev = stmtLast;
847         goto _Done;
848     }
849
850     stmtAfter->gtNext = stmtList;
851     stmtList->gtPrev  = stmtAfter;
852
853     stmtLast->gtNext = stmtNext;
854     stmtNext->gtPrev = stmtLast;
855
856 _Done:
857
858     noway_assert(block->bbTreeList == nullptr || block->bbTreeList->gtPrev->gtNext == nullptr);
859
860     return stmtLast;
861 }
862
863 /*
864     Removes a block from the return block list
865 */
866 void Compiler::fgRemoveReturnBlock(BasicBlock* block)
867 {
868     if (fgReturnBlocks == nullptr)
869     {
870         return;
871     }
872
873     if (fgReturnBlocks->block == block)
874     {
875         // It's the 1st entry, assign new head of list.
876         fgReturnBlocks = fgReturnBlocks->next;
877         return;
878     }
879
880     for (BasicBlockList* retBlocks = fgReturnBlocks; retBlocks->next != nullptr; retBlocks = retBlocks->next)
881     {
882         if (retBlocks->next->block == block)
883         {
884             // Found it; splice it out.
885             retBlocks->next = retBlocks->next->next;
886             return;
887         }
888     }
889 }
890
891 //------------------------------------------------------------------------
892 // fgGetPredForBlock: Find and return the predecessor edge corresponding to a given predecessor block.
893 //
894 // Arguments:
895 //    block -- The block with the predecessor list to operate on.
896 //    blockPred -- The predecessor block to find in the predecessor list.
897 //
898 // Return Value:
899 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
900 //    then returns nullptr.
901 //
902 // Assumptions:
903 //    -- This only works on the full predecessor lists, not the cheap preds lists.
904
905 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred)
906 {
907     assert(block);
908     assert(blockPred);
909     assert(!fgCheapPredsValid);
910
911     flowList* pred;
912
913     for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
914     {
915         if (blockPred == pred->flBlock)
916         {
917             return pred;
918         }
919     }
920
921     return nullptr;
922 }
923
924 //------------------------------------------------------------------------
925 // fgGetPredForBlock: Find and return the predecessor edge corresponding to a given predecessor block.
926 // Also returns the address of the pointer that points to this edge, to make it possible to remove this edge from the
927 // predecessor list without doing another linear search over the edge list.
928 //
929 // Arguments:
930 //    block -- The block with the predecessor list to operate on.
931 //    blockPred -- The predecessor block to find in the predecessor list.
932 //    ptrToPred -- Out parameter: set to the address of the pointer that points to the returned predecessor edge.
933 //
934 // Return Value:
935 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
936 //    then returns nullptr.
937 //
938 // Assumptions:
939 //    -- This only works on the full predecessor lists, not the cheap preds lists.
940
941 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, flowList*** ptrToPred)
942 {
943     assert(block);
944     assert(blockPred);
945     assert(ptrToPred);
946     assert(!fgCheapPredsValid);
947
948     flowList** predPrevAddr;
949     flowList*  pred;
950
951     for (predPrevAddr = &block->bbPreds, pred = *predPrevAddr; pred != nullptr;
952          predPrevAddr = &pred->flNext, pred = *predPrevAddr)
953     {
954         if (blockPred == pred->flBlock)
955         {
956             *ptrToPred = predPrevAddr;
957             return pred;
958         }
959     }
960
961     *ptrToPred = nullptr;
962     return nullptr;
963 }
964
965 //------------------------------------------------------------------------
966 // fgSpliceOutPred: Removes a predecessor edge for a block from the predecessor list.
967 //
968 // Arguments:
969 //    block -- The block with the predecessor list to operate on.
970 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
971 //
972 // Return Value:
973 //    The flowList edge that was removed.
974 //
975 // Assumptions:
976 //    -- "blockPred" must be a predecessor block of "block".
977 //    -- This simply splices out the flowList object. It doesn't update block ref counts, handle duplicate counts, etc.
978 //       For that, use fgRemoveRefPred() or fgRemoveAllRefPred().
979 //    -- This only works on the full predecessor lists, not the cheap preds lists.
980 //
981 // Notes:
982 //    -- This must walk the predecessor list to find the block in question. If the predecessor edge
983 //       is found using fgGetPredForBlock(), consider using the version that hands back the predecessor pointer
984 //       address instead, to avoid this search.
985 //    -- Marks fgModified = true, since the flow graph has changed.
986
987 flowList* Compiler::fgSpliceOutPred(BasicBlock* block, BasicBlock* blockPred)
988 {
989     assert(!fgCheapPredsValid);
990     noway_assert(block->bbPreds);
991
992     flowList* oldEdge = nullptr;
993
994     // Is this the first block in the pred list?
995     if (blockPred == block->bbPreds->flBlock)
996     {
997         oldEdge        = block->bbPreds;
998         block->bbPreds = block->bbPreds->flNext;
999     }
1000     else
1001     {
1002         flowList* pred;
1003         for (pred = block->bbPreds; (pred->flNext != nullptr) && (blockPred != pred->flNext->flBlock);
1004              pred = pred->flNext)
1005         {
1006             // empty
1007         }
1008         oldEdge = pred->flNext;
1009         if (oldEdge == nullptr)
1010         {
1011             noway_assert(!"Should always find the blockPred");
1012         }
1013         pred->flNext = pred->flNext->flNext;
1014     }
1015
1016     // Any changes to the flow graph invalidate the dominator sets.
1017     fgModified = true;
1018
1019     return oldEdge;
1020 }
1021
1022 //------------------------------------------------------------------------
1023 // fgAddRefPred: Increment block->bbRefs by one and add "blockPred" to the predecessor list of "block".
1024 //
1025 // Arguments:
1026 //    block -- A block to operate on.
1027 //    blockPred -- The predecessor block to add to the predecessor list.
1028 //    oldEdge -- Optional (default: nullptr). If non-nullptr, and a new edge is created (and the dup count
1029 //               of an existing edge is not just incremented), the edge weights are copied from this edge.
1030 //    initializingPreds -- Optional (default: false). Only set to "true" when the initial preds computation is
1031 //    happening.
1032 //
1033 // Return Value:
1034 //    The flow edge representing the predecessor.
1035 //
1036 // Assumptions:
1037 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1038 //
1039 // Notes:
1040 //    -- block->bbRefs is incremented by one to account for the reduction in incoming edges.
1041 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
1042 //       the preds themselves aren't touched.
1043 //    -- fgModified is set if a new flow edge is created (but not if an existing flow edge dup count is incremented),
1044 //       indicating that the flow graph shape has changed.
1045
1046 flowList* Compiler::fgAddRefPred(BasicBlock* block,
1047                                  BasicBlock* blockPred,
1048                                  flowList*   oldEdge /* = nullptr */,
1049                                  bool        initializingPreds /* = false */)
1050 {
1051     assert(block != nullptr);
1052     assert(blockPred != nullptr);
1053
1054     block->bbRefs++;
1055
1056     if (!fgComputePredsDone && !initializingPreds)
1057     {
1058         // Why is someone trying to update the preds list when the preds haven't been created?
1059         // Ignore them! This can happen when fgMorph is called before the preds list is created.
1060         return nullptr;
1061     }
1062
1063     assert(!fgCheapPredsValid);
1064
1065     flowList* flow;
1066
1067     // Keep the predecessor list in lowest to highest bbNum order. This allows us to discover the loops in
1068     // optFindNaturalLoops from innermost to outermost.
1069     //
1070     // TODO-Throughput: Inserting an edge for a block in sorted order requires searching every existing edge.
1071     // Thus, inserting all the edges for a block is quadratic in the number of edges. We need to either
1072     // not bother sorting for debuggable code, or sort in optFindNaturalLoops, or better, make the code in
1073     // optFindNaturalLoops not depend on order. This also requires ensuring that nobody else has taken a
1074     // dependency on this order. Note also that we don't allow duplicates in the list; we maintain a flDupCount
1075     // count of duplication. This also necessitates walking the flow list for every edge we add.
1076
1077     flowList** listp = &block->bbPreds;
1078     while ((*listp != nullptr) && ((*listp)->flBlock->bbNum < blockPred->bbNum))
1079     {
1080         listp = &(*listp)->flNext;
1081     }
1082
1083     if ((*listp != nullptr) && ((*listp)->flBlock == blockPred))
1084     {
1085         // The predecessor block already exists in the flow list; simply add to its duplicate count.
1086         flow = *listp;
1087         noway_assert(flow->flDupCount > 0);
1088         flow->flDupCount++;
1089     }
1090     else
1091     {
1092         flow = new (this, CMK_FlowList) flowList();
1093
1094 #if MEASURE_BLOCK_SIZE
1095         genFlowNodeCnt += 1;
1096         genFlowNodeSize += sizeof(flowList);
1097 #endif // MEASURE_BLOCK_SIZE
1098
1099         // Any changes to the flow graph invalidate the dominator sets.
1100         fgModified = true;
1101
1102         // Insert the new edge in the list in the correct ordered location.
1103         flow->flNext = *listp;
1104         *listp       = flow;
1105
1106         flow->flBlock    = blockPred;
1107         flow->flDupCount = 1;
1108
1109         if (fgHaveValidEdgeWeights)
1110         {
1111             // We are creating an edge from blockPred to block
1112             // and we have already computed the edge weights, so
1113             // we will try to setup this new edge with valid edge weights.
1114             //
1115             if (oldEdge != nullptr)
1116             {
1117                 // If our caller has given us the old edge weights
1118                 // then we will use them.
1119                 //
1120                 flow->flEdgeWeightMin = oldEdge->flEdgeWeightMin;
1121                 flow->flEdgeWeightMax = oldEdge->flEdgeWeightMax;
1122             }
1123             else
1124             {
1125                 // Set the max edge weight to be the minimum of block's or blockPred's weight
1126                 //
1127                 flow->flEdgeWeightMax = min(block->bbWeight, blockPred->bbWeight);
1128
1129                 // If we are inserting a conditional block the minimum weight is zero,
1130                 // otherwise it is the same as the edge's max weight.
1131                 if (blockPred->NumSucc() > 1)
1132                 {
1133                     flow->flEdgeWeightMin = BB_ZERO_WEIGHT;
1134                 }
1135                 else
1136                 {
1137                     flow->flEdgeWeightMin = flow->flEdgeWeightMax;
1138                 }
1139             }
1140         }
1141         else
1142         {
1143             flow->flEdgeWeightMin = BB_ZERO_WEIGHT;
1144             flow->flEdgeWeightMax = BB_MAX_WEIGHT;
1145         }
1146     }
1147     return flow;
1148 }
1149
1150 //------------------------------------------------------------------------
1151 // fgRemoveRefPred: Decrements the reference count of a predecessor edge from "blockPred" to "block",
1152 // removing the edge if it is no longer necessary.
1153 //
1154 // Arguments:
1155 //    block -- A block to operate on.
1156 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
1157 //
1158 // Return Value:
1159 //    If the flow edge was removed (the predecessor has a "dup count" of 1),
1160 //        returns the flow graph edge that was removed. This means "blockPred" is no longer a predecessor of "block".
1161 //    Otherwise, returns nullptr. This means that "blockPred" is still a predecessor of "block" (because "blockPred"
1162 //        is a switch with multiple cases jumping to "block", or a BBJ_COND with both conditional and fall-through
1163 //        paths leading to "block").
1164 //
1165 // Assumptions:
1166 //    -- "blockPred" must be a predecessor block of "block".
1167 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1168 //
1169 // Notes:
1170 //    -- block->bbRefs is decremented by one to account for the reduction in incoming edges.
1171 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
1172 //       the preds themselves aren't touched.
1173 //    -- fgModified is set if a flow edge is removed (but not if an existing flow edge dup count is decremented),
1174 //       indicating that the flow graph shape has changed.
1175
1176 flowList* Compiler::fgRemoveRefPred(BasicBlock* block, BasicBlock* blockPred)
1177 {
1178     noway_assert(block != nullptr);
1179     noway_assert(blockPred != nullptr);
1180
1181     noway_assert(block->countOfInEdges() > 0);
1182     block->bbRefs--;
1183
1184     // Do nothing if we haven't calculated the predecessor list yet.
1185     // Yes, this does happen.
1186     // For example the predecessor lists haven't been created yet when we do fgMorph.
1187     // But fgMorph calls fgFoldConditional, which in turn calls fgRemoveRefPred.
1188     if (!fgComputePredsDone)
1189     {
1190         return nullptr;
1191     }
1192
1193     assert(!fgCheapPredsValid);
1194
1195     flowList** ptrToPred;
1196     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
1197     noway_assert(pred);
1198     noway_assert(pred->flDupCount > 0);
1199
1200     pred->flDupCount--;
1201
1202     if (pred->flDupCount == 0)
1203     {
1204         // Splice out the predecessor edge since it's no longer necessary.
1205         *ptrToPred = pred->flNext;
1206
1207         // Any changes to the flow graph invalidate the dominator sets.
1208         fgModified = true;
1209
1210         return pred;
1211     }
1212     else
1213     {
1214         return nullptr;
1215     }
1216 }
1217
1218 //------------------------------------------------------------------------
1219 // fgRemoveAllRefPreds: Removes a predecessor edge from one block to another, no matter what the "dup count" is.
1220 //
1221 // Arguments:
1222 //    block -- A block to operate on.
1223 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
1224 //
1225 // Return Value:
1226 //    Returns the flow graph edge that was removed. The dup count on the edge is no longer valid.
1227 //
1228 // Assumptions:
1229 //    -- "blockPred" must be a predecessor block of "block".
1230 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1231 //
1232 // Notes:
1233 //    block->bbRefs is decremented to account for the reduction in incoming edges.
1234
1235 flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, BasicBlock* blockPred)
1236 {
1237     assert(block != nullptr);
1238     assert(blockPred != nullptr);
1239     assert(fgComputePredsDone);
1240     assert(!fgCheapPredsValid);
1241     assert(block->countOfInEdges() > 0);
1242
1243     flowList** ptrToPred;
1244     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
1245     assert(pred != nullptr);
1246     assert(pred->flDupCount > 0);
1247
1248     assert(block->bbRefs >= pred->flDupCount);
1249     block->bbRefs -= pred->flDupCount;
1250
1251     // Now splice out the predecessor edge.
1252     *ptrToPred = pred->flNext;
1253
1254     // Any changes to the flow graph invalidate the dominator sets.
1255     fgModified = true;
1256
1257     return pred;
1258 }
1259
1260 //------------------------------------------------------------------------
1261 // fgRemoveAllRefPreds: Remove a predecessor edge, given the address of a pointer to it in the
1262 // predecessor list, no matter what the "dup count" is.
1263 //
1264 // Arguments:
1265 //    block -- A block with the predecessor list to operate on.
1266 //    ptrToPred -- The address of a pointer to the predecessor to remove.
1267 //
1268 // Return Value:
1269 //    The removed predecessor edge. The dup count on the edge is no longer valid.
1270 //
1271 // Assumptions:
1272 //    -- The predecessor edge must be in the predecessor list for "block".
1273 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1274 //
1275 // Notes:
1276 //    block->bbRefs is decremented by the dup count of the predecessor edge, to account for the reduction in incoming
1277 //    edges.
1278
1279 flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, flowList** ptrToPred)
1280 {
1281     assert(block != nullptr);
1282     assert(ptrToPred != nullptr);
1283     assert(fgComputePredsDone);
1284     assert(!fgCheapPredsValid);
1285     assert(block->countOfInEdges() > 0);
1286
1287     flowList* pred = *ptrToPred;
1288     assert(pred != nullptr);
1289     assert(pred->flDupCount > 0);
1290
1291     assert(block->bbRefs >= pred->flDupCount);
1292     block->bbRefs -= pred->flDupCount;
1293
1294     // Now splice out the predecessor edge.
1295     *ptrToPred = pred->flNext;
1296
1297     // Any changes to the flow graph invalidate the dominator sets.
1298     fgModified = true;
1299
1300     return pred;
1301 }
1302
1303 /*
1304     Removes all the appearances of block as predecessor of others
1305 */
1306
1307 void Compiler::fgRemoveBlockAsPred(BasicBlock* block)
1308 {
1309     assert(!fgCheapPredsValid);
1310
1311     PREFIX_ASSUME(block != nullptr);
1312
1313     BasicBlock* bNext;
1314
1315     switch (block->bbJumpKind)
1316     {
1317         case BBJ_CALLFINALLY:
1318             if (!(block->bbFlags & BBF_RETLESS_CALL))
1319             {
1320                 assert(block->isBBCallAlwaysPair());
1321
1322                 /* The block after the BBJ_CALLFINALLY block is not reachable */
1323                 bNext = block->bbNext;
1324
1325                 /* bNext is an unreachable BBJ_ALWAYS block */
1326                 noway_assert(bNext->bbJumpKind == BBJ_ALWAYS);
1327
1328                 while (bNext->countOfInEdges() > 0)
1329                 {
1330                     fgRemoveRefPred(bNext, bNext->bbPreds->flBlock);
1331                 }
1332             }
1333
1334             __fallthrough;
1335
1336         case BBJ_COND:
1337         case BBJ_ALWAYS:
1338         case BBJ_EHCATCHRET:
1339
1340             /* Update the predecessor list for 'block->bbJumpDest' and 'block->bbNext' */
1341             fgRemoveRefPred(block->bbJumpDest, block);
1342
1343             if (block->bbJumpKind != BBJ_COND)
1344             {
1345                 break;
1346             }
1347
1348             /* If BBJ_COND fall through */
1349             __fallthrough;
1350
1351         case BBJ_NONE:
1352
1353             /* Update the predecessor list for 'block->bbNext' */
1354             fgRemoveRefPred(block->bbNext, block);
1355             break;
1356
1357         case BBJ_EHFILTERRET:
1358
1359             block->bbJumpDest->bbRefs++; // To compensate the bbRefs-- inside fgRemoveRefPred
1360             fgRemoveRefPred(block->bbJumpDest, block);
1361             break;
1362
1363         case BBJ_EHFINALLYRET:
1364         {
1365             /* Remove block as the predecessor of the bbNext of all
1366                BBJ_CALLFINALLY blocks calling this finally. No need
1367                to look for BBJ_CALLFINALLY for fault handlers. */
1368
1369             unsigned  hndIndex = block->getHndIndex();
1370             EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
1371
1372             if (ehDsc->HasFinallyHandler())
1373             {
1374                 BasicBlock* begBlk;
1375                 BasicBlock* endBlk;
1376                 ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
1377
1378                 BasicBlock* finBeg = ehDsc->ebdHndBeg;
1379
1380                 for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
1381                 {
1382                     if ((bcall->bbFlags & BBF_REMOVED) || bcall->bbJumpKind != BBJ_CALLFINALLY ||
1383                         bcall->bbJumpDest != finBeg)
1384                     {
1385                         continue;
1386                     }
1387
1388                     assert(bcall->isBBCallAlwaysPair());
1389                     fgRemoveRefPred(bcall->bbNext, block);
1390                 }
1391             }
1392         }
1393         break;
1394
1395         case BBJ_THROW:
1396         case BBJ_RETURN:
1397             break;
1398
1399         case BBJ_SWITCH:
1400         {
1401             unsigned     jumpCnt = block->bbJumpSwt->bbsCount;
1402             BasicBlock** jumpTab = block->bbJumpSwt->bbsDstTab;
1403
1404             do
1405             {
1406                 fgRemoveRefPred(*jumpTab, block);
1407             } while (++jumpTab, --jumpCnt);
1408
1409             break;
1410         }
1411
1412         default:
1413             noway_assert(!"Block doesn't have a valid bbJumpKind!!!!");
1414             break;
1415     }
1416 }
1417
1418 /*****************************************************************************
1419  * fgChangeSwitchBlock:
1420  *
1421  * We have a BBJ_SWITCH jump at 'oldSwitchBlock' and we want to move this
1422  * switch jump over to 'newSwitchBlock'.  All of the blocks that are jumped
1423  * to from jumpTab[] need to have their predecessor lists updated by removing
1424  * the 'oldSwitchBlock' and adding 'newSwitchBlock'.
1425  */
1426
1427 void Compiler::fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSwitchBlock)
1428 {
1429     noway_assert(oldSwitchBlock != nullptr);
1430     noway_assert(newSwitchBlock != nullptr);
1431     noway_assert(oldSwitchBlock->bbJumpKind == BBJ_SWITCH);
1432
1433     unsigned     jumpCnt = oldSwitchBlock->bbJumpSwt->bbsCount;
1434     BasicBlock** jumpTab = oldSwitchBlock->bbJumpSwt->bbsDstTab;
1435
1436     unsigned i;
1437
1438     // Walk the switch's jump table, updating the predecessor for each branch.
1439     for (i = 0; i < jumpCnt; i++)
1440     {
1441         BasicBlock* bJump = jumpTab[i];
1442         noway_assert(bJump != nullptr);
1443
1444         // Note that if there are duplicate branch targets in the switch jump table,
1445         // fgRemoveRefPred()/fgAddRefPred() will do the right thing: the second and
1446         // subsequent duplicates will simply subtract from and add to the duplicate
1447         // count (respectively).
1448
1449         //
1450         // Remove the old edge [oldSwitchBlock => bJump]
1451         //
1452         fgRemoveRefPred(bJump, oldSwitchBlock);
1453
1454         //
1455         // Create the new edge [newSwitchBlock => bJump]
1456         //
1457         fgAddRefPred(bJump, newSwitchBlock);
1458     }
1459
1460     if (m_switchDescMap != nullptr)
1461     {
1462         SwitchUniqueSuccSet uniqueSuccSet;
1463
1464         // If already computed and cached the unique descriptors for the old block, let's
1465         // update those for the new block.
1466         if (m_switchDescMap->Lookup(oldSwitchBlock, &uniqueSuccSet))
1467         {
1468             m_switchDescMap->Set(newSwitchBlock, uniqueSuccSet);
1469         }
1470         else
1471         {
1472             fgInvalidateSwitchDescMapEntry(newSwitchBlock);
1473         }
1474         fgInvalidateSwitchDescMapEntry(oldSwitchBlock);
1475     }
1476 }
1477
1478 /*****************************************************************************
1479  * fgReplaceSwitchJumpTarget:
1480  *
1481  * We have a BBJ_SWITCH at 'blockSwitch' and we want to replace all entries
1482  * in the jumpTab[] such that so that jumps that previously went to
1483  * 'oldTarget' now go to 'newTarget'.
1484  * We also must update the predecessor lists for 'oldTarget' and 'newPred'.
1485  */
1486
1487 void Compiler::fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* newTarget, BasicBlock* oldTarget)
1488 {
1489     noway_assert(blockSwitch != nullptr);
1490     noway_assert(newTarget != nullptr);
1491     noway_assert(oldTarget != nullptr);
1492     noway_assert(blockSwitch->bbJumpKind == BBJ_SWITCH);
1493
1494     // For the jump targets values that match oldTarget of our BBJ_SWITCH
1495     // replace predecessor 'blockSwitch' with 'newTarget'
1496     //
1497
1498     unsigned     jumpCnt = blockSwitch->bbJumpSwt->bbsCount;
1499     BasicBlock** jumpTab = blockSwitch->bbJumpSwt->bbsDstTab;
1500
1501     unsigned i = 0;
1502
1503     // Walk the switch's jump table looking for blocks to update the preds for
1504     while (i < jumpCnt)
1505     {
1506         if (jumpTab[i] == oldTarget) // We will update when jumpTab[i] matches
1507         {
1508             // Remove the old edge [oldTarget from blockSwitch]
1509             //
1510             fgRemoveAllRefPreds(oldTarget, blockSwitch);
1511
1512             //
1513             // Change the jumpTab entry to branch to the new location
1514             //
1515             jumpTab[i] = newTarget;
1516
1517             //
1518             // Create the new edge [newTarget from blockSwitch]
1519             //
1520             flowList* newEdge = fgAddRefPred(newTarget, blockSwitch);
1521
1522             // Now set the correct value of newEdge->flDupCount
1523             // and replace any other jumps in jumpTab[] that go to oldTarget.
1524             //
1525             i++;
1526             while (i < jumpCnt)
1527             {
1528                 if (jumpTab[i] == oldTarget)
1529                 {
1530                     //
1531                     // We also must update this entry in the jumpTab
1532                     //
1533                     jumpTab[i] = newTarget;
1534                     newTarget->bbRefs++;
1535
1536                     //
1537                     // Increment the flDupCount
1538                     //
1539                     newEdge->flDupCount++;
1540                 }
1541                 i++; // Check the next entry in jumpTab[]
1542             }
1543
1544             // Maintain, if necessary, the set of unique targets of "block."
1545             UpdateSwitchTableTarget(blockSwitch, oldTarget, newTarget);
1546
1547             // Make sure the new target has the proper bits set for being a branch target.
1548             newTarget->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
1549
1550             return; // We have replaced the jumps to oldTarget with newTarget
1551         }
1552         i++; // Check the next entry in jumpTab[] for a match
1553     }
1554     noway_assert(!"Did not find oldTarget in jumpTab[]");
1555 }
1556
1557 //------------------------------------------------------------------------
1558 // Compiler::fgReplaceJumpTarget: For a given block, replace the target 'oldTarget' with 'newTarget'.
1559 //
1560 // Arguments:
1561 //    block     - the block in which a jump target will be replaced.
1562 //    newTarget - the new branch target of the block.
1563 //    oldTarget - the old branch target of the block.
1564 //
1565 // Notes:
1566 // 1. Only branches are changed: BBJ_ALWAYS, the non-fallthrough path of BBJ_COND, BBJ_SWITCH, etc.
1567 //    We ignore other block types.
1568 // 2. Only the first target found is updated. If there are multiple ways for a block
1569 //    to reach 'oldTarget' (e.g., multiple arms of a switch), only the first one found is changed.
1570 // 3. The predecessor lists are not changed.
1571 // 4. The switch table "unique successor" cache is invalidated.
1572 //
1573 // This function is most useful early, before the full predecessor lists have been computed.
1574 //
1575 void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget)
1576 {
1577     assert(block != nullptr);
1578
1579     switch (block->bbJumpKind)
1580     {
1581         case BBJ_CALLFINALLY:
1582         case BBJ_COND:
1583         case BBJ_ALWAYS:
1584         case BBJ_EHCATCHRET:
1585         case BBJ_EHFILTERRET:
1586         case BBJ_LEAVE: // This function will be called before import, so we still have BBJ_LEAVE
1587
1588             if (block->bbJumpDest == oldTarget)
1589             {
1590                 block->bbJumpDest = newTarget;
1591             }
1592             break;
1593
1594         case BBJ_NONE:
1595         case BBJ_EHFINALLYRET:
1596         case BBJ_THROW:
1597         case BBJ_RETURN:
1598             break;
1599
1600         case BBJ_SWITCH:
1601             unsigned jumpCnt;
1602             jumpCnt = block->bbJumpSwt->bbsCount;
1603             BasicBlock** jumpTab;
1604             jumpTab = block->bbJumpSwt->bbsDstTab;
1605
1606             for (unsigned i = 0; i < jumpCnt; i++)
1607             {
1608                 if (jumpTab[i] == oldTarget)
1609                 {
1610                     jumpTab[i] = newTarget;
1611                     break;
1612                 }
1613             }
1614             break;
1615
1616         default:
1617             assert(!"Block doesn't have a valid bbJumpKind!!!!");
1618             unreached();
1619             break;
1620     }
1621 }
1622
1623 /*****************************************************************************
1624  * Updates the predecessor list for 'block' by replacing 'oldPred' with 'newPred'.
1625  * Note that a block can only appear once in the preds list (for normal preds, not
1626  * cheap preds): if a predecessor has multiple ways to get to this block, then
1627  * flDupCount will be >1, but the block will still appear exactly once. Thus, this
1628  * function assumes that all branches from the predecessor (practically, that all
1629  * switch cases that target this block) are changed to branch from the new predecessor,
1630  * with the same dup count.
1631  *
1632  * Note that the block bbRefs is not changed, since 'block' has the same number of
1633  * references as before, just from a different predecessor block.
1634  */
1635
1636 void Compiler::fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* newPred)
1637 {
1638     noway_assert(block != nullptr);
1639     noway_assert(oldPred != nullptr);
1640     noway_assert(newPred != nullptr);
1641     assert(!fgCheapPredsValid);
1642
1643     flowList* pred;
1644
1645     for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
1646     {
1647         if (oldPred == pred->flBlock)
1648         {
1649             pred->flBlock = newPred;
1650             break;
1651         }
1652     }
1653 }
1654
1655 /*****************************************************************************
1656  *
1657  *  Returns true if block b1 dominates block b2.
1658  */
1659
1660 bool Compiler::fgDominate(BasicBlock* b1, BasicBlock* b2)
1661 {
1662     noway_assert(fgDomsComputed);
1663     assert(!fgCheapPredsValid);
1664
1665     //
1666     // If the fgModified flag is false then we made some modifications to
1667     // the flow graph, like adding a new block or changing a conditional branch
1668     // into an unconditional branch.
1669     //
1670     // We can continue to use the dominator and reachable information to
1671     // unmark loops as long as we haven't renumbered the blocks or we aren't
1672     // asking for information about a new block
1673     //
1674
1675     if (b2->bbNum > fgDomBBcount)
1676     {
1677         if (b1 == b2)
1678         {
1679             return true;
1680         }
1681
1682         for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext)
1683         {
1684             if (!fgDominate(b1, pred->flBlock))
1685             {
1686                 return false;
1687             }
1688         }
1689
1690         return b2->bbPreds != nullptr;
1691     }
1692
1693     if (b1->bbNum > fgDomBBcount)
1694     {
1695         // if b1 is a loop preheader and Succ is its only successor, then all predecessors of
1696         // Succ either are b1 itself or are dominated by Succ. Under these conditions, b1
1697         // dominates b2 if and only if Succ dominates b2 (or if b2 == b1, but we already tested
1698         // for this case)
1699         if (b1->bbFlags & BBF_LOOP_PREHEADER)
1700         {
1701             noway_assert(b1->bbFlags & BBF_INTERNAL);
1702             noway_assert(b1->bbJumpKind == BBJ_NONE);
1703             return fgDominate(b1->bbNext, b2);
1704         }
1705
1706         // unknown dominators; err on the safe side and return false
1707         return false;
1708     }
1709
1710     /* Check if b1 dominates b2 */
1711     unsigned numA = b1->bbNum;
1712     noway_assert(numA <= fgDomBBcount);
1713     unsigned numB = b2->bbNum;
1714     noway_assert(numB <= fgDomBBcount);
1715
1716     // 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)
1717     // in the dominator tree. Turns out that can be translated as:
1718     //
1719     //   A dom B <-> preorder(A) <= preorder(B) && postorder(A) >= postorder(B)
1720     //
1721     // where the equality holds when you ask if A dominates itself.
1722     bool treeDom =
1723         fgDomTreePreOrder[numA] <= fgDomTreePreOrder[numB] && fgDomTreePostOrder[numA] >= fgDomTreePostOrder[numB];
1724
1725     return treeDom;
1726 }
1727
1728 /*****************************************************************************
1729  *
1730  *  Returns true if block b1 can reach block b2.
1731  */
1732
1733 bool Compiler::fgReachable(BasicBlock* b1, BasicBlock* b2)
1734 {
1735     noway_assert(fgDomsComputed);
1736     assert(!fgCheapPredsValid);
1737
1738     //
1739     // If the fgModified flag is false then we made some modifications to
1740     // the flow graph, like adding a new block or changing a conditional branch
1741     // into an unconditional branch.
1742     //
1743     // We can continue to use the dominator and reachable information to
1744     // unmark loops as long as we haven't renumbered the blocks or we aren't
1745     // asking for information about a new block
1746     //
1747
1748     if (b2->bbNum > fgDomBBcount)
1749     {
1750         if (b1 == b2)
1751         {
1752             return true;
1753         }
1754
1755         for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext)
1756         {
1757             if (fgReachable(b1, pred->flBlock))
1758             {
1759                 return true;
1760             }
1761         }
1762
1763         return false;
1764     }
1765
1766     if (b1->bbNum > fgDomBBcount)
1767     {
1768         noway_assert(b1->bbJumpKind == BBJ_NONE || b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND);
1769
1770         if (b1->bbFallsThrough() && fgReachable(b1->bbNext, b2))
1771         {
1772             return true;
1773         }
1774
1775         if (b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND)
1776         {
1777             return fgReachable(b1->bbJumpDest, b2);
1778         }
1779
1780         return false;
1781     }
1782
1783     /* Check if b1 can reach b2 */
1784     assert(fgReachabilitySetsValid);
1785     assert(BasicBlockBitSetTraits::GetSize(this) == fgDomBBcount + 1);
1786     return BlockSetOps::IsMember(this, b2->bbReach, b1->bbNum);
1787 }
1788
1789 /*****************************************************************************
1790  *  Update changed flow graph information.
1791  *
1792  *  If the flow graph has changed, we need to recompute various information if we want to use
1793  *  it again.
1794  */
1795
1796 void Compiler::fgUpdateChangedFlowGraph()
1797 {
1798     // We need to clear this so we don't hit an assert calling fgRenumberBlocks().
1799     fgDomsComputed = false;
1800
1801     JITDUMP("\nRenumbering the basic blocks for fgUpdateChangeFlowGraph\n");
1802     fgRenumberBlocks();
1803
1804     fgComputePreds();
1805     fgComputeEnterBlocksSet();
1806     fgComputeReachabilitySets();
1807     fgComputeDoms();
1808 }
1809
1810 /*****************************************************************************
1811  *  Compute the bbReach sets.
1812  *
1813  *  This can be called to recompute the bbReach sets after the flow graph changes, such as when the
1814  *  number of BasicBlocks change (and thus, the BlockSet epoch changes).
1815  *
1816  *  Finally, this also sets the BBF_GC_SAFE_POINT flag on blocks.
1817  *
1818  *  Assumes the predecessor lists are correct.
1819  *
1820  *  TODO-Throughput: This algorithm consumes O(n^2) because we're using dense bitsets to
1821  *  represent reachability. While this yields O(1) time queries, it bloats the memory usage
1822  *  for large code.  We can do better if we try to approach reachability by
1823  *  computing the strongly connected components of the flow graph.  That way we only need
1824  *  linear memory to label every block with its SCC.
1825  */
1826
1827 void Compiler::fgComputeReachabilitySets()
1828 {
1829     assert(fgComputePredsDone);
1830     assert(!fgCheapPredsValid);
1831
1832 #ifdef DEBUG
1833     fgReachabilitySetsValid = false;
1834 #endif // DEBUG
1835
1836     BasicBlock* block;
1837
1838     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1839     {
1840         // Initialize the per-block bbReach sets. It creates a new empty set,
1841         // because the block epoch could change since the previous initialization
1842         // and the old set could have wrong size.
1843         block->bbReach = BlockSetOps::MakeEmpty(this);
1844
1845         /* Mark block as reaching itself */
1846         BlockSetOps::AddElemD(this, block->bbReach, block->bbNum);
1847     }
1848
1849     /* Find the reachable blocks */
1850     // Also, set BBF_GC_SAFE_POINT.
1851
1852     bool     change;
1853     BlockSet newReach(BlockSetOps::MakeEmpty(this));
1854     do
1855     {
1856         change = false;
1857
1858         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1859         {
1860             BlockSetOps::Assign(this, newReach, block->bbReach);
1861
1862             bool predGcSafe = (block->bbPreds != nullptr); // Do all of our predecessor blocks have a GC safe bit?
1863
1864             for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
1865             {
1866                 BasicBlock* predBlock = pred->flBlock;
1867
1868                 /* Union the predecessor's reachability set into newReach */
1869                 BlockSetOps::UnionD(this, newReach, predBlock->bbReach);
1870
1871                 if (!(predBlock->bbFlags & BBF_GC_SAFE_POINT))
1872                 {
1873                     predGcSafe = false;
1874                 }
1875             }
1876
1877             if (predGcSafe)
1878             {
1879                 block->bbFlags |= BBF_GC_SAFE_POINT;
1880             }
1881
1882             if (!BlockSetOps::Equal(this, newReach, block->bbReach))
1883             {
1884                 BlockSetOps::Assign(this, block->bbReach, newReach);
1885                 change = true;
1886             }
1887         }
1888     } while (change);
1889
1890 #ifdef DEBUG
1891     if (verbose)
1892     {
1893         printf("\nAfter computing reachability sets:\n");
1894         fgDispReach();
1895     }
1896
1897     fgReachabilitySetsValid = true;
1898 #endif // DEBUG
1899 }
1900
1901 /*****************************************************************************
1902  *  Compute the entry blocks set.
1903  *
1904  *  Initialize fgEnterBlks to the set of blocks for which we don't have explicit control
1905  *  flow edges. These are the entry basic block and each of the EH handler blocks.
1906  *  For ARM, also include the BBJ_ALWAYS block of a BBJ_CALLFINALLY/BBJ_ALWAYS pair,
1907  *  to avoid creating "retless" calls, since we need the BBJ_ALWAYS for the purpose
1908  *  of unwinding, even if the call doesn't return (due to an explicit throw, for example).
1909  */
1910
1911 void Compiler::fgComputeEnterBlocksSet()
1912 {
1913 #ifdef DEBUG
1914     fgEnterBlksSetValid = false;
1915 #endif // DEBUG
1916
1917     fgEnterBlks = BlockSetOps::MakeEmpty(this);
1918
1919     /* Now set the entry basic block */
1920     BlockSetOps::AddElemD(this, fgEnterBlks, fgFirstBB->bbNum);
1921     assert(fgFirstBB->bbNum == 1);
1922
1923     if (compHndBBtabCount > 0)
1924     {
1925         /* Also 'or' in the handler basic blocks */
1926         EHblkDsc* HBtab;
1927         EHblkDsc* HBtabEnd;
1928         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
1929         {
1930             if (HBtab->HasFilter())
1931             {
1932                 BlockSetOps::AddElemD(this, fgEnterBlks, HBtab->ebdFilter->bbNum);
1933             }
1934             BlockSetOps::AddElemD(this, fgEnterBlks, HBtab->ebdHndBeg->bbNum);
1935         }
1936     }
1937
1938 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1939     // TODO-ARM-Cleanup: The ARM code here to prevent creating retless calls by adding the BBJ_ALWAYS
1940     // to the enter blocks is a bit of a compromise, because sometimes the blocks are already reachable,
1941     // and it messes up DFS ordering to have them marked as enter block. We should prevent the
1942     // creation of retless calls some other way.
1943     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
1944     {
1945         if (block->bbJumpKind == BBJ_CALLFINALLY)
1946         {
1947             assert(block->isBBCallAlwaysPair());
1948
1949             // Don't remove the BBJ_ALWAYS block that is only here for the unwinder. It might be dead
1950             // if the finally is no-return, so mark it as an entry point.
1951             BlockSetOps::AddElemD(this, fgEnterBlks, block->bbNext->bbNum);
1952         }
1953     }
1954 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1955
1956 #ifdef DEBUG
1957     if (verbose)
1958     {
1959         printf("Enter blocks: ");
1960         BlockSetOps::Iter iter(this, fgEnterBlks);
1961         unsigned          bbNum = 0;
1962         while (iter.NextElem(&bbNum))
1963         {
1964             printf("BB%02u ", bbNum);
1965         }
1966         printf("\n");
1967     }
1968 #endif // DEBUG
1969
1970 #ifdef DEBUG
1971     fgEnterBlksSetValid = true;
1972 #endif // DEBUG
1973 }
1974
1975 /*****************************************************************************
1976  *  Remove unreachable blocks.
1977  *
1978  *  Return true if any unreachable blocks were removed.
1979  */
1980
1981 bool Compiler::fgRemoveUnreachableBlocks()
1982 {
1983     assert(!fgCheapPredsValid);
1984     assert(fgReachabilitySetsValid);
1985
1986     bool        hasLoops             = false;
1987     bool        hasUnreachableBlocks = false;
1988     BasicBlock* block;
1989
1990     /* Record unreachable blocks */
1991     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1992     {
1993         /* Internal throw blocks are also reachable */
1994         if (fgIsThrowHlpBlk(block))
1995         {
1996             goto SKIP_BLOCK;
1997         }
1998         else if (block == genReturnBB)
1999         {
2000             // Don't remove statements for the genReturnBB block, as we might have special hookups there.
2001             // For example, <BUGNUM> in VSW 364383, </BUGNUM>
2002             // the profiler hookup needs to have the "void GT_RETURN" statement
2003             // to properly set the info.compProfilerCallback flag.
2004             goto SKIP_BLOCK;
2005         }
2006         else
2007         {
2008             // If any of the entry blocks can reach this block, then we skip it.
2009             if (!BlockSetOps::IsEmptyIntersection(this, fgEnterBlks, block->bbReach))
2010             {
2011                 goto SKIP_BLOCK;
2012             }
2013         }
2014
2015         // Remove all the code for the block
2016         fgUnreachableBlock(block);
2017
2018         // Make sure that the block was marked as removed */
2019         noway_assert(block->bbFlags & BBF_REMOVED);
2020
2021         // Some blocks mark the end of trys and catches
2022         // and can't be removed. We convert these into
2023         // empty blocks of type BBJ_THROW
2024
2025         if (block->bbFlags & BBF_DONT_REMOVE)
2026         {
2027             bool bIsBBCallAlwaysPair = block->isBBCallAlwaysPair();
2028
2029             /* Unmark the block as removed, */
2030             /* clear BBF_INTERNAL as well and set BBJ_IMPORTED */
2031
2032             block->bbFlags &= ~(BBF_REMOVED | BBF_INTERNAL | BBF_NEEDS_GCPOLL);
2033             block->bbFlags |= BBF_IMPORTED;
2034             block->bbJumpKind = BBJ_THROW;
2035             block->bbSetRunRarely();
2036
2037 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2038             // If this is a <BBJ_CALLFINALLY, BBJ_ALWAYS> pair, we have to clear BBF_FINALLY_TARGET flag on
2039             // the target node (of BBJ_ALWAYS) since BBJ_CALLFINALLY node is getting converted to a BBJ_THROW.
2040             if (bIsBBCallAlwaysPair)
2041             {
2042                 noway_assert(block->bbNext->bbJumpKind == BBJ_ALWAYS);
2043                 fgClearFinallyTargetBit(block->bbNext->bbJumpDest);
2044             }
2045 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2046         }
2047         else
2048         {
2049             /* We have to call fgRemoveBlock next */
2050             hasUnreachableBlocks = true;
2051         }
2052         continue;
2053
2054     SKIP_BLOCK:;
2055
2056         // if (block->isRunRarely())
2057         //    continue;
2058         if (block->bbJumpKind == BBJ_RETURN)
2059         {
2060             continue;
2061         }
2062
2063         /* Set BBF_LOOP_HEAD if we have backwards branches to this block */
2064
2065         unsigned blockNum = block->bbNum;
2066         for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
2067         {
2068             BasicBlock* predBlock = pred->flBlock;
2069             if (blockNum <= predBlock->bbNum)
2070             {
2071                 if (predBlock->bbJumpKind == BBJ_CALLFINALLY)
2072                 {
2073                     continue;
2074                 }
2075
2076                 /* If block can reach predBlock then we have a loop head */
2077                 if (BlockSetOps::IsMember(this, predBlock->bbReach, blockNum))
2078                 {
2079                     hasLoops = true;
2080
2081                     /* Set the BBF_LOOP_HEAD flag */
2082                     block->bbFlags |= BBF_LOOP_HEAD;
2083                     break;
2084                 }
2085             }
2086         }
2087     }
2088
2089     fgHasLoops = hasLoops;
2090
2091     if (hasUnreachableBlocks)
2092     {
2093         // Now remove the unreachable blocks
2094         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2095         {
2096             //  If we mark the block with BBF_REMOVED then
2097             //  we need to call fgRemovedBlock() on it
2098
2099             if (block->bbFlags & BBF_REMOVED)
2100             {
2101                 fgRemoveBlock(block, true);
2102
2103                 // When we have a BBJ_CALLFINALLY, BBJ_ALWAYS pair; fgRemoveBlock will remove
2104                 // both blocks, so we must advance 1 extra place in the block list
2105                 //
2106                 if (block->isBBCallAlwaysPair())
2107                 {
2108                     block = block->bbNext;
2109                 }
2110             }
2111         }
2112     }
2113
2114     return hasUnreachableBlocks;
2115 }
2116
2117 /*****************************************************************************
2118  *
2119  *  Function called to compute the dominator and reachable sets.
2120  *
2121  *  Assumes the predecessor lists are computed and correct.
2122  */
2123
2124 void Compiler::fgComputeReachability()
2125 {
2126 #ifdef DEBUG
2127     if (verbose)
2128     {
2129         printf("*************** In fgComputeReachability\n");
2130     }
2131
2132     fgVerifyHandlerTab();
2133
2134     // Make sure that the predecessor lists are accurate
2135     assert(fgComputePredsDone);
2136     fgDebugCheckBBlist();
2137 #endif // DEBUG
2138
2139     /* Create a list of all BBJ_RETURN blocks. The head of the list is 'fgReturnBlocks'. */
2140     fgReturnBlocks = nullptr;
2141
2142     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2143     {
2144         // If this is a BBJ_RETURN block, add it to our list of all BBJ_RETURN blocks. This list is only
2145         // used to find return blocks.
2146         if (block->bbJumpKind == BBJ_RETURN)
2147         {
2148             fgReturnBlocks = new (this, CMK_Reachability) BasicBlockList(block, fgReturnBlocks);
2149         }
2150     }
2151
2152     // Compute reachability and then delete blocks determined to be unreachable. If we delete blocks, we
2153     // need to loop, as that might have caused more blocks to become unreachable. This can happen in the
2154     // case where a call to a finally is unreachable and deleted (maybe the call to the finally is
2155     // preceded by a throw or an infinite loop), making the blocks following the finally unreachable.
2156     // However, all EH entry blocks are considered global entry blocks, causing the blocks following the
2157     // call to the finally to stay rooted, until a second round of reachability is done.
2158     // The dominator algorithm expects that all blocks can be reached from the fgEnterBlks set.
2159     unsigned passNum = 1;
2160     bool     changed;
2161     do
2162     {
2163         // Just to be paranoid, avoid infinite loops; fall back to minopts.
2164         if (passNum > 10)
2165         {
2166             noway_assert(!"Too many unreachable block removal loops");
2167         }
2168
2169         /* Walk the flow graph, reassign block numbers to keep them in ascending order */
2170         JITDUMP("\nRenumbering the basic blocks for fgComputeReachability pass #%u\n", passNum);
2171         passNum++;
2172         fgRenumberBlocks();
2173
2174         //
2175         // Compute fgEnterBlks
2176         //
2177
2178         fgComputeEnterBlocksSet();
2179
2180         //
2181         // Compute bbReach
2182         //
2183
2184         fgComputeReachabilitySets();
2185
2186         //
2187         // Use reachability information to delete unreachable blocks.
2188         // Also, determine if the flow graph has loops and set 'fgHasLoops' accordingly.
2189         // Set the BBF_LOOP_HEAD flag on the block target of backwards branches.
2190         //
2191
2192         changed = fgRemoveUnreachableBlocks();
2193
2194     } while (changed);
2195
2196 #ifdef DEBUG
2197     if (verbose)
2198     {
2199         printf("\nAfter computing reachability:\n");
2200         fgDispBasicBlocks(verboseTrees);
2201         printf("\n");
2202     }
2203
2204     fgVerifyHandlerTab();
2205     fgDebugCheckBBlist(true);
2206 #endif // DEBUG
2207
2208     //
2209     // Now, compute the dominators
2210     //
2211
2212     fgComputeDoms();
2213 }
2214
2215 /** In order to be able to compute dominance, we need to first get a DFS reverse post order sort on the basic flow graph
2216   * for the dominance algorithm to operate correctly.  The reason why we need the DFS sort is because
2217   * we will build the dominance sets using the partial order induced by the DFS sorting.  With this
2218   * precondition not holding true, the algorithm doesn't work properly.
2219   */
2220 void Compiler::fgDfsInvPostOrder()
2221 {
2222     // NOTE: This algorithm only pays attention to the actual blocks. It ignores the imaginary entry block.
2223
2224     // visited   :  Once we run the DFS post order sort recursive algorithm, we mark the nodes we visited to avoid
2225     //              backtracking.
2226     BlockSet visited(BlockSetOps::MakeEmpty(this));
2227
2228     // We begin by figuring out which basic blocks don't have incoming edges and mark them as
2229     // start nodes.  Later on we run the recursive algorithm for each node that we
2230     // mark in this step.
2231     BlockSet_ValRet_T startNodes = fgDomFindStartNodes();
2232
2233     // Make sure fgEnterBlks are still there in startNodes, even if they participate in a loop (i.e., there is
2234     // an incoming edge into the block).
2235     assert(fgEnterBlksSetValid);
2236
2237 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2238     //
2239     //    BlockSetOps::UnionD(this, startNodes, fgEnterBlks);
2240     //
2241     // This causes problems on ARM, because we for BBJ_CALLFINALLY/BBJ_ALWAYS pairs, we add the BBJ_ALWAYS
2242     // to the enter blocks set to prevent flow graph optimizations from removing it and creating retless call finallies
2243     // (BBF_RETLESS_CALL). This leads to an incorrect DFS ordering in some cases, because we start the recursive walk
2244     // from the BBJ_ALWAYS, which is reachable from other blocks. A better solution would be to change ARM to avoid
2245     // creating retless calls in a different way, not by adding BBJ_ALWAYS to fgEnterBlks.
2246     //
2247     // So, let us make sure at least fgFirstBB is still there, even if it participates in a loop.
2248     BlockSetOps::AddElemD(this, startNodes, 1);
2249     assert(fgFirstBB->bbNum == 1);
2250 #else
2251     BlockSetOps::UnionD(this, startNodes, fgEnterBlks);
2252 #endif
2253
2254     assert(BlockSetOps::IsMember(this, startNodes, fgFirstBB->bbNum));
2255
2256     // Call the flowgraph DFS traversal helper.
2257     unsigned postIndex = 1;
2258     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2259     {
2260         // If the block has no predecessors, and we haven't already visited it (because it's in fgEnterBlks but also
2261         // reachable from the first block), go ahead and traverse starting from this block.
2262         if (BlockSetOps::IsMember(this, startNodes, block->bbNum) &&
2263             !BlockSetOps::IsMember(this, visited, block->bbNum))
2264         {
2265             fgDfsInvPostOrderHelper(block, visited, &postIndex);
2266         }
2267     }
2268
2269     // After the DFS reverse postorder is completed, we must have visited all the basic blocks.
2270     noway_assert(postIndex == fgBBcount + 1);
2271     noway_assert(fgBBNumMax == fgBBcount);
2272
2273 #ifdef DEBUG
2274     if (0 && verbose)
2275     {
2276         printf("\nAfter doing a post order traversal of the BB graph, this is the ordering:\n");
2277         for (unsigned i = 1; i <= fgBBNumMax; ++i)
2278         {
2279             printf("%02u -> BB%02u\n", i, fgBBInvPostOrder[i]->bbNum);
2280         }
2281         printf("\n");
2282     }
2283 #endif // DEBUG
2284 }
2285
2286 BlockSet_ValRet_T Compiler::fgDomFindStartNodes()
2287 {
2288     unsigned    j;
2289     BasicBlock* block;
2290
2291     // startNodes ::  A set that represents which basic blocks in the flow graph don't have incoming edges.
2292     // We begin assuming everything is a start block and remove any block that is being referenced by another in its
2293     // successor list.
2294
2295     BlockSet startNodes(BlockSetOps::MakeFull(this));
2296
2297     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2298     {
2299         unsigned cSucc = block->NumSucc(this);
2300         for (j = 0; j < cSucc; ++j)
2301         {
2302             BasicBlock* succ = block->GetSucc(j, this);
2303             BlockSetOps::RemoveElemD(this, startNodes, succ->bbNum);
2304         }
2305     }
2306
2307 #ifdef DEBUG
2308     if (verbose)
2309     {
2310         printf("\nDominator computation start blocks (those blocks with no incoming edges):\n");
2311         BlockSetOps::Iter iter(this, startNodes);
2312         unsigned          bbNum = 0;
2313         while (iter.NextElem(&bbNum))
2314         {
2315             printf("BB%02u ", bbNum);
2316         }
2317         printf("\n");
2318     }
2319 #endif // DEBUG
2320
2321     return startNodes;
2322 }
2323
2324 //------------------------------------------------------------------------
2325 // fgDfsInvPostOrderHelper: Helper to assign post-order numbers to blocks.
2326 //
2327 // Arguments:
2328 //    block   - The starting entry block
2329 //    visited - The set of visited blocks
2330 //    count   - Pointer to the Dfs counter
2331 //
2332 // Notes:
2333 //    Compute a non-recursive DFS traversal of the flow graph using an
2334 //    evaluation stack to assign post-order numbers.
2335
2336 void Compiler::fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, unsigned* count)
2337 {
2338     // Assume we haven't visited this node yet (callers ensure this).
2339     assert(!BlockSetOps::IsMember(this, visited, block->bbNum));
2340
2341     // Allocate a local stack to hold the DFS traversal actions necessary
2342     // to compute pre/post-ordering of the control flowgraph.
2343     ArrayStack<DfsBlockEntry> stack(this);
2344
2345     // Push the first block on the stack to seed the traversal.
2346     stack.Push(DfsBlockEntry(DSS_Pre, block));
2347     // Flag the node we just visited to avoid backtracking.
2348     BlockSetOps::AddElemD(this, visited, block->bbNum);
2349
2350     // The search is terminated once all the actions have been processed.
2351     while (stack.Height() != 0)
2352     {
2353         DfsBlockEntry current      = stack.Pop();
2354         BasicBlock*   currentBlock = current.dfsBlock;
2355
2356         if (current.dfsStackState == DSS_Pre)
2357         {
2358             // This is a pre-visit that corresponds to the first time the
2359             // node is encountered in the spanning tree and receives pre-order
2360             // numberings. By pushing the post-action on the stack here we
2361             // are guaranteed to only process it after all of its successors
2362             // pre and post actions are processed.
2363             stack.Push(DfsBlockEntry(DSS_Post, currentBlock));
2364
2365             unsigned cSucc = currentBlock->NumSucc(this);
2366             for (unsigned j = 0; j < cSucc; ++j)
2367             {
2368                 BasicBlock* succ = currentBlock->GetSucc(j, this);
2369
2370                 // If this is a node we haven't seen before, go ahead and process
2371                 if (!BlockSetOps::IsMember(this, visited, succ->bbNum))
2372                 {
2373                     // Push a pre-visit action for this successor onto the stack and
2374                     // mark it as visited in case this block has multiple successors
2375                     // to the same node (multi-graph).
2376                     stack.Push(DfsBlockEntry(DSS_Pre, succ));
2377                     BlockSetOps::AddElemD(this, visited, succ->bbNum);
2378                 }
2379             }
2380         }
2381         else
2382         {
2383             // This is a post-visit that corresponds to the last time the
2384             // node is visited in the spanning tree and only happens after
2385             // all descendents in the spanning tree have had pre and post
2386             // actions applied.
2387
2388             assert(current.dfsStackState == DSS_Post);
2389
2390             unsigned invCount = fgBBcount - *count + 1;
2391             assert(1 <= invCount && invCount <= fgBBNumMax);
2392             fgBBInvPostOrder[invCount] = currentBlock;
2393             currentBlock->bbDfsNum     = invCount;
2394             ++(*count);
2395         }
2396     }
2397 }
2398
2399 void Compiler::fgComputeDoms()
2400 {
2401     assert(!fgCheapPredsValid);
2402
2403 #ifdef DEBUG
2404     if (verbose)
2405     {
2406         printf("*************** In fgComputeDoms\n");
2407     }
2408
2409     fgVerifyHandlerTab();
2410
2411     // Make sure that the predecessor lists are accurate.
2412     // Also check that the blocks are properly, densely numbered (so calling fgRenumberBlocks is not necessary).
2413     fgDebugCheckBBlist(true);
2414
2415     // Assert things related to the BlockSet epoch.
2416     assert(fgBBcount == fgBBNumMax);
2417     assert(BasicBlockBitSetTraits::GetSize(this) == fgBBNumMax + 1);
2418 #endif // DEBUG
2419
2420     BlockSet processedBlks(BlockSetOps::MakeEmpty(this));
2421
2422     fgBBInvPostOrder = new (this, CMK_DominatorMemory) BasicBlock*[fgBBNumMax + 1];
2423     memset(fgBBInvPostOrder, 0, sizeof(BasicBlock*) * (fgBBNumMax + 1));
2424
2425     fgDfsInvPostOrder();
2426     noway_assert(fgBBInvPostOrder[0] == nullptr);
2427
2428     // flRoot and bbRoot represent an imaginary unique entry point in the flow graph.
2429     // All the orphaned EH blocks and fgFirstBB will temporarily have its predecessors list
2430     // (with bbRoot as the only basic block in it) set as flRoot.
2431     // Later on, we clear their predecessors and let them to be nullptr again.
2432     // Since we number basic blocks starting at one, the imaginary entry block is conveniently numbered as zero.
2433     flowList   flRoot;
2434     BasicBlock bbRoot;
2435
2436     bbRoot.bbPreds  = nullptr;
2437     bbRoot.bbNum    = 0;
2438     bbRoot.bbIDom   = &bbRoot;
2439     bbRoot.bbDfsNum = 0;
2440     bbRoot.bbFlags  = 0;
2441     flRoot.flNext   = nullptr;
2442     flRoot.flBlock  = &bbRoot;
2443
2444     fgBBInvPostOrder[0] = &bbRoot;
2445
2446     // Mark both bbRoot and fgFirstBB processed
2447     BlockSetOps::AddElemD(this, processedBlks, 0); // bbRoot    == block #0
2448     BlockSetOps::AddElemD(this, processedBlks, 1); // fgFirstBB == block #1
2449     assert(fgFirstBB->bbNum == 1);
2450
2451     // Special case fgFirstBB to say its IDom is bbRoot.
2452     fgFirstBB->bbIDom = &bbRoot;
2453
2454     BasicBlock* block = nullptr;
2455
2456     for (block = fgFirstBB->bbNext; block != nullptr; block = block->bbNext)
2457     {
2458         // If any basic block has no predecessors then we flag it as processed and temporarily
2459         // mark its precedessor list to be flRoot.  This makes the flowgraph connected,
2460         // a precondition that is needed by the dominance algorithm to operate properly.
2461         if (block->bbPreds == nullptr)
2462         {
2463             block->bbPreds = &flRoot;
2464             block->bbIDom  = &bbRoot;
2465             BlockSetOps::AddElemD(this, processedBlks, block->bbNum);
2466         }
2467         else
2468         {
2469             block->bbIDom = nullptr;
2470         }
2471     }
2472
2473     // Mark the EH blocks as entry blocks and also flag them as processed.
2474     if (compHndBBtabCount > 0)
2475     {
2476         EHblkDsc* HBtab;
2477         EHblkDsc* HBtabEnd;
2478         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
2479         {
2480             if (HBtab->HasFilter())
2481             {
2482                 HBtab->ebdFilter->bbIDom = &bbRoot;
2483                 BlockSetOps::AddElemD(this, processedBlks, HBtab->ebdFilter->bbNum);
2484             }
2485             HBtab->ebdHndBeg->bbIDom = &bbRoot;
2486             BlockSetOps::AddElemD(this, processedBlks, HBtab->ebdHndBeg->bbNum);
2487         }
2488     }
2489
2490     // Now proceed to compute the immediate dominators for each basic block.
2491     bool changed = true;
2492     while (changed)
2493     {
2494         changed = false;
2495         for (unsigned i = 1; i <= fgBBNumMax;
2496              ++i) // Process each actual block; don't process the imaginary predecessor block.
2497         {
2498             flowList*   first   = nullptr;
2499             BasicBlock* newidom = nullptr;
2500             block               = fgBBInvPostOrder[i];
2501
2502             // If we have a block that has bbRoot as its bbIDom
2503             // it means we flag it as processed and as an entry block so
2504             // in this case we're all set.
2505             if (block->bbIDom == &bbRoot)
2506             {
2507                 continue;
2508             }
2509
2510             // Pick up the first processed predecesor of the current block.
2511             for (first = block->bbPreds; first != nullptr; first = first->flNext)
2512             {
2513                 if (BlockSetOps::IsMember(this, processedBlks, first->flBlock->bbNum))
2514                 {
2515                     break;
2516                 }
2517             }
2518             noway_assert(first != nullptr);
2519
2520             // We assume the first processed predecessor will be the
2521             // immediate dominator and then compute the forward flow analysis.
2522             newidom = first->flBlock;
2523             for (flowList* p = block->bbPreds; p != nullptr; p = p->flNext)
2524             {
2525                 if (p->flBlock == first->flBlock)
2526                 {
2527                     continue;
2528                 }
2529                 if (p->flBlock->bbIDom != nullptr)
2530                 {
2531                     // fgIntersectDom is basically the set intersection between
2532                     // the dominance sets of the new IDom and the current predecessor
2533                     // Since the nodes are ordered in DFS inverse post order and
2534                     // IDom induces a tree, fgIntersectDom actually computes
2535                     // the lowest common ancestor in the dominator tree.
2536                     newidom = fgIntersectDom(p->flBlock, newidom);
2537                 }
2538             }
2539
2540             // If the Immediate dominator changed, assign the new one
2541             // to the current working basic block.
2542             if (block->bbIDom != newidom)
2543             {
2544                 noway_assert(newidom != nullptr);
2545                 block->bbIDom = newidom;
2546                 changed       = true;
2547             }
2548             BlockSetOps::AddElemD(this, processedBlks, block->bbNum);
2549         }
2550     }
2551
2552     // As stated before, once we have computed immediate dominance we need to clear
2553     // all the basic blocks whose predecessor list was set to flRoot.  This
2554     // reverts that and leaves the blocks the same as before.
2555     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2556     {
2557         if (block->bbPreds == &flRoot)
2558         {
2559             block->bbPreds = nullptr;
2560         }
2561     }
2562
2563     fgCompDominatedByExceptionalEntryBlocks();
2564
2565 #ifdef DEBUG
2566     if (verbose)
2567     {
2568         fgDispDoms();
2569     }
2570 #endif
2571
2572     fgBuildDomTree();
2573
2574     fgModified   = false;
2575     fgDomBBcount = fgBBcount;
2576     assert(fgBBcount == fgBBNumMax);
2577     assert(BasicBlockBitSetTraits::GetSize(this) == fgDomBBcount + 1);
2578
2579     fgDomsComputed = true;
2580 }
2581
2582 void Compiler::fgBuildDomTree()
2583 {
2584     unsigned    i;
2585     BasicBlock* block;
2586
2587 #ifdef DEBUG
2588     if (verbose)
2589     {
2590         printf("\nInside fgBuildDomTree\n");
2591     }
2592 #endif // DEBUG
2593
2594     // domTree :: The dominance tree represented using adjacency lists. We use BasicBlockList to represent edges.
2595     // Indexed by basic block number.
2596     unsigned         bbArraySize = fgBBNumMax + 1;
2597     BasicBlockList** domTree     = new (this, CMK_DominatorMemory) BasicBlockList*[bbArraySize];
2598
2599     fgDomTreePreOrder  = new (this, CMK_DominatorMemory) unsigned[bbArraySize];
2600     fgDomTreePostOrder = new (this, CMK_DominatorMemory) unsigned[bbArraySize];
2601
2602     // Initialize all the data structures.
2603     for (i = 0; i < bbArraySize; ++i)
2604     {
2605         domTree[i]           = nullptr;
2606         fgDomTreePreOrder[i] = fgDomTreePostOrder[i] = 0;
2607     }
2608
2609     // Build the dominance tree.
2610     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2611     {
2612         // If the immediate dominator is not the imaginary root (bbRoot)
2613         // we proceed to append this block to the children of the dominator node.
2614         if (block->bbIDom->bbNum != 0)
2615         {
2616             int bbNum      = block->bbIDom->bbNum;
2617             domTree[bbNum] = new (this, CMK_DominatorMemory) BasicBlockList(block, domTree[bbNum]);
2618         }
2619         else
2620         {
2621             // This means this block had bbRoot set as its IDom.  We clear it out
2622             // and convert the tree back to a forest.
2623             block->bbIDom = nullptr;
2624         }
2625     }
2626
2627 #ifdef DEBUG
2628     if (verbose)
2629     {
2630         printf("\nAfter computing the Dominance Tree:\n");
2631         fgDispDomTree(domTree);
2632     }
2633 #endif // DEBUG
2634
2635     // Get the bitset that represents the roots of the dominance tree.
2636     // Something to note here is that the dominance tree has been converted from a forest to a tree
2637     // by using the bbRoot trick on fgComputeDoms. The reason we have a forest instead of a real tree
2638     // is because we treat the EH blocks as entry nodes so the real dominance tree is not necessarily connected.
2639     BlockSet_ValRet_T domTreeEntryNodes = fgDomTreeEntryNodes(domTree);
2640
2641     // The preorder and postorder numbers.
2642     // We start from 1 to match the bbNum ordering.
2643     unsigned preNum  = 1;
2644     unsigned postNum = 1;
2645
2646     // There will be nodes in the dominance tree that will not be reachable:
2647     // the catch blocks that return since they don't have any predecessor.
2648     // For that matter we'll keep track of how many nodes we can
2649     // reach and assert at the end that we visited all of them.
2650     unsigned domTreeReachable = fgBBcount;
2651
2652     // Once we have the dominance tree computed, we need to traverse it
2653     // to get the preorder and postorder numbers for each node.  The purpose of
2654     // this is to achieve O(1) queries for of the form A dominates B.
2655     for (i = 1; i <= fgBBNumMax; ++i)
2656     {
2657         if (BlockSetOps::IsMember(this, domTreeEntryNodes, i))
2658         {
2659             if (domTree[i] == nullptr)
2660             {
2661                 // If this is an entry node but there's no children on this
2662                 // node, it means it's unreachable so we decrement the reachable
2663                 // counter.
2664                 --domTreeReachable;
2665             }
2666             else
2667             {
2668                 // Otherwise, we do a DFS traversal of the dominator tree.
2669                 fgTraverseDomTree(i, domTree, &preNum, &postNum);
2670             }
2671         }
2672     }
2673
2674     noway_assert(preNum == domTreeReachable + 1);
2675     noway_assert(postNum == domTreeReachable + 1);
2676
2677     // Once we have all the reachable nodes numbered, we proceed to
2678     // assign numbers to the non-reachable ones, just assign incrementing
2679     // values.  We must reach fgBBcount at the end.
2680
2681     for (i = 1; i <= fgBBNumMax; ++i)
2682     {
2683         if (BlockSetOps::IsMember(this, domTreeEntryNodes, i))
2684         {
2685             if (domTree[i] == nullptr)
2686             {
2687                 fgDomTreePreOrder[i]  = preNum++;
2688                 fgDomTreePostOrder[i] = postNum++;
2689             }
2690         }
2691     }
2692
2693     noway_assert(preNum == fgBBNumMax + 1);
2694     noway_assert(postNum == fgBBNumMax + 1);
2695     noway_assert(fgDomTreePreOrder[0] == 0);  // Unused first element
2696     noway_assert(fgDomTreePostOrder[0] == 0); // Unused first element
2697
2698 #ifdef DEBUG
2699     if (0 && verbose)
2700     {
2701         printf("\nAfter traversing the dominance tree:\n");
2702         printf("PreOrder:\n");
2703         for (i = 1; i <= fgBBNumMax; ++i)
2704         {
2705             printf("BB%02u : %02u\n", i, fgDomTreePreOrder[i]);
2706         }
2707         printf("PostOrder:\n");
2708         for (i = 1; i <= fgBBNumMax; ++i)
2709         {
2710             printf("BB%02u : %02u\n", i, fgDomTreePostOrder[i]);
2711         }
2712     }
2713 #endif // DEBUG
2714 }
2715
2716 BlockSet_ValRet_T Compiler::fgDomTreeEntryNodes(BasicBlockList** domTree)
2717 {
2718     // domTreeEntryNodes ::  Set that represents which basic blocks are roots of the dominator forest.
2719
2720     BlockSet domTreeEntryNodes(BlockSetOps::MakeFull(this));
2721
2722     // First of all we need to find all the roots of the dominance forest.
2723
2724     for (unsigned i = 1; i <= fgBBNumMax; ++i)
2725     {
2726         for (BasicBlockList* current = domTree[i]; current != nullptr; current = current->next)
2727         {
2728             BlockSetOps::RemoveElemD(this, domTreeEntryNodes, current->block->bbNum);
2729         }
2730     }
2731
2732     return domTreeEntryNodes;
2733 }
2734
2735 #ifdef DEBUG
2736 void Compiler::fgDispDomTree(BasicBlockList** domTree)
2737 {
2738     for (unsigned i = 1; i <= fgBBNumMax; ++i)
2739     {
2740         if (domTree[i] != nullptr)
2741         {
2742             printf("BB%02u : ", i);
2743             for (BasicBlockList* current = domTree[i]; current != nullptr; current = current->next)
2744             {
2745                 assert(current->block);
2746                 printf("BB%02u ", current->block->bbNum);
2747             }
2748             printf("\n");
2749         }
2750     }
2751     printf("\n");
2752 }
2753 #endif // DEBUG
2754
2755 //------------------------------------------------------------------------
2756 // fgTraverseDomTree: Assign pre/post-order numbers to the dominator tree.
2757 //
2758 // Arguments:
2759 //    bbNum   - The basic block number of the starting block
2760 //    domTree - The dominator tree (as child block lists)
2761 //    preNum  - Pointer to the pre-number counter
2762 //    postNum - Pointer to the post-number counter
2763 //
2764 // Notes:
2765 //    Runs a non-recursive DFS traversal of the dominator tree using an
2766 //    evaluation stack to assign pre-order and post-order numbers.
2767 //    These numberings are used to provide constant time lookup for
2768 //    ancestor/descendent tests between pairs of nodes in the tree.
2769
2770 void Compiler::fgTraverseDomTree(unsigned bbNum, BasicBlockList** domTree, unsigned* preNum, unsigned* postNum)
2771 {
2772     noway_assert(bbNum <= fgBBNumMax);
2773
2774     // If the block preorder number is not zero it means we already visited
2775     // that node, so we skip it.
2776     if (fgDomTreePreOrder[bbNum] == 0)
2777     {
2778         // If this is the first time we visit this node, both preorder and postnumber
2779         // values must be zero.
2780         noway_assert(fgDomTreePostOrder[bbNum] == 0);
2781
2782         // Allocate a local stack to hold the Dfs traversal actions necessary
2783         // to compute pre/post-ordering of the dominator tree.
2784         ArrayStack<DfsNumEntry> stack(this);
2785
2786         // Push the first entry number on the stack to seed the traversal.
2787         stack.Push(DfsNumEntry(DSS_Pre, bbNum));
2788
2789         // The search is terminated once all the actions have been processed.
2790         while (stack.Height() != 0)
2791         {
2792             DfsNumEntry current    = stack.Pop();
2793             unsigned    currentNum = current.dfsNum;
2794
2795             if (current.dfsStackState == DSS_Pre)
2796             {
2797                 // This pre-visit action corresponds to the first time the
2798                 // node is encountered during the spanning traversal.
2799                 noway_assert(fgDomTreePreOrder[currentNum] == 0);
2800                 noway_assert(fgDomTreePostOrder[currentNum] == 0);
2801
2802                 // Assign the preorder number on the first visit.
2803                 fgDomTreePreOrder[currentNum] = (*preNum)++;
2804
2805                 // Push this nodes post-action on the stack such that all successors
2806                 // pre-order visits occur before this nodes post-action. We will assign
2807                 // its post-order numbers when we pop off the stack.
2808                 stack.Push(DfsNumEntry(DSS_Post, currentNum));
2809
2810                 // For each child in the dominator tree process its pre-actions.
2811                 for (BasicBlockList* child = domTree[currentNum]; child != nullptr; child = child->next)
2812                 {
2813                     unsigned childNum = child->block->bbNum;
2814
2815                     // This is a tree so never could have been visited
2816                     assert(fgDomTreePreOrder[childNum] == 0);
2817
2818                     // Push the successor in the dominator tree for pre-actions.
2819                     stack.Push(DfsNumEntry(DSS_Pre, childNum));
2820                 }
2821             }
2822             else
2823             {
2824                 // This post-visit action corresponds to the last time the node
2825                 // is encountered and only after all descendents in the spanning
2826                 // tree have had pre and post-order numbers assigned.
2827
2828                 assert(current.dfsStackState == DSS_Post);
2829                 assert(fgDomTreePreOrder[currentNum] != 0);
2830                 assert(fgDomTreePostOrder[currentNum] == 0);
2831
2832                 // Now assign this nodes post-order number.
2833                 fgDomTreePostOrder[currentNum] = (*postNum)++;
2834             }
2835         }
2836     }
2837 }
2838
2839 // This code finds the lowest common ancestor in the
2840 // dominator tree between two basic blocks. The LCA in the Dominance tree
2841 // represents the closest dominator between the two basic blocks. Used to
2842 // adjust the IDom value in fgComputDoms.
2843 BasicBlock* Compiler::fgIntersectDom(BasicBlock* a, BasicBlock* b)
2844 {
2845     BasicBlock* finger1 = a;
2846     BasicBlock* finger2 = b;
2847     while (finger1 != finger2)
2848     {
2849         while (finger1->bbDfsNum > finger2->bbDfsNum)
2850         {
2851             finger1 = finger1->bbIDom;
2852         }
2853         while (finger2->bbDfsNum > finger1->bbDfsNum)
2854         {
2855             finger2 = finger2->bbIDom;
2856         }
2857     }
2858     return finger1;
2859 }
2860
2861 // Return a BlockSet containing all the blocks that dominate 'block'.
2862 BlockSet_ValRet_T Compiler::fgGetDominatorSet(BasicBlock* block)
2863 {
2864     assert(block != nullptr);
2865
2866     BlockSet domSet(BlockSetOps::MakeEmpty(this));
2867
2868     do
2869     {
2870         BlockSetOps::AddElemD(this, domSet, block->bbNum);
2871         if (block == block->bbIDom)
2872         {
2873             break; // We found a cycle in the IDom list, so we're done.
2874         }
2875         block = block->bbIDom;
2876     } while (block != nullptr);
2877
2878     return domSet;
2879 }
2880
2881 /*****************************************************************************
2882  *
2883  *  fgComputeCheapPreds: Function called to compute the BasicBlock::bbCheapPreds lists.
2884  *
2885  *  No other block data is changed (e.g., bbRefs, bbFlags).
2886  *
2887  *  The cheap preds lists are similar to the normal (bbPreds) predecessor lists, but are cheaper to
2888  *  compute and store, as follows:
2889  *  1. A flow edge is typed BasicBlockList, which only has a block pointer and 'next' pointer. It doesn't
2890  *     have weights or a dup count.
2891  *  2. The preds list for a block is not sorted by block number.
2892  *  3. The predecessors of the block following a BBJ_CALLFINALLY (the corresponding BBJ_ALWAYS,
2893  *     for normal, non-retless calls to the finally) are not computed.
2894  *  4. The cheap preds lists will contain duplicates if a single switch table has multiple branches
2895  *     to the same block. Thus, we don't spend the time looking for duplicates for every edge we insert.
2896  */
2897 void Compiler::fgComputeCheapPreds()
2898 {
2899     noway_assert(!fgComputePredsDone); // We can't do this if we've got the full preds.
2900     noway_assert(fgFirstBB != nullptr);
2901
2902     BasicBlock* block;
2903
2904 #ifdef DEBUG
2905     if (verbose)
2906     {
2907         printf("\n*************** In fgComputeCheapPreds()\n");
2908         fgDispBasicBlocks();
2909         printf("\n");
2910     }
2911 #endif // DEBUG
2912
2913     // Clear out the cheap preds lists.
2914     fgRemovePreds();
2915
2916     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2917     {
2918         switch (block->bbJumpKind)
2919         {
2920             case BBJ_COND:
2921                 fgAddCheapPred(block->bbJumpDest, block);
2922                 fgAddCheapPred(block->bbNext, block);
2923                 break;
2924
2925             case BBJ_CALLFINALLY:
2926             case BBJ_LEAVE: // If fgComputeCheapPreds is called before all blocks are imported, BBJ_LEAVE blocks are
2927                             // still in the BB list.
2928             case BBJ_ALWAYS:
2929             case BBJ_EHCATCHRET:
2930                 fgAddCheapPred(block->bbJumpDest, block);
2931                 break;
2932
2933             case BBJ_NONE:
2934                 fgAddCheapPred(block->bbNext, block);
2935                 break;
2936
2937             case BBJ_EHFILTERRET:
2938                 // Connect end of filter to catch handler.
2939                 // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
2940                 // fgComputeCheapPreds before fgImport on an ill-formed program; the problem will be detected in
2941                 // fgImport.
2942                 if (block->bbJumpDest != nullptr)
2943                 {
2944                     fgAddCheapPred(block->bbJumpDest, block);
2945                 }
2946                 break;
2947
2948             case BBJ_SWITCH:
2949                 unsigned jumpCnt;
2950                 jumpCnt = block->bbJumpSwt->bbsCount;
2951                 BasicBlock** jumpTab;
2952                 jumpTab = block->bbJumpSwt->bbsDstTab;
2953
2954                 do
2955                 {
2956                     fgAddCheapPred(*jumpTab, block);
2957                 } while (++jumpTab, --jumpCnt);
2958
2959                 break;
2960
2961             case BBJ_EHFINALLYRET: // It's expensive to compute the preds for this case, so we don't for the cheap
2962                                    // preds.
2963             case BBJ_THROW:
2964             case BBJ_RETURN:
2965                 break;
2966
2967             default:
2968                 noway_assert(!"Unexpected bbJumpKind");
2969                 break;
2970         }
2971     }
2972
2973     fgCheapPredsValid = true;
2974
2975 #ifdef DEBUG
2976     if (verbose)
2977     {
2978         printf("\n*************** After fgComputeCheapPreds()\n");
2979         fgDispBasicBlocks();
2980         printf("\n");
2981     }
2982 #endif
2983 }
2984
2985 /*****************************************************************************
2986  * Add 'blockPred' to the cheap predecessor list of 'block'.
2987  */
2988
2989 void Compiler::fgAddCheapPred(BasicBlock* block, BasicBlock* blockPred)
2990 {
2991     assert(!fgComputePredsDone);
2992     assert(block != nullptr);
2993     assert(blockPred != nullptr);
2994
2995     block->bbCheapPreds = new (this, CMK_FlowList) BasicBlockList(blockPred, block->bbCheapPreds);
2996
2997 #if MEASURE_BLOCK_SIZE
2998     genFlowNodeCnt += 1;
2999     genFlowNodeSize += sizeof(BasicBlockList);
3000 #endif // MEASURE_BLOCK_SIZE
3001 }
3002
3003 /*****************************************************************************
3004  * Remove 'blockPred' from the cheap predecessor list of 'block'.
3005  * If there are duplicate edges, only remove one of them.
3006  */
3007 void Compiler::fgRemoveCheapPred(BasicBlock* block, BasicBlock* blockPred)
3008 {
3009     assert(!fgComputePredsDone);
3010     assert(fgCheapPredsValid);
3011
3012     flowList* oldEdge = nullptr;
3013
3014     assert(block != nullptr);
3015     assert(blockPred != nullptr);
3016     assert(block->bbCheapPreds != nullptr);
3017
3018     /* Is this the first block in the pred list? */
3019     if (blockPred == block->bbCheapPreds->block)
3020     {
3021         block->bbCheapPreds = block->bbCheapPreds->next;
3022     }
3023     else
3024     {
3025         BasicBlockList* pred;
3026         for (pred = block->bbCheapPreds; pred->next != nullptr; pred = pred->next)
3027         {
3028             if (blockPred == pred->next->block)
3029             {
3030                 break;
3031             }
3032         }
3033         noway_assert(pred->next != nullptr); // we better have found it!
3034         pred->next = pred->next->next;       // splice it out
3035     }
3036 }
3037
3038 void Compiler::fgRemovePreds()
3039 {
3040     C_ASSERT(offsetof(BasicBlock, bbPreds) ==
3041              offsetof(BasicBlock, bbCheapPreds)); // bbPreds and bbCheapPreds are at the same place in a union,
3042     C_ASSERT(sizeof(((BasicBlock*)nullptr)->bbPreds) ==
3043              sizeof(((BasicBlock*)nullptr)->bbCheapPreds)); // and are the same size. So, this function removes both.
3044
3045     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
3046     {
3047         block->bbPreds = nullptr;
3048     }
3049     fgComputePredsDone = false;
3050     fgCheapPredsValid  = false;
3051 }
3052
3053 /*****************************************************************************
3054  *
3055  *  Function called to compute the bbPreds lists.
3056  */
3057 void Compiler::fgComputePreds()
3058 {
3059     noway_assert(fgFirstBB);
3060
3061     BasicBlock* block;
3062
3063 #ifdef DEBUG
3064     if (verbose)
3065     {
3066         printf("\n*************** In fgComputePreds()\n");
3067         fgDispBasicBlocks();
3068         printf("\n");
3069     }
3070 #endif // DEBUG
3071
3072     // reset the refs count for each basic block
3073
3074     for (block = fgFirstBB; block; block = block->bbNext)
3075     {
3076         block->bbRefs = 0;
3077     }
3078
3079     /* the first block is always reachable! */
3080     fgFirstBB->bbRefs = 1;
3081
3082     /* Treat the initial block as a jump target */
3083     fgFirstBB->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3084
3085     fgRemovePreds();
3086
3087     for (block = fgFirstBB; block; block = block->bbNext)
3088     {
3089         switch (block->bbJumpKind)
3090         {
3091             case BBJ_CALLFINALLY:
3092                 if (!(block->bbFlags & BBF_RETLESS_CALL))
3093                 {
3094                     assert(block->isBBCallAlwaysPair());
3095
3096                     /* Mark the next block as being a jump target,
3097                        since the call target will return there */
3098                     PREFIX_ASSUME(block->bbNext != nullptr);
3099                     block->bbNext->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
3100                 }
3101
3102                 __fallthrough;
3103
3104             case BBJ_LEAVE: // Sometimes fgComputePreds is called before all blocks are imported, so BBJ_LEAVE
3105                             // blocks are still in the BB list.
3106             case BBJ_COND:
3107             case BBJ_ALWAYS:
3108             case BBJ_EHCATCHRET:
3109
3110                 /* Mark the jump dest block as being a jump target */
3111                 block->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3112
3113                 fgAddRefPred(block->bbJumpDest, block, nullptr, true);
3114
3115                 /* Is the next block reachable? */
3116
3117                 if (block->bbJumpKind != BBJ_COND)
3118                 {
3119                     break;
3120                 }
3121
3122                 noway_assert(block->bbNext);
3123
3124                 /* Fall through, the next block is also reachable */
3125                 __fallthrough;
3126
3127             case BBJ_NONE:
3128
3129                 fgAddRefPred(block->bbNext, block, nullptr, true);
3130                 break;
3131
3132             case BBJ_EHFILTERRET:
3133
3134                 // Connect end of filter to catch handler.
3135                 // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
3136                 // fgComputePreds before fgImport on an ill-formed program; the problem will be detected in fgImport.
3137                 if (block->bbJumpDest != nullptr)
3138                 {
3139                     fgAddRefPred(block->bbJumpDest, block, nullptr, true);
3140                 }
3141                 break;
3142
3143             case BBJ_EHFINALLYRET:
3144             {
3145                 /* Connect the end of the finally to the successor of
3146                   the call to this finally */
3147
3148                 if (!block->hasHndIndex())
3149                 {
3150                     NO_WAY("endfinally outside a finally/fault block.");
3151                 }
3152
3153                 unsigned  hndIndex = block->getHndIndex();
3154                 EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
3155
3156                 if (!ehDsc->HasFinallyOrFaultHandler())
3157                 {
3158                     NO_WAY("endfinally outside a finally/fault block.");
3159                 }
3160
3161                 if (ehDsc->HasFinallyHandler())
3162                 {
3163                     // Find all BBJ_CALLFINALLY that branched to this finally handler.
3164                     BasicBlock* begBlk;
3165                     BasicBlock* endBlk;
3166                     ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
3167
3168                     BasicBlock* finBeg = ehDsc->ebdHndBeg;
3169                     for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
3170                     {
3171                         if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
3172                         {
3173                             continue;
3174                         }
3175
3176                         noway_assert(bcall->isBBCallAlwaysPair());
3177                         fgAddRefPred(bcall->bbNext, block, nullptr, true);
3178                     }
3179                 }
3180             }
3181             break;
3182
3183             case BBJ_THROW:
3184             case BBJ_RETURN:
3185                 break;
3186
3187             case BBJ_SWITCH:
3188                 unsigned jumpCnt;
3189                 jumpCnt = block->bbJumpSwt->bbsCount;
3190                 BasicBlock** jumpTab;
3191                 jumpTab = block->bbJumpSwt->bbsDstTab;
3192
3193                 do
3194                 {
3195                     /* Mark the target block as being a jump target */
3196                     (*jumpTab)->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3197
3198                     fgAddRefPred(*jumpTab, block, nullptr, true);
3199                 } while (++jumpTab, --jumpCnt);
3200
3201                 break;
3202
3203             default:
3204                 noway_assert(!"Unexpected bbJumpKind");
3205                 break;
3206         }
3207     }
3208
3209     for (unsigned EHnum = 0; EHnum < compHndBBtabCount; EHnum++)
3210     {
3211         EHblkDsc* ehDsc = ehGetDsc(EHnum);
3212
3213         if (ehDsc->HasFilter())
3214         {
3215             ehDsc->ebdFilter->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3216
3217             // The first block of a filter has an artifical extra refcount.
3218             ehDsc->ebdFilter->bbRefs++;
3219         }
3220
3221         ehDsc->ebdHndBeg->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3222
3223         // The first block of a handler has an artificial extra refcount.
3224         ehDsc->ebdHndBeg->bbRefs++;
3225     }
3226
3227     fgModified         = false;
3228     fgComputePredsDone = true;
3229
3230 #ifdef DEBUG
3231     if (verbose)
3232     {
3233         printf("\n*************** After fgComputePreds()\n");
3234         fgDispBasicBlocks();
3235         printf("\n");
3236     }
3237 #endif
3238 }
3239
3240 unsigned Compiler::fgNSuccsOfFinallyRet(BasicBlock* block)
3241 {
3242     BasicBlock* bb;
3243     unsigned    res;
3244     fgSuccOfFinallyRetWork(block, ~0, &bb, &res);
3245     return res;
3246 }
3247
3248 BasicBlock* Compiler::fgSuccOfFinallyRet(BasicBlock* block, unsigned i)
3249 {
3250     BasicBlock* bb;
3251     unsigned    res;
3252     fgSuccOfFinallyRetWork(block, i, &bb, &res);
3253     return bb;
3254 }
3255
3256 void Compiler::fgSuccOfFinallyRetWork(BasicBlock* block, unsigned i, BasicBlock** bres, unsigned* nres)
3257 {
3258     assert(block->hasHndIndex()); // Otherwise, endfinally outside a finally/fault block?
3259
3260     unsigned  hndIndex = block->getHndIndex();
3261     EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
3262
3263     assert(ehDsc->HasFinallyOrFaultHandler()); // Otherwise, endfinally outside a finally/fault block.
3264
3265     *bres            = nullptr;
3266     unsigned succNum = 0;
3267
3268     if (ehDsc->HasFinallyHandler())
3269     {
3270         BasicBlock* begBlk;
3271         BasicBlock* endBlk;
3272         ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
3273
3274         BasicBlock* finBeg = ehDsc->ebdHndBeg;
3275
3276         for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
3277         {
3278             if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
3279             {
3280                 continue;
3281             }
3282
3283             assert(bcall->isBBCallAlwaysPair());
3284
3285             if (succNum == i)
3286             {
3287                 *bres = bcall->bbNext;
3288                 return;
3289             }
3290             succNum++;
3291         }
3292     }
3293     assert(i == ~0u || ehDsc->HasFaultHandler()); // Should reach here only for fault blocks.
3294     if (i == ~0u)
3295     {
3296         *nres = succNum;
3297     }
3298 }
3299
3300 Compiler::SwitchUniqueSuccSet Compiler::GetDescriptorForSwitch(BasicBlock* switchBlk)
3301 {
3302     assert(switchBlk->bbJumpKind == BBJ_SWITCH);
3303     BlockToSwitchDescMap* switchMap = GetSwitchDescMap();
3304     SwitchUniqueSuccSet   res;
3305     if (switchMap->Lookup(switchBlk, &res))
3306     {
3307         return res;
3308     }
3309     else
3310     {
3311         // We must compute the descriptor. Find which are dups, by creating a bit set with the unique successors.
3312         // We create a temporary bitset of blocks to compute the unique set of successor blocks,
3313         // since adding a block's number twice leaves just one "copy" in the bitset. Note that
3314         // we specifically don't use the BlockSet type, because doing so would require making a
3315         // call to EnsureBasicBlockEpoch() to make sure the epoch is up-to-date. However, that
3316         // can create a new epoch, thus invalidating all existing BlockSet objects, such as
3317         // reachability information stored in the blocks. To avoid that, we just use a local BitVec.
3318
3319         BitVecTraits blockVecTraits(fgBBNumMax + 1, this);
3320         BitVec       uniqueSuccBlocks(BitVecOps::MakeEmpty(&blockVecTraits));
3321         BasicBlock** jumpTable = switchBlk->bbJumpSwt->bbsDstTab;
3322         unsigned     jumpCount = switchBlk->bbJumpSwt->bbsCount;
3323         for (unsigned i = 0; i < jumpCount; i++)
3324         {
3325             BasicBlock* targ = jumpTable[i];
3326             BitVecOps::AddElemD(&blockVecTraits, uniqueSuccBlocks, targ->bbNum);
3327         }
3328         // Now we have a set of unique successors.
3329         unsigned numNonDups = BitVecOps::Count(&blockVecTraits, uniqueSuccBlocks);
3330
3331         BasicBlock** nonDups = new (getAllocator()) BasicBlock*[numNonDups];
3332
3333         unsigned nonDupInd = 0;
3334         // At this point, all unique targets are in "uniqueSuccBlocks".  As we encounter each,
3335         // add to nonDups, remove from "uniqueSuccBlocks".
3336         for (unsigned i = 0; i < jumpCount; i++)
3337         {
3338             BasicBlock* targ = jumpTable[i];
3339             if (BitVecOps::IsMember(&blockVecTraits, uniqueSuccBlocks, targ->bbNum))
3340             {
3341                 nonDups[nonDupInd] = targ;
3342                 nonDupInd++;
3343                 BitVecOps::RemoveElemD(&blockVecTraits, uniqueSuccBlocks, targ->bbNum);
3344             }
3345         }
3346
3347         assert(nonDupInd == numNonDups);
3348         assert(BitVecOps::Count(&blockVecTraits, uniqueSuccBlocks) == 0);
3349         res.numDistinctSuccs = numNonDups;
3350         res.nonDuplicates    = nonDups;
3351         switchMap->Set(switchBlk, res);
3352         return res;
3353     }
3354 }
3355
3356 void Compiler::SwitchUniqueSuccSet::UpdateTarget(CompAllocator* alloc,
3357                                                  BasicBlock*    switchBlk,
3358                                                  BasicBlock*    from,
3359                                                  BasicBlock*    to)
3360 {
3361     assert(switchBlk->bbJumpKind == BBJ_SWITCH); // Precondition.
3362     unsigned     jmpTabCnt = switchBlk->bbJumpSwt->bbsCount;
3363     BasicBlock** jmpTab    = switchBlk->bbJumpSwt->bbsDstTab;
3364
3365     // Is "from" still in the switch table (because it had more than one entry before?)
3366     bool fromStillPresent = false;
3367     for (unsigned i = 0; i < jmpTabCnt; i++)
3368     {
3369         if (jmpTab[i] == from)
3370         {
3371             fromStillPresent = true;
3372             break;
3373         }
3374     }
3375
3376     // Is "to" already in "this"?
3377     bool toAlreadyPresent = false;
3378     for (unsigned i = 0; i < numDistinctSuccs; i++)
3379     {
3380         if (nonDuplicates[i] == to)
3381         {
3382             toAlreadyPresent = true;
3383             break;
3384         }
3385     }
3386
3387     // Four cases:
3388     //   If "from" is still present, and "to" is already present, do nothing
3389     //   If "from" is still present, and "to" is not, must reallocate to add an entry.
3390     //   If "from" is not still present, and "to" is not present, write "to" where "from" was.
3391     //   If "from" is not still present, but "to" is present, remove "from".
3392     if (fromStillPresent && toAlreadyPresent)
3393     {
3394         return;
3395     }
3396     else if (fromStillPresent && !toAlreadyPresent)
3397     {
3398         // reallocate to add an entry
3399         BasicBlock** newNonDups = new (alloc) BasicBlock*[numDistinctSuccs + 1];
3400         memcpy(newNonDups, nonDuplicates, numDistinctSuccs * sizeof(BasicBlock*));
3401         newNonDups[numDistinctSuccs] = to;
3402         numDistinctSuccs++;
3403         nonDuplicates = newNonDups;
3404     }
3405     else if (!fromStillPresent && !toAlreadyPresent)
3406     {
3407 #ifdef DEBUG
3408         // write "to" where "from" was
3409         bool foundFrom = false;
3410 #endif // DEBUG
3411         for (unsigned i = 0; i < numDistinctSuccs; i++)
3412         {
3413             if (nonDuplicates[i] == from)
3414             {
3415                 nonDuplicates[i] = to;
3416 #ifdef DEBUG
3417                 foundFrom = true;
3418 #endif // DEBUG
3419                 break;
3420             }
3421         }
3422         assert(foundFrom);
3423     }
3424     else
3425     {
3426         assert(!fromStillPresent && toAlreadyPresent);
3427 #ifdef DEBUG
3428         // remove "from".
3429         bool foundFrom = false;
3430 #endif // DEBUG
3431         for (unsigned i = 0; i < numDistinctSuccs; i++)
3432         {
3433             if (nonDuplicates[i] == from)
3434             {
3435                 nonDuplicates[i] = nonDuplicates[numDistinctSuccs - 1];
3436                 numDistinctSuccs--;
3437 #ifdef DEBUG
3438                 foundFrom = true;
3439 #endif // DEBUG
3440                 break;
3441             }
3442         }
3443         assert(foundFrom);
3444     }
3445 }
3446
3447 /*****************************************************************************
3448  *
3449  *  Simple utility function to remove an entry for a block in the switch desc
3450  *  map. So it can be called from other phases.
3451  *
3452  */
3453 void Compiler::fgInvalidateSwitchDescMapEntry(BasicBlock* block)
3454 {
3455     // Check if map has no entries yet.
3456     if (m_switchDescMap != nullptr)
3457     {
3458         m_switchDescMap->Remove(block);
3459     }
3460 }
3461
3462 void Compiler::UpdateSwitchTableTarget(BasicBlock* switchBlk, BasicBlock* from, BasicBlock* to)
3463 {
3464     if (m_switchDescMap == nullptr)
3465     {
3466         return; // No mappings, nothing to do.
3467     }
3468
3469     // Otherwise...
3470     BlockToSwitchDescMap* switchMap = GetSwitchDescMap();
3471     SwitchUniqueSuccSet*  res       = switchMap->LookupPointer(switchBlk);
3472     if (res != nullptr)
3473     {
3474         // If no result, nothing to do. Otherwise, update it.
3475         res->UpdateTarget(getAllocator(), switchBlk, from, to);
3476     }
3477 }
3478
3479 /*****************************************************************************
3480  *  For a block that is in a handler region, find the first block of the most-nested
3481  *  handler containing the block.
3482  */
3483 BasicBlock* Compiler::fgFirstBlockOfHandler(BasicBlock* block)
3484 {
3485     assert(block->hasHndIndex());
3486     return ehGetDsc(block->getHndIndex())->ebdHndBeg;
3487 }
3488
3489 /*****************************************************************************
3490  *
3491  *  Function called to find back edges and return blocks and mark them as needing GC Polls.  This marks all
3492  *  blocks.
3493  */
3494 void Compiler::fgMarkGCPollBlocks()
3495 {
3496     if (GCPOLL_NONE == opts.compGCPollType)
3497     {
3498         return;
3499     }
3500
3501 #ifdef DEBUG
3502     /* Check that the flowgraph data (bbNum, bbRefs, bbPreds) is up-to-date */
3503     fgDebugCheckBBlist();
3504 #endif
3505
3506     BasicBlock* block;
3507
3508     // Return blocks always need GC polls.  In addition, all back edges (including those from switch
3509     // statements) need GC polls.  The poll is on the block with the outgoing back edge (or ret), rather than
3510     // on the destination or on the edge itself.
3511     for (block = fgFirstBB; block; block = block->bbNext)
3512     {
3513         bool blockNeedsPoll = false;
3514         switch (block->bbJumpKind)
3515         {
3516             case BBJ_COND:
3517             case BBJ_ALWAYS:
3518                 blockNeedsPoll = (block->bbJumpDest->bbNum <= block->bbNum);
3519                 break;
3520
3521             case BBJ_RETURN:
3522                 blockNeedsPoll = true;
3523                 break;
3524
3525             case BBJ_SWITCH:
3526                 unsigned jumpCnt;
3527                 jumpCnt = block->bbJumpSwt->bbsCount;
3528                 BasicBlock** jumpTab;
3529                 jumpTab = block->bbJumpSwt->bbsDstTab;
3530
3531                 do
3532                 {
3533                     if ((*jumpTab)->bbNum <= block->bbNum)
3534                     {
3535                         blockNeedsPoll = true;
3536                         break;
3537                     }
3538                 } while (++jumpTab, --jumpCnt);
3539                 break;
3540
3541             default:
3542                 break;
3543         }
3544
3545         if (blockNeedsPoll)
3546         {
3547             block->bbFlags |= BBF_NEEDS_GCPOLL;
3548         }
3549     }
3550 }
3551
3552 void Compiler::fgInitBlockVarSets()
3553 {
3554     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
3555     {
3556         block->InitVarSets(this);
3557     }
3558
3559 #ifdef LEGACY_BACKEND
3560     // QMarks are much like blocks, and need their VarSets initialized.
3561     assert(!compIsForInlining());
3562     for (unsigned i = 0; i < compQMarks->Size(); i++)
3563     {
3564         GenTree* qmark = compQMarks->Get(i);
3565         // Perhaps the gtOper of a QMark node was changed to something else since it was created and put on this list.
3566         // So can't hurt to check.
3567         if (qmark->OperGet() == GT_QMARK)
3568         {
3569             VarSetOps::AssignAllowUninitRhs(this, qmark->gtQmark.gtThenLiveSet, VarSetOps::UninitVal());
3570             VarSetOps::AssignAllowUninitRhs(this, qmark->gtQmark.gtElseLiveSet, VarSetOps::UninitVal());
3571         }
3572     }
3573 #endif // LEGACY_BACKEND
3574     fgBBVarSetsInited = true;
3575 }
3576
3577 /*****************************************************************************
3578  *
3579  *  The following does the final pass on BBF_NEEDS_GCPOLL and then actually creates the GC Polls.
3580  */
3581 void Compiler::fgCreateGCPolls()
3582 {
3583     if (GCPOLL_NONE == opts.compGCPollType)
3584     {
3585         return;
3586     }
3587
3588     bool createdPollBlocks = false;
3589
3590 #ifdef DEBUG
3591     if (verbose)
3592     {
3593         printf("*************** In fgCreateGCPolls() for %s\n", info.compFullName);
3594     }
3595 #endif // DEBUG
3596
3597     if (!(opts.MinOpts() || opts.compDbgCode))
3598     {
3599         // Remove polls from well formed loops with a constant upper bound.
3600         for (unsigned lnum = 0; lnum < optLoopCount; ++lnum)
3601         {
3602             // Look for constant counted loops that run for a short duration.  This logic is very similar to
3603             // what's in code:Compiler::optUnrollLoops, since they have similar constraints.  However, this
3604             // logic is much more permissive since we're not doing a complex transformation.
3605
3606             /* TODO-Cleanup:
3607              * I feel bad cloning so much logic from optUnrollLoops
3608              */
3609
3610             // Filter out loops not meeting the obvious preconditions.
3611             //
3612             if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED)
3613             {
3614                 continue;
3615             }
3616
3617             if (!(optLoopTable[lnum].lpFlags & LPFLG_CONST))
3618             {
3619                 continue;
3620             }
3621
3622             BasicBlock* head   = optLoopTable[lnum].lpHead;
3623             BasicBlock* bottom = optLoopTable[lnum].lpBottom;
3624
3625             // Loops dominated by GC_SAFE_POINT won't have this set.
3626             if (!(bottom->bbFlags & BBF_NEEDS_GCPOLL))
3627             {
3628                 continue;
3629             }
3630
3631             /* Get the loop data:
3632                 - initial constant
3633                 - limit constant
3634                 - iterator
3635                 - iterator increment
3636                 - increment operation type (i.e. ASG_ADD, ASG_SUB, etc...)
3637                 - loop test type (i.e. GT_GE, GT_LT, etc...)
3638              */
3639
3640             int        lbeg     = optLoopTable[lnum].lpConstInit;
3641             int        llim     = optLoopTable[lnum].lpConstLimit();
3642             genTreeOps testOper = optLoopTable[lnum].lpTestOper();
3643
3644             int        lvar     = optLoopTable[lnum].lpIterVar();
3645             int        iterInc  = optLoopTable[lnum].lpIterConst();
3646             genTreeOps iterOper = optLoopTable[lnum].lpIterOper();
3647
3648             var_types iterOperType = optLoopTable[lnum].lpIterOperType();
3649             bool      unsTest      = (optLoopTable[lnum].lpTestTree->gtFlags & GTF_UNSIGNED) != 0;
3650             if (lvaTable[lvar].lvAddrExposed)
3651             { // Can't reason about the value of the iteration variable.
3652                 continue;
3653             }
3654
3655             unsigned totalIter;
3656
3657             /* Find the number of iterations - the function returns false if not a constant number */
3658
3659             if (!optComputeLoopRep(lbeg, llim, iterInc, iterOper, iterOperType, testOper, unsTest,
3660                                    // The value here doesn't matter for this variation of the optimization
3661                                    true, &totalIter))
3662             {
3663 #ifdef DEBUG
3664                 if (verbose)
3665                 {
3666                     printf("Could not compute loop iterations for loop from BB%02u to BB%02u", head->bbNum,
3667                            bottom->bbNum);
3668                 }
3669 #endif                      // DEBUG
3670                 (void)head; // suppress gcc error.
3671
3672                 continue;
3673             }
3674
3675             /* Forget it if there are too many repetitions or not a constant loop */
3676
3677             static const unsigned ITER_LIMIT = 256;
3678             if (totalIter > ITER_LIMIT)
3679             {
3680                 continue;
3681             }
3682
3683             // It is safe to elminate the poll from this loop.
3684             bottom->bbFlags &= ~BBF_NEEDS_GCPOLL;
3685
3686 #ifdef DEBUG
3687             if (verbose)
3688             {
3689                 printf("Removing poll in block BB%02u because it forms a bounded counted loop\n", bottom->bbNum);
3690             }
3691 #endif // DEBUG
3692         }
3693     }
3694
3695     // Final chance to optimize the polls.  Move all polls in loops from the bottom of the loop up to the
3696     // loop head.  Also eliminate all epilog polls in non-leaf methods.  This only works if we have dominator
3697     // information.
3698     if (fgDomsComputed)
3699     {
3700         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
3701         {
3702             if (!(block->bbFlags & BBF_NEEDS_GCPOLL))
3703             {
3704                 continue;
3705             }
3706
3707             if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
3708             {
3709                 // make sure that this is loop-like
3710                 if (!fgReachable(block->bbJumpDest, block))
3711                 {
3712                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3713 #ifdef DEBUG
3714                     if (verbose)
3715                     {
3716                         printf("Removing poll in block BB%02u because it is not loop\n", block->bbNum);
3717                     }
3718 #endif // DEBUG
3719                     continue;
3720                 }
3721             }
3722             else if (!(block->bbJumpKind == BBJ_RETURN || block->bbJumpKind == BBJ_SWITCH))
3723             {
3724                 noway_assert(!"GC Poll on a block that has no control transfer.");
3725 #ifdef DEBUG
3726                 if (verbose)
3727                 {
3728                     printf("Removing poll in block BB%02u because it is not a jump\n", block->bbNum);
3729                 }
3730 #endif // DEBUG
3731                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3732                 continue;
3733             }
3734
3735             // Because of block compaction, it's possible to end up with a block that is both poll and safe.
3736             // Clean those up now.
3737
3738             if (block->bbFlags & BBF_GC_SAFE_POINT)
3739             {
3740 #ifdef DEBUG
3741                 if (verbose)
3742                 {
3743                     printf("Removing poll in return block BB%02u because it is GC Safe\n", block->bbNum);
3744                 }
3745 #endif // DEBUG
3746                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3747                 continue;
3748             }
3749
3750             if (block->bbJumpKind == BBJ_RETURN)
3751             {
3752                 if (!optReachWithoutCall(fgFirstBB, block))
3753                 {
3754                     // check to see if there is a call along the path between the first block and the return
3755                     // block.
3756                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3757 #ifdef DEBUG
3758                     if (verbose)
3759                     {
3760                         printf("Removing poll in return block BB%02u because it dominated by a call\n", block->bbNum);
3761                     }
3762 #endif // DEBUG
3763                     continue;
3764                 }
3765             }
3766         }
3767     }
3768
3769     noway_assert(!fgGCPollsCreated);
3770     BasicBlock* block;
3771     fgGCPollsCreated = true;
3772
3773     // Walk through the blocks and hunt for a block that has BBF_NEEDS_GCPOLL
3774     for (block = fgFirstBB; block; block = block->bbNext)
3775     {
3776         // Because of block compaction, it's possible to end up with a block that is both poll and safe.
3777         // And if !fgDomsComputed, we won't have cleared them, so skip them now
3778         if (!(block->bbFlags & BBF_NEEDS_GCPOLL) || (block->bbFlags & BBF_GC_SAFE_POINT))
3779         {
3780             continue;
3781         }
3782
3783         // This block needs a poll.  We either just insert a callout or we split the block and inline part of
3784         // the test.  This depends on the value of opts.compGCPollType.
3785
3786         // If we're doing GCPOLL_CALL, just insert a GT_CALL node before the last node in the block.
3787         CLANG_FORMAT_COMMENT_ANCHOR;
3788
3789 #ifdef DEBUG
3790         switch (block->bbJumpKind)
3791         {
3792             case BBJ_RETURN:
3793             case BBJ_ALWAYS:
3794             case BBJ_COND:
3795             case BBJ_SWITCH:
3796                 break;
3797             default:
3798                 noway_assert(!"Unknown block type for BBF_NEEDS_GCPOLL");
3799         }
3800 #endif // DEBUG
3801
3802         noway_assert(opts.compGCPollType);
3803
3804         GCPollType pollType = opts.compGCPollType;
3805         // pollType is set to either CALL or INLINE at this point.  Below is the list of places where we
3806         // can't or don't want to emit an inline check.  Check all of those.  If after all of that we still
3807         // have INLINE, then emit an inline check.
3808
3809         if (opts.MinOpts() || opts.compDbgCode)
3810         {
3811 #ifdef DEBUG
3812             if (verbose)
3813             {
3814                 printf("Selecting CALL poll in block BB%02u because of debug/minopts\n", block->bbNum);
3815             }
3816 #endif // DEBUG
3817
3818             // Don't split blocks and create inlined polls unless we're optimizing.
3819             pollType = GCPOLL_CALL;
3820         }
3821         else if (genReturnBB == block)
3822         {
3823 #ifdef DEBUG
3824             if (verbose)
3825             {
3826                 printf("Selecting CALL poll in block BB%02u because it is the single return block\n", block->bbNum);
3827             }
3828 #endif // DEBUG
3829
3830             // we don't want to split the single return block
3831             pollType = GCPOLL_CALL;
3832         }
3833         else if (BBJ_SWITCH == block->bbJumpKind)
3834         {
3835 #ifdef DEBUG
3836             if (verbose)
3837             {
3838                 printf("Selecting CALL poll in block BB%02u because it is a loop formed by a SWITCH\n", block->bbNum);
3839             }
3840 #endif // DEBUG
3841
3842             // I don't want to deal with all the outgoing edges of a switch block.
3843             pollType = GCPOLL_CALL;
3844         }
3845
3846         // TODO-Cleanup: potentially don't split if we're in an EH region.
3847
3848         createdPollBlocks |= fgCreateGCPoll(pollType, block);
3849     }
3850
3851     // If we split a block to create a GC Poll, then rerun fgReorderBlocks to push the rarely run blocks out
3852     // past the epilog.  We should never split blocks unless we're optimizing.
3853     if (createdPollBlocks)
3854     {
3855         noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3856         fgReorderBlocks();
3857     }
3858 }
3859
3860 /*****************************************************************************
3861  *
3862  *  Actually create a GCPoll in the given block. Returns true if it created
3863  *  a basic block.
3864  */
3865
3866 bool Compiler::fgCreateGCPoll(GCPollType pollType, BasicBlock* block)
3867 {
3868     assert(!(block->bbFlags & BBF_GC_SAFE_POINT));
3869     bool createdPollBlocks;
3870
3871     void* addrTrap;
3872     void* pAddrOfCaptureThreadGlobal;
3873
3874     addrTrap = info.compCompHnd->getAddrOfCaptureThreadGlobal(&pAddrOfCaptureThreadGlobal);
3875
3876 #ifdef ENABLE_FAST_GCPOLL_HELPER
3877     // I never want to split blocks if we've got two indirections here.
3878     // This is a size trade-off assuming the VM has ENABLE_FAST_GCPOLL_HELPER.
3879     // So don't do it when that is off
3880     if (pAddrOfCaptureThreadGlobal != NULL)
3881     {
3882         pollType = GCPOLL_CALL;
3883     }
3884 #endif // ENABLE_FAST_GCPOLL_HELPER
3885
3886     if (GCPOLL_CALL == pollType)
3887     {
3888         createdPollBlocks = false;
3889         GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_POLL_GC, TYP_VOID);
3890 #ifdef LEGACY_BACKEND
3891         call->gtFlags |= GTF_CALL_REG_SAVE;
3892 #endif // LEGACY_BACKEND
3893
3894         // for BBJ_ALWAYS I don't need to insert it before the condition.  Just append it.
3895         if (block->bbJumpKind == BBJ_ALWAYS)
3896         {
3897             fgInsertStmtAtEnd(block, call);
3898         }
3899         else
3900         {
3901             GenTreeStmt* newStmt = fgInsertStmtNearEnd(block, call);
3902             // For DDB156656, we need to associate the GC Poll with the IL offset (and therefore sequence
3903             // point) of the tree before which we inserted the poll.  One example of when this is a
3904             // problem:
3905             //  if (...) {  //1
3906             //      ...
3907             //  } //2
3908             //  else { //3
3909             //      ...
3910             //  }
3911             //  (gcpoll) //4
3912             //  return. //5
3913             //
3914             //  If we take the if statement at 1, we encounter a jump at 2.  This jumps over the else
3915             //  and lands at 4.  4 is where we inserted the gcpoll.  However, that is associated with
3916             //  the sequence point a 3.  Therefore, the debugger displays the wrong source line at the
3917             //  gc poll location.
3918             //
3919             //  More formally, if control flow targets an instruction, that instruction must be the
3920             //  start of a new sequence point.
3921             if (newStmt->gtNext)
3922             {
3923                 // Is it possible for gtNext to be NULL?
3924                 noway_assert(newStmt->gtNext->gtOper == GT_STMT);
3925                 newStmt->gtStmtILoffsx = newStmt->gtNextStmt->gtStmtILoffsx;
3926             }
3927         }
3928
3929         block->bbFlags |= BBF_GC_SAFE_POINT;
3930 #ifdef DEBUG
3931         if (verbose)
3932         {
3933             printf("*** creating GC Poll in block BB%02u\n", block->bbNum);
3934             gtDispTreeList(block->bbTreeList);
3935         }
3936 #endif // DEBUG
3937     }
3938     else
3939     {
3940         createdPollBlocks = true;
3941         // if we're doing GCPOLL_INLINE, then:
3942         //  1) Create two new blocks: Poll and Bottom.  The original block is called Top.
3943
3944         // I want to create:
3945         // top -> poll -> bottom (lexically)
3946         // so that we jump over poll to get to bottom.
3947         BasicBlock* top         = block;
3948         BasicBlock* poll        = fgNewBBafter(BBJ_NONE, top, true);
3949         BasicBlock* bottom      = fgNewBBafter(top->bbJumpKind, poll, true);
3950         BBjumpKinds oldJumpKind = top->bbJumpKind;
3951
3952         // Update block flags
3953         const unsigned __int64 originalFlags = top->bbFlags | BBF_GC_SAFE_POINT;
3954
3955         // Unlike Fei's inliner from puclr, I'm allowed to split loops.
3956         // And we keep a few other flags...
3957         noway_assert((originalFlags & (BBF_SPLIT_NONEXIST & ~(BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1))) == 0);
3958         top->bbFlags = originalFlags & (~BBF_SPLIT_LOST | BBF_GC_SAFE_POINT);
3959         bottom->bbFlags |= originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT);
3960         bottom->inheritWeight(top);
3961         poll->bbFlags |= originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT);
3962
3963         //  9) Mark Poll as rarely run.
3964         poll->bbSetRunRarely();
3965
3966         //  5) Bottom gets all the outgoing edges and inherited flags of Original.
3967         bottom->bbJumpDest = top->bbJumpDest;
3968
3969         //  2) Add a GC_CALL node to Poll.
3970         GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_POLL_GC, TYP_VOID);
3971 #ifdef LEGACY_BACKEND
3972         call->gtFlags |= GTF_CALL_REG_SAVE;
3973 #endif // LEGACY_BACKEND
3974         fgInsertStmtAtEnd(poll, call);
3975
3976         //  3) Remove the last statement from Top and add it to Bottom.
3977         if (oldJumpKind != BBJ_ALWAYS)
3978         {
3979             // if I'm always jumping to the target, then this is not a condition that needs moving.
3980             GenTreeStmt* stmt = top->firstStmt();
3981             while (stmt->gtNext)
3982             {
3983                 stmt = stmt->gtNextStmt;
3984             }
3985             fgRemoveStmt(top, stmt);
3986             fgInsertStmtAtEnd(bottom, stmt);
3987         }
3988
3989         // for BBJ_ALWAYS blocks, bottom is an empty block.
3990
3991         //  4) Create a GT_EQ node that checks against g_TrapReturningThreads.  True jumps to Bottom,
3992         //  false falls through to poll.  Add this to the end of Top.  Top is now BBJ_COND.  Bottom is
3993         //  now a jump target
3994         CLANG_FORMAT_COMMENT_ANCHOR;
3995
3996 #ifdef ENABLE_FAST_GCPOLL_HELPER
3997         // Prefer the fast gc poll helepr over the double indirection
3998         noway_assert(pAddrOfCaptureThreadGlobal == nullptr);
3999 #endif
4000
4001         GenTree* value; // The value of g_TrapReturningThreads
4002         if (pAddrOfCaptureThreadGlobal != nullptr)
4003         {
4004             // Use a double indirection
4005             GenTree* addr =
4006                 gtNewIndOfIconHandleNode(TYP_I_IMPL, (size_t)pAddrOfCaptureThreadGlobal, GTF_ICON_PTR_HDL, true);
4007
4008             value = gtNewOperNode(GT_IND, TYP_INT, addr);
4009             // This indirection won't cause an exception.
4010             value->gtFlags |= GTF_IND_NONFAULTING;
4011         }
4012         else
4013         {
4014             // Use a single indirection
4015             value = gtNewIndOfIconHandleNode(TYP_INT, (size_t)addrTrap, GTF_ICON_PTR_HDL, false);
4016         }
4017
4018         // Treat the reading of g_TrapReturningThreads as volatile.
4019         value->gtFlags |= GTF_IND_VOLATILE;
4020
4021         // Compare for equal to zero
4022         GenTree* trapRelop = gtNewOperNode(GT_EQ, TYP_INT, value, gtNewIconNode(0, TYP_INT));
4023
4024         trapRelop->gtFlags |= GTF_RELOP_JMP_USED | GTF_DONT_CSE;
4025         GenTree* trapCheck = gtNewOperNode(GT_JTRUE, TYP_VOID, trapRelop);
4026         fgInsertStmtAtEnd(top, trapCheck);
4027         top->bbJumpDest = bottom;
4028         top->bbJumpKind = BBJ_COND;
4029         bottom->bbFlags |= BBF_JMP_TARGET;
4030
4031         //  7) Bottom has Top and Poll as its predecessors.  Poll has just Top as a predecessor.
4032         fgAddRefPred(bottom, poll);
4033         fgAddRefPred(bottom, top);
4034         fgAddRefPred(poll, top);
4035
4036         //  8) Replace Top with Bottom in the predecessor list of all outgoing edges from Bottom (1 for
4037         //      jumps, 2 for conditional branches, N for switches).
4038         switch (oldJumpKind)
4039         {
4040             case BBJ_RETURN:
4041                 // no successors
4042                 break;
4043             case BBJ_COND:
4044                 // replace predecessor in the fall through block.
4045                 noway_assert(bottom->bbNext);
4046                 fgReplacePred(bottom->bbNext, top, bottom);
4047
4048                 // fall through for the jump target
4049                 __fallthrough;
4050
4051             case BBJ_ALWAYS:
4052                 fgReplacePred(bottom->bbJumpDest, top, bottom);
4053                 break;
4054             case BBJ_SWITCH:
4055                 NO_WAY("SWITCH should be a call rather than an inlined poll.");
4056                 break;
4057             default:
4058                 NO_WAY("Unknown block type for updating predecessor lists.");
4059         }
4060
4061         top->bbFlags &= ~BBF_NEEDS_GCPOLL;
4062         noway_assert(!(poll->bbFlags & BBF_NEEDS_GCPOLL));
4063         noway_assert(!(bottom->bbFlags & BBF_NEEDS_GCPOLL));
4064
4065         if (compCurBB == top)
4066         {
4067             compCurBB = bottom;
4068         }
4069
4070 #ifdef DEBUG
4071         if (verbose)
4072         {
4073             printf("*** creating inlined GC Poll in top block BB%02u\n", top->bbNum);
4074             gtDispTreeList(top->bbTreeList);
4075             printf(" poll block is BB%02u\n", poll->bbNum);
4076             gtDispTreeList(poll->bbTreeList);
4077             printf(" bottom block is BB%02u\n", bottom->bbNum);
4078             gtDispTreeList(bottom->bbTreeList);
4079         }
4080 #endif // DEBUG
4081     }
4082
4083     return createdPollBlocks;
4084 }
4085
4086 /*****************************************************************************
4087  *
4088  *  The following helps find a basic block given its PC offset.
4089  */
4090
4091 void Compiler::fgInitBBLookup()
4092 {
4093     BasicBlock** dscBBptr;
4094     BasicBlock*  tmpBBdesc;
4095
4096     /* Allocate the basic block table */
4097
4098     dscBBptr = fgBBs = new (this, CMK_BasicBlock) BasicBlock*[fgBBcount];
4099
4100     /* Walk all the basic blocks, filling in the table */
4101
4102     for (tmpBBdesc = fgFirstBB; tmpBBdesc; tmpBBdesc = tmpBBdesc->bbNext)
4103     {
4104         *dscBBptr++ = tmpBBdesc;
4105     }
4106
4107     noway_assert(dscBBptr == fgBBs + fgBBcount);
4108 }
4109
4110 BasicBlock* Compiler::fgLookupBB(unsigned addr)
4111 {
4112     unsigned lo;
4113     unsigned hi;
4114
4115     /* Do a binary search */
4116
4117     for (lo = 0, hi = fgBBcount - 1;;)
4118     {
4119
4120     AGAIN:;
4121
4122         if (lo > hi)
4123         {
4124             break;
4125         }
4126
4127         unsigned    mid = (lo + hi) / 2;
4128         BasicBlock* dsc = fgBBs[mid];
4129
4130         // We introduce internal blocks for BBJ_CALLFINALLY. Skip over these.
4131
4132         while (dsc->bbFlags & BBF_INTERNAL)
4133         {
4134             dsc = dsc->bbNext;
4135             mid++;
4136
4137             // We skipped over too many, Set hi back to the original mid - 1
4138
4139             if (mid > hi)
4140             {
4141                 mid = (lo + hi) / 2;
4142                 hi  = mid - 1;
4143                 goto AGAIN;
4144             }
4145         }
4146
4147         unsigned pos = dsc->bbCodeOffs;
4148
4149         if (pos < addr)
4150         {
4151             if ((lo == hi) && (lo == (fgBBcount - 1)))
4152             {
4153                 noway_assert(addr == dsc->bbCodeOffsEnd);
4154                 return nullptr; // NULL means the end of method
4155             }
4156             lo = mid + 1;
4157             continue;
4158         }
4159
4160         if (pos > addr)
4161         {
4162             hi = mid - 1;
4163             continue;
4164         }
4165
4166         return dsc;
4167     }
4168 #ifdef DEBUG
4169     printf("ERROR: Couldn't find basic block at offset %04X\n", addr);
4170 #endif // DEBUG
4171     NO_WAY("fgLookupBB failed.");
4172 }
4173
4174 /*****************************************************************************
4175  *
4176  *  The 'jump target' array uses the following flags to indicate what kind
4177  *  of label is present.
4178  */
4179
4180 #define JT_NONE 0x00  // This IL offset is never used
4181 #define JT_ADDR 0x01  // merely make sure this is an OK address
4182 #define JT_JUMP 0x02  // 'normal' jump target
4183 #define JT_MULTI 0x04 // target of multiple jumps
4184
4185 inline void Compiler::fgMarkJumpTarget(BYTE* jumpTarget, unsigned offs)
4186 {
4187     /* Make sure we set JT_MULTI if target of multiple jumps */
4188
4189     noway_assert(JT_MULTI == JT_JUMP << 1);
4190
4191     jumpTarget[offs] |= (jumpTarget[offs] & JT_JUMP) << 1 | JT_JUMP;
4192 }
4193
4194 //------------------------------------------------------------------------
4195 // FgStack: simple stack model for the inlinee's evaluation stack.
4196 //
4197 // Model the inputs available to various operations in the inline body.
4198 // Tracks constants, arguments, array lengths.
4199
4200 class FgStack
4201 {
4202 public:
4203     FgStack() : slot0(SLOT_INVALID), slot1(SLOT_INVALID), depth(0)
4204     {
4205         // Empty
4206     }
4207
4208     void Clear()
4209     {
4210         depth = 0;
4211     }
4212     void PushUnknown()
4213     {
4214         Push(SLOT_UNKNOWN);
4215     }
4216     void PushConstant()
4217     {
4218         Push(SLOT_CONSTANT);
4219     }
4220     void PushArrayLen()
4221     {
4222         Push(SLOT_ARRAYLEN);
4223     }
4224     void PushArgument(unsigned arg)
4225     {
4226         Push(SLOT_ARGUMENT + arg);
4227     }
4228     unsigned GetSlot0() const
4229     {
4230         assert(depth >= 1);
4231         return slot0;
4232     }
4233     unsigned GetSlot1() const
4234     {
4235         assert(depth >= 2);
4236         return slot1;
4237     }
4238     static bool IsConstant(unsigned value)
4239     {
4240         return value == SLOT_CONSTANT;
4241     }
4242     static bool IsArrayLen(unsigned value)
4243     {
4244         return value == SLOT_ARRAYLEN;
4245     }
4246     static bool IsArgument(unsigned value)
4247     {
4248         return value >= SLOT_ARGUMENT;
4249     }
4250     static unsigned SlotTypeToArgNum(unsigned value)
4251     {
4252         assert(IsArgument(value));
4253         return value - SLOT_ARGUMENT;
4254     }
4255     bool IsStackTwoDeep() const
4256     {
4257         return depth == 2;
4258     }
4259     bool IsStackOneDeep() const
4260     {
4261         return depth == 1;
4262     }
4263     bool IsStackAtLeastOneDeep() const
4264     {
4265         return depth >= 1;
4266     }
4267
4268 private:
4269     enum
4270     {
4271         SLOT_INVALID  = UINT_MAX,
4272         SLOT_UNKNOWN  = 0,
4273         SLOT_CONSTANT = 1,
4274         SLOT_ARRAYLEN = 2,
4275         SLOT_ARGUMENT = 3
4276     };
4277
4278     void Push(int type)
4279     {
4280         switch (depth)
4281         {
4282             case 0:
4283                 ++depth;
4284                 slot0 = type;
4285                 break;
4286             case 1:
4287                 ++depth;
4288                 __fallthrough;
4289             case 2:
4290                 slot1 = slot0;
4291                 slot0 = type;
4292         }
4293     }
4294
4295     unsigned slot0;
4296     unsigned slot1;
4297     unsigned depth;
4298 };
4299
4300 //------------------------------------------------------------------------
4301 // fgFindJumpTargets: walk the IL stream, determining jump target offsets
4302 //
4303 // Arguments:
4304 //    codeAddr   - base address of the IL code buffer
4305 //    codeSize   - number of bytes in the IL code buffer
4306 //    jumpTarget - [OUT] byte array for flagging jump targets
4307 //
4308 // Notes:
4309 //    If inlining or prejitting the root, this method also makes
4310 //    various observations about the method that factor into inline
4311 //    decisions.
4312 //
4313 //    May throw an exception if the IL is malformed.
4314 //
4315 //    jumpTarget[N] is set to a JT_* value if IL offset N is a
4316 //    jump target in the method.
4317 //
4318 //    Also sets lvAddrExposed and lvHasILStoreOp, ilHasMultipleILStoreOp in lvaTable[].
4319
4320 #ifdef _PREFAST_
4321 #pragma warning(push)
4322 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
4323 #endif
4324
4325 void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget)
4326 {
4327     const BYTE* codeBegp = codeAddr;
4328     const BYTE* codeEndp = codeAddr + codeSize;
4329     unsigned    varNum;
4330     bool        seenJump = false;
4331     var_types   varType  = DUMMY_INIT(TYP_UNDEF); // TYP_ type
4332     typeInfo    ti;                               // Verifier type.
4333     bool        typeIsNormed = false;
4334     FgStack     pushedStack;
4335     const bool  isForceInline          = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0;
4336     const bool  makeInlineObservations = (compInlineResult != nullptr);
4337     const bool  isInlining             = compIsForInlining();
4338     unsigned    retBlocks              = 0;
4339
4340     if (makeInlineObservations)
4341     {
4342         // Observe force inline state and code size.
4343         compInlineResult->NoteBool(InlineObservation::CALLEE_IS_FORCE_INLINE, isForceInline);
4344         compInlineResult->NoteInt(InlineObservation::CALLEE_IL_CODE_SIZE, codeSize);
4345
4346         // Determine if call site is within a try.
4347         if (isInlining && impInlineInfo->iciBlock->hasTryIndex())
4348         {
4349             compInlineResult->Note(InlineObservation::CALLSITE_IN_TRY_REGION);
4350         }
4351
4352         // Determine if the call site is in a loop.
4353         if (isInlining && ((impInlineInfo->iciBlock->bbFlags & BBF_BACKWARD_JUMP) != 0))
4354         {
4355             compInlineResult->Note(InlineObservation::CALLSITE_IN_LOOP);
4356         }
4357
4358 #ifdef DEBUG
4359
4360         // If inlining, this method should still be a candidate.
4361         if (isInlining)
4362         {
4363             assert(compInlineResult->IsCandidate());
4364         }
4365
4366 #endif // DEBUG
4367
4368         // note that we're starting to look at the opcodes.
4369         compInlineResult->Note(InlineObservation::CALLEE_BEGIN_OPCODE_SCAN);
4370     }
4371
4372     while (codeAddr < codeEndp)
4373     {
4374         OPCODE opcode = (OPCODE)getU1LittleEndian(codeAddr);
4375         codeAddr += sizeof(__int8);
4376         opts.instrCount++;
4377         typeIsNormed = false;
4378
4379     DECODE_OPCODE:
4380
4381         if ((unsigned)opcode >= CEE_COUNT)
4382         {
4383             BADCODE3("Illegal opcode", ": %02X", (int)opcode);
4384         }
4385
4386         if ((opcode >= CEE_LDARG_0 && opcode <= CEE_STLOC_S) || (opcode >= CEE_LDARG && opcode <= CEE_STLOC))
4387         {
4388             opts.lvRefCount++;
4389         }
4390
4391         if (makeInlineObservations && (opcode >= CEE_LDNULL) && (opcode <= CEE_LDC_R8))
4392         {
4393             pushedStack.PushConstant();
4394         }
4395
4396         unsigned sz = opcodeSizes[opcode];
4397
4398         switch (opcode)
4399         {
4400             case CEE_PREFIX1:
4401             {
4402                 if (codeAddr >= codeEndp)
4403                 {
4404                     goto TOO_FAR;
4405                 }
4406                 opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr));
4407                 codeAddr += sizeof(__int8);
4408                 goto DECODE_OPCODE;
4409             }
4410
4411             case CEE_PREFIX2:
4412             case CEE_PREFIX3:
4413             case CEE_PREFIX4:
4414             case CEE_PREFIX5:
4415             case CEE_PREFIX6:
4416             case CEE_PREFIX7:
4417             case CEE_PREFIXREF:
4418             {
4419                 BADCODE3("Illegal opcode", ": %02X", (int)opcode);
4420             }
4421
4422             case CEE_CALL:
4423             case CEE_CALLVIRT:
4424             {
4425                 // There has to be code after the call, otherwise the inlinee is unverifiable.
4426                 if (isInlining)
4427                 {
4428
4429                     noway_assert(codeAddr < codeEndp - sz);
4430                 }
4431
4432                 // If the method has a call followed by a ret, assume that
4433                 // it is a wrapper method.
4434                 if (makeInlineObservations)
4435                 {
4436                     if ((OPCODE)getU1LittleEndian(codeAddr + sz) == CEE_RET)
4437                     {
4438                         compInlineResult->Note(InlineObservation::CALLEE_LOOKS_LIKE_WRAPPER);
4439                     }
4440                 }
4441             }
4442             break;
4443
4444             case CEE_LEAVE:
4445             case CEE_LEAVE_S:
4446             case CEE_BR:
4447             case CEE_BR_S:
4448             case CEE_BRFALSE:
4449             case CEE_BRFALSE_S:
4450             case CEE_BRTRUE:
4451             case CEE_BRTRUE_S:
4452             case CEE_BEQ:
4453             case CEE_BEQ_S:
4454             case CEE_BGE:
4455             case CEE_BGE_S:
4456             case CEE_BGE_UN:
4457             case CEE_BGE_UN_S:
4458             case CEE_BGT:
4459             case CEE_BGT_S:
4460             case CEE_BGT_UN:
4461             case CEE_BGT_UN_S:
4462             case CEE_BLE:
4463             case CEE_BLE_S:
4464             case CEE_BLE_UN:
4465             case CEE_BLE_UN_S:
4466             case CEE_BLT:
4467             case CEE_BLT_S:
4468             case CEE_BLT_UN:
4469             case CEE_BLT_UN_S:
4470             case CEE_BNE_UN:
4471             case CEE_BNE_UN_S:
4472             {
4473                 seenJump = true;
4474
4475                 if (codeAddr > codeEndp - sz)
4476                 {
4477                     goto TOO_FAR;
4478                 }
4479
4480                 // Compute jump target address
4481                 signed jmpDist = (sz == 1) ? getI1LittleEndian(codeAddr) : getI4LittleEndian(codeAddr);
4482
4483                 if (compIsForInlining() && jmpDist == 0 &&
4484                     (opcode == CEE_LEAVE || opcode == CEE_LEAVE_S || opcode == CEE_BR || opcode == CEE_BR_S))
4485                 {
4486                     break; /* NOP */
4487                 }
4488
4489                 unsigned jmpAddr = (IL_OFFSET)(codeAddr - codeBegp) + sz + jmpDist;
4490
4491                 // Make sure target is reasonable
4492                 if (jmpAddr >= codeSize)
4493                 {
4494                     BADCODE3("code jumps to outer space", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4495                 }
4496
4497                 // Mark the jump target
4498                 fgMarkJumpTarget(jumpTarget, jmpAddr);
4499
4500                 // See if jump might be sensitive to inlining
4501                 if (makeInlineObservations && (opcode != CEE_BR_S) && (opcode != CEE_BR))
4502                 {
4503                     fgObserveInlineConstants(opcode, pushedStack, isInlining);
4504                 }
4505             }
4506             break;
4507
4508             case CEE_SWITCH:
4509             {
4510                 seenJump = true;
4511
4512                 if (makeInlineObservations)
4513                 {
4514                     compInlineResult->Note(InlineObservation::CALLEE_HAS_SWITCH);
4515
4516                     // Fail fast, if we're inlining and can't handle this.
4517                     if (isInlining && compInlineResult->IsFailure())
4518                     {
4519                         return;
4520                     }
4521                 }
4522
4523                 // Make sure we don't go past the end reading the number of cases
4524                 if (codeAddr > codeEndp - sizeof(DWORD))
4525                 {
4526                     goto TOO_FAR;
4527                 }
4528
4529                 // Read the number of cases
4530                 unsigned jmpCnt = getU4LittleEndian(codeAddr);
4531                 codeAddr += sizeof(DWORD);
4532
4533                 if (jmpCnt > codeSize / sizeof(DWORD))
4534                 {
4535                     goto TOO_FAR;
4536                 }
4537
4538                 // Find the end of the switch table
4539                 unsigned jmpBase = (unsigned)((codeAddr - codeBegp) + jmpCnt * sizeof(DWORD));
4540
4541                 // Make sure there is more code after the switch
4542                 if (jmpBase >= codeSize)
4543                 {
4544                     goto TOO_FAR;
4545                 }
4546
4547                 // jmpBase is also the target of the default case, so mark it
4548                 fgMarkJumpTarget(jumpTarget, jmpBase);
4549
4550                 // Process table entries
4551                 while (jmpCnt > 0)
4552                 {
4553                     unsigned jmpAddr = jmpBase + getI4LittleEndian(codeAddr);
4554                     codeAddr += 4;
4555
4556                     if (jmpAddr >= codeSize)
4557                     {
4558                         BADCODE3("jump target out of range", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4559                     }
4560
4561                     fgMarkJumpTarget(jumpTarget, jmpAddr);
4562                     jmpCnt--;
4563                 }
4564
4565                 // We've advanced past all the bytes in this instruction
4566                 sz = 0;
4567             }
4568             break;
4569
4570             case CEE_UNALIGNED:
4571             case CEE_CONSTRAINED:
4572             case CEE_READONLY:
4573             case CEE_VOLATILE:
4574             case CEE_TAILCALL:
4575             {
4576                 if (codeAddr >= codeEndp)
4577                 {
4578                     goto TOO_FAR;
4579                 }
4580             }
4581             break;
4582
4583             case CEE_STARG:
4584             case CEE_STARG_S:
4585             {
4586                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4587
4588                 if (codeAddr > codeEndp - sz)
4589                 {
4590                     goto TOO_FAR;
4591                 }
4592
4593                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4594
4595                 if (isInlining)
4596                 {
4597                     if (varNum < impInlineInfo->argCnt)
4598                     {
4599                         impInlineInfo->inlArgInfo[varNum].argHasStargOp = true;
4600                     }
4601                 }
4602                 else
4603                 {
4604                     // account for possible hidden param
4605                     varNum = compMapILargNum(varNum);
4606
4607                     // This check is only intended to prevent an AV.  Bad varNum values will later
4608                     // be handled properly by the verifier.
4609                     if (varNum < lvaTableCnt)
4610                     {
4611                         // In non-inline cases, note written-to arguments.
4612                         lvaTable[varNum].lvHasILStoreOp = 1;
4613                     }
4614                 }
4615             }
4616             break;
4617
4618             case CEE_STLOC_0:
4619             case CEE_STLOC_1:
4620             case CEE_STLOC_2:
4621             case CEE_STLOC_3:
4622                 varNum = (opcode - CEE_STLOC_0);
4623                 goto STLOC;
4624
4625             case CEE_STLOC:
4626             case CEE_STLOC_S:
4627             {
4628                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4629
4630                 if (codeAddr > codeEndp - sz)
4631                 {
4632                     goto TOO_FAR;
4633                 }
4634
4635                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4636
4637             STLOC:
4638                 if (isInlining)
4639                 {
4640                     InlLclVarInfo& lclInfo = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt];
4641
4642                     if (lclInfo.lclHasStlocOp)
4643                     {
4644                         lclInfo.lclHasMultipleStlocOp = 1;
4645                     }
4646                     else
4647                     {
4648                         lclInfo.lclHasStlocOp = 1;
4649                     }
4650                 }
4651                 else
4652                 {
4653                     varNum += info.compArgsCount;
4654
4655                     // This check is only intended to prevent an AV.  Bad varNum values will later
4656                     // be handled properly by the verifier.
4657                     if (varNum < lvaTableCnt)
4658                     {
4659                         // In non-inline cases, note written-to locals.
4660                         if (lvaTable[varNum].lvHasILStoreOp)
4661                         {
4662                             lvaTable[varNum].lvHasMultipleILStoreOp = 1;
4663                         }
4664                         else
4665                         {
4666                             lvaTable[varNum].lvHasILStoreOp = 1;
4667                         }
4668                     }
4669                 }
4670             }
4671             break;
4672
4673             case CEE_LDARGA:
4674             case CEE_LDARGA_S:
4675             case CEE_LDLOCA:
4676             case CEE_LDLOCA_S:
4677             {
4678                 // Handle address-taken args or locals
4679                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4680
4681                 if (codeAddr > codeEndp - sz)
4682                 {
4683                     goto TOO_FAR;
4684                 }
4685
4686                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4687
4688                 if (isInlining)
4689                 {
4690                     if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
4691                     {
4692                         varType = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclTypeInfo;
4693                         ti      = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclVerTypeInfo;
4694
4695                         impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclHasLdlocaOp = true;
4696                     }
4697                     else
4698                     {
4699                         noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
4700
4701                         varType = impInlineInfo->lclVarInfo[varNum].lclTypeInfo;
4702                         ti      = impInlineInfo->lclVarInfo[varNum].lclVerTypeInfo;
4703
4704                         impInlineInfo->inlArgInfo[varNum].argHasLdargaOp = true;
4705
4706                         pushedStack.PushArgument(varNum);
4707                     }
4708                 }
4709                 else
4710                 {
4711                     if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
4712                     {
4713                         if (varNum >= info.compMethodInfo->locals.numArgs)
4714                         {
4715                             BADCODE("bad local number");
4716                         }
4717
4718                         varNum += info.compArgsCount;
4719                     }
4720                     else
4721                     {
4722                         noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
4723
4724                         if (varNum >= info.compILargsCount)
4725                         {
4726                             BADCODE("bad argument number");
4727                         }
4728
4729                         varNum = compMapILargNum(varNum); // account for possible hidden param
4730                     }
4731
4732                     varType = (var_types)lvaTable[varNum].lvType;
4733                     ti      = lvaTable[varNum].lvVerTypeInfo;
4734
4735                     // Determine if the next instruction will consume
4736                     // the address. If so we won't mark this var as
4737                     // address taken.
4738                     //
4739                     // We will put structs on the stack and changing
4740                     // the addrTaken of a local requires an extra pass
4741                     // in the morpher so we won't apply this
4742                     // optimization to structs.
4743                     //
4744                     // Debug code spills for every IL instruction, and
4745                     // therefore it will split statements, so we will
4746                     // need the address.  Note that this optimization
4747                     // is based in that we know what trees we will
4748                     // generate for this ldfld, and we require that we
4749                     // won't need the address of this local at all
4750                     noway_assert(varNum < lvaTableCnt);
4751
4752                     const bool notStruct    = !varTypeIsStruct(&lvaTable[varNum]);
4753                     const bool notLastInstr = (codeAddr < codeEndp - sz);
4754                     const bool notDebugCode = !opts.compDbgCode;
4755
4756                     if (notStruct && notLastInstr && notDebugCode &&
4757                         impILConsumesAddr(codeAddr + sz, impTokenLookupContextHandle, info.compScopeHnd))
4758                     {
4759                         // We can skip the addrtaken, as next IL instruction consumes
4760                         // the address.
4761                     }
4762                     else
4763                     {
4764                         lvaTable[varNum].lvHasLdAddrOp = 1;
4765                         if (!info.compIsStatic && (varNum == 0))
4766                         {
4767                             // Addr taken on "this" pointer is significant,
4768                             // go ahead to mark it as permanently addr-exposed here.
4769                             lvaSetVarAddrExposed(0);
4770                             // This may be conservative, but probably not very.
4771                         }
4772                     }
4773                 } // isInlining
4774
4775                 typeIsNormed = ti.IsValueClass() && !varTypeIsStruct(varType);
4776             }
4777             break;
4778
4779             case CEE_CALLI:
4780
4781                 // CEE_CALLI should not be inlined if the call indirect target has a calling convention other than
4782                 // CORINFO_CALLCONV_DEFAULT. In the case where we have a no-marshal CALLI P/Invoke we end up calling
4783                 // the IL stub. We don't NGEN these stubs, so we'll have to JIT an IL stub for a trivial func.
4784                 // It's almost certainly a better choice to leave out the inline candidate so we can generate an inlined
4785                 // call frame.
4786
4787                 // Consider skipping this bail-out for force inlines.
4788                 if (makeInlineObservations)
4789                 {
4790                     if (codeAddr > codeEndp - sizeof(DWORD))
4791                     {
4792                         goto TOO_FAR;
4793                     }
4794
4795                     CORINFO_SIG_INFO calliSig;
4796                     eeGetSig(getU4LittleEndian(codeAddr), info.compScopeHnd, impTokenLookupContextHandle, &calliSig);
4797
4798                     if (calliSig.getCallConv() != CORINFO_CALLCONV_DEFAULT)
4799                     {
4800                         compInlineResult->Note(InlineObservation::CALLEE_UNSUPPORTED_OPCODE);
4801
4802                         // Fail fast if we're inlining
4803                         if (isInlining)
4804                         {
4805                             assert(compInlineResult->IsFailure());
4806                             return;
4807                         }
4808                     }
4809                 }
4810                 break;
4811
4812             case CEE_JMP:
4813                 retBlocks++;
4814
4815 #if !defined(_TARGET_X86_) && !defined(_TARGET_ARM_)
4816                 if (!isInlining)
4817                 {
4818                     // We transform this into a set of ldarg's + tail call and
4819                     // thus may push more onto the stack than originally thought.
4820                     // This doesn't interfere with verification because CEE_JMP
4821                     // is never verifiable, and there's nothing unsafe you can
4822                     // do with a an IL stack overflow if the JIT is expecting it.
4823                     info.compMaxStack = max(info.compMaxStack, info.compILargsCount);
4824                     break;
4825                 }
4826 #endif // !_TARGET_X86_ && !_TARGET_ARM_
4827
4828                 // If we are inlining, we need to fail for a CEE_JMP opcode, just like
4829                 // the list of other opcodes (for all platforms).
4830
4831                 __fallthrough;
4832             case CEE_MKREFANY:
4833             case CEE_RETHROW:
4834                 if (makeInlineObservations)
4835                 {
4836                     // Arguably this should be NoteFatal, but the legacy behavior is
4837                     // to ignore this for the prejit root.
4838                     compInlineResult->Note(InlineObservation::CALLEE_UNSUPPORTED_OPCODE);
4839
4840                     // Fail fast if we're inlining...
4841                     if (isInlining)
4842                     {
4843                         assert(compInlineResult->IsFailure());
4844                         return;
4845                     }
4846                 }
4847                 break;
4848
4849             case CEE_LOCALLOC:
4850
4851                 // We now allow localloc callees to become candidates in some cases.
4852                 if (makeInlineObservations)
4853                 {
4854                     compInlineResult->Note(InlineObservation::CALLEE_HAS_LOCALLOC);
4855                     if (isInlining && compInlineResult->IsFailure())
4856                     {
4857                         return;
4858                     }
4859                 }
4860                 break;
4861
4862             case CEE_LDARG_0:
4863             case CEE_LDARG_1:
4864             case CEE_LDARG_2:
4865             case CEE_LDARG_3:
4866                 if (makeInlineObservations)
4867                 {
4868                     pushedStack.PushArgument(opcode - CEE_LDARG_0);
4869                 }
4870                 break;
4871
4872             case CEE_LDARG_S:
4873             case CEE_LDARG:
4874             {
4875                 if (codeAddr > codeEndp - sz)
4876                 {
4877                     goto TOO_FAR;
4878                 }
4879
4880                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4881
4882                 if (makeInlineObservations)
4883                 {
4884                     pushedStack.PushArgument(varNum);
4885                 }
4886             }
4887             break;
4888
4889             case CEE_LDLEN:
4890                 if (makeInlineObservations)
4891                 {
4892                     pushedStack.PushArrayLen();
4893                 }
4894                 break;
4895
4896             case CEE_CEQ:
4897             case CEE_CGT:
4898             case CEE_CGT_UN:
4899             case CEE_CLT:
4900             case CEE_CLT_UN:
4901                 if (makeInlineObservations)
4902                 {
4903                     fgObserveInlineConstants(opcode, pushedStack, isInlining);
4904                 }
4905                 break;
4906             case CEE_RET:
4907                 retBlocks++;
4908
4909             default:
4910                 break;
4911         }
4912
4913         // Skip any remaining operands this opcode may have
4914         codeAddr += sz;
4915
4916         // Note the opcode we just saw
4917         if (makeInlineObservations)
4918         {
4919             InlineObservation obs =
4920                 typeIsNormed ? InlineObservation::CALLEE_OPCODE_NORMED : InlineObservation::CALLEE_OPCODE;
4921             compInlineResult->NoteInt(obs, opcode);
4922         }
4923     }
4924
4925     if (codeAddr != codeEndp)
4926     {
4927     TOO_FAR:
4928         BADCODE3("Code ends in the middle of an opcode, or there is a branch past the end of the method",
4929                  " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4930     }
4931
4932     if (makeInlineObservations)
4933     {
4934         compInlineResult->Note(InlineObservation::CALLEE_END_OPCODE_SCAN);
4935
4936         // If there are no return blocks we know it does not return, however if there
4937         // return blocks we don't know it returns as it may be counting unreachable code.
4938         // However we will still make the CALLEE_DOES_NOT_RETURN observation.
4939
4940         compInlineResult->NoteBool(InlineObservation::CALLEE_DOES_NOT_RETURN, retBlocks == 0);
4941
4942         if (retBlocks == 0 && isInlining)
4943         {
4944             // Mark the call node as "no return" as it can impact caller's code quality.
4945             impInlineInfo->iciCall->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN;
4946         }
4947
4948         // If the inline is viable and discretionary, do the
4949         // profitability screening.
4950         if (compInlineResult->IsDiscretionaryCandidate())
4951         {
4952             // Make some callsite specific observations that will feed
4953             // into the profitability model.
4954             impMakeDiscretionaryInlineObservations(impInlineInfo, compInlineResult);
4955
4956             // None of those observations should have changed the
4957             // inline's viability.
4958             assert(compInlineResult->IsCandidate());
4959
4960             if (isInlining)
4961             {
4962                 // Assess profitability...
4963                 CORINFO_METHOD_INFO* methodInfo = &impInlineInfo->inlineCandidateInfo->methInfo;
4964                 compInlineResult->DetermineProfitability(methodInfo);
4965
4966                 if (compInlineResult->IsFailure())
4967                 {
4968                     impInlineRoot()->m_inlineStrategy->NoteUnprofitable();
4969                     JITDUMP("\n\nInline expansion aborted, inline not profitable\n");
4970                     return;
4971                 }
4972                 else
4973                 {
4974                     // The inline is still viable.
4975                     assert(compInlineResult->IsCandidate());
4976                 }
4977             }
4978             else
4979             {
4980                 // Prejit root case. Profitability assessment for this
4981                 // is done over in compCompileHelper.
4982             }
4983         }
4984     }
4985
4986     // None of the local vars in the inlinee should have address taken or been written to.
4987     // Therefore we should NOT need to enter this "if" statement.
4988     if (!isInlining && !info.compIsStatic)
4989     {
4990         fgAdjustForAddressExposedOrWrittenThis();
4991     }
4992 }
4993
4994 #ifdef _PREFAST_
4995 #pragma warning(pop)
4996 #endif
4997
4998 //------------------------------------------------------------------------
4999 // fgAdjustForAddressExposedOrWrittenThis: update var table for cases
5000 //   where the this pointer value can change.
5001 //
5002 // Notes:
5003 //    Modifies lvaArg0Var to refer to a temp if the value of 'this' can
5004 //    change. The original this (info.compThisArg) then remains
5005 //    unmodified in the method.  fgAddInternal is reponsible for
5006 //    adding the code to copy the initial this into the temp.
5007
5008 void Compiler::fgAdjustForAddressExposedOrWrittenThis()
5009 {
5010     // Optionally enable adjustment during stress.
5011     if (!tiVerificationNeeded && compStressCompile(STRESS_GENERIC_VARN, 15))
5012     {
5013         lvaTable[info.compThisArg].lvHasILStoreOp = true;
5014     }
5015
5016     // If this is exposed or written to, create a temp for the modifiable this
5017     if (lvaTable[info.compThisArg].lvAddrExposed || lvaTable[info.compThisArg].lvHasILStoreOp)
5018     {
5019         // If there is a "ldarga 0" or "starg 0", grab and use the temp.
5020         lvaArg0Var = lvaGrabTemp(false DEBUGARG("Address-exposed, or written this pointer"));
5021         noway_assert(lvaArg0Var > (unsigned)info.compThisArg);
5022         lvaTable[lvaArg0Var].lvType            = lvaTable[info.compThisArg].TypeGet();
5023         lvaTable[lvaArg0Var].lvAddrExposed     = lvaTable[info.compThisArg].lvAddrExposed;
5024         lvaTable[lvaArg0Var].lvDoNotEnregister = lvaTable[info.compThisArg].lvDoNotEnregister;
5025 #ifdef DEBUG
5026         lvaTable[lvaArg0Var].lvVMNeedsStackAddr = lvaTable[info.compThisArg].lvVMNeedsStackAddr;
5027         lvaTable[lvaArg0Var].lvLiveInOutOfHndlr = lvaTable[info.compThisArg].lvLiveInOutOfHndlr;
5028         lvaTable[lvaArg0Var].lvLclFieldExpr     = lvaTable[info.compThisArg].lvLclFieldExpr;
5029         lvaTable[lvaArg0Var].lvLiveAcrossUCall  = lvaTable[info.compThisArg].lvLiveAcrossUCall;
5030 #endif
5031         lvaTable[lvaArg0Var].lvHasILStoreOp = lvaTable[info.compThisArg].lvHasILStoreOp;
5032         lvaTable[lvaArg0Var].lvVerTypeInfo  = lvaTable[info.compThisArg].lvVerTypeInfo;
5033
5034         // Clear the TI_FLAG_THIS_PTR in the original 'this' pointer.
5035         noway_assert(lvaTable[lvaArg0Var].lvVerTypeInfo.IsThisPtr());
5036         lvaTable[info.compThisArg].lvVerTypeInfo.ClearThisPtr();
5037         lvaTable[info.compThisArg].lvAddrExposed  = false;
5038         lvaTable[info.compThisArg].lvHasILStoreOp = false;
5039     }
5040 }
5041
5042 //------------------------------------------------------------------------
5043 // fgObserveInlineConstants: look for operations that might get optimized
5044 //   if this method were to be inlined, and report these to the inliner.
5045 //
5046 // Arguments:
5047 //    opcode     -- MSIL opcode under consideration
5048 //    stack      -- abstract stack model at this point in the IL
5049 //    isInlining -- true if we're inlining (vs compiling a prejit root)
5050 //
5051 // Notes:
5052 //    Currently only invoked on compare and branch opcodes.
5053 //
5054 //    If we're inlining we also look at the argument values supplied by
5055 //    the caller at this call site.
5056 //
5057 //    The crude stack model may overestimate stack depth.
5058
5059 void Compiler::fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, bool isInlining)
5060 {
5061     // We should be able to record inline observations.
5062     assert(compInlineResult != nullptr);
5063
5064     // The stack only has to be 1 deep for BRTRUE/FALSE
5065     bool lookForBranchCases = stack.IsStackAtLeastOneDeep();
5066
5067     if (lookForBranchCases)
5068     {
5069         if (opcode == CEE_BRFALSE || opcode == CEE_BRFALSE_S || opcode == CEE_BRTRUE || opcode == CEE_BRTRUE_S)
5070         {
5071             unsigned slot0 = stack.GetSlot0();
5072             if (FgStack::IsArgument(slot0))
5073             {
5074                 compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST);
5075
5076                 if (isInlining)
5077                 {
5078                     // Check for the double whammy of an incoming constant argument
5079                     // feeding a constant test.
5080                     unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
5081                     if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5082                     {
5083                         compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5084                     }
5085                 }
5086             }
5087
5088             return;
5089         }
5090     }
5091
5092     // Remaining cases require at least two things on the stack.
5093     if (!stack.IsStackTwoDeep())
5094     {
5095         return;
5096     }
5097
5098     unsigned slot0 = stack.GetSlot0();
5099     unsigned slot1 = stack.GetSlot1();
5100
5101     // Arg feeds constant test
5102     if ((FgStack::IsConstant(slot0) && FgStack::IsArgument(slot1)) ||
5103         (FgStack::IsConstant(slot1) && FgStack::IsArgument(slot0)))
5104     {
5105         compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST);
5106     }
5107
5108     // Arg feeds range check
5109     if ((FgStack::IsArrayLen(slot0) && FgStack::IsArgument(slot1)) ||
5110         (FgStack::IsArrayLen(slot1) && FgStack::IsArgument(slot0)))
5111     {
5112         compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_RANGE_CHECK);
5113     }
5114
5115     // Check for an incoming arg that's a constant
5116     if (isInlining)
5117     {
5118         if (FgStack::IsArgument(slot0))
5119         {
5120             compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_TEST);
5121
5122             unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
5123             if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5124             {
5125                 compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5126             }
5127         }
5128
5129         if (FgStack::IsArgument(slot1))
5130         {
5131             compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_TEST);
5132
5133             unsigned varNum = FgStack::SlotTypeToArgNum(slot1);
5134             if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5135             {
5136                 compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5137             }
5138         }
5139     }
5140 }
5141
5142 /*****************************************************************************
5143  *
5144  *  Finally link up the bbJumpDest of the blocks together
5145  */
5146
5147 void Compiler::fgMarkBackwardJump(BasicBlock* startBlock, BasicBlock* endBlock)
5148 {
5149     noway_assert(startBlock->bbNum <= endBlock->bbNum);
5150
5151     for (BasicBlock* block = startBlock; block != endBlock->bbNext; block = block->bbNext)
5152     {
5153         if ((block->bbFlags & BBF_BACKWARD_JUMP) == 0)
5154         {
5155             block->bbFlags |= BBF_BACKWARD_JUMP;
5156         }
5157     }
5158 }
5159
5160 /*****************************************************************************
5161  *
5162  *  Finally link up the bbJumpDest of the blocks together
5163  */
5164
5165 void Compiler::fgLinkBasicBlocks()
5166 {
5167     /* Create the basic block lookup tables */
5168
5169     fgInitBBLookup();
5170
5171     /* First block is always reachable */
5172
5173     fgFirstBB->bbRefs = 1;
5174
5175     /* Walk all the basic blocks, filling in the target addresses */
5176
5177     for (BasicBlock* curBBdesc = fgFirstBB; curBBdesc; curBBdesc = curBBdesc->bbNext)
5178     {
5179         switch (curBBdesc->bbJumpKind)
5180         {
5181             case BBJ_COND:
5182             case BBJ_ALWAYS:
5183             case BBJ_LEAVE:
5184                 curBBdesc->bbJumpDest = fgLookupBB(curBBdesc->bbJumpOffs);
5185                 curBBdesc->bbJumpDest->bbRefs++;
5186                 if (curBBdesc->bbJumpDest->bbNum <= curBBdesc->bbNum)
5187                 {
5188                     fgMarkBackwardJump(curBBdesc->bbJumpDest, curBBdesc);
5189                 }
5190
5191                 /* Is the next block reachable? */
5192
5193                 if (curBBdesc->bbJumpKind == BBJ_ALWAYS || curBBdesc->bbJumpKind == BBJ_LEAVE)
5194                 {
5195                     break;
5196                 }
5197
5198                 if (!curBBdesc->bbNext)
5199                 {
5200                     BADCODE("Fall thru the end of a method");
5201                 }
5202
5203             // Fall through, the next block is also reachable
5204
5205             case BBJ_NONE:
5206                 curBBdesc->bbNext->bbRefs++;
5207                 break;
5208
5209             case BBJ_EHFINALLYRET:
5210             case BBJ_EHFILTERRET:
5211             case BBJ_THROW:
5212             case BBJ_RETURN:
5213                 break;
5214
5215             case BBJ_SWITCH:
5216
5217                 unsigned jumpCnt;
5218                 jumpCnt = curBBdesc->bbJumpSwt->bbsCount;
5219                 BasicBlock** jumpPtr;
5220                 jumpPtr = curBBdesc->bbJumpSwt->bbsDstTab;
5221
5222                 do
5223                 {
5224                     *jumpPtr = fgLookupBB((unsigned)*(size_t*)jumpPtr);
5225                     (*jumpPtr)->bbRefs++;
5226                     if ((*jumpPtr)->bbNum <= curBBdesc->bbNum)
5227                     {
5228                         fgMarkBackwardJump(*jumpPtr, curBBdesc);
5229                     }
5230                 } while (++jumpPtr, --jumpCnt);
5231
5232                 /* Default case of CEE_SWITCH (next block), is at end of jumpTab[] */
5233
5234                 noway_assert(*(jumpPtr - 1) == curBBdesc->bbNext);
5235                 break;
5236
5237             case BBJ_CALLFINALLY: // BBJ_CALLFINALLY and BBJ_EHCATCHRET don't appear until later
5238             case BBJ_EHCATCHRET:
5239             default:
5240                 noway_assert(!"Unexpected bbJumpKind");
5241                 break;
5242         }
5243     }
5244 }
5245
5246 /*****************************************************************************
5247  *
5248  *  Walk the instrs to create the basic blocks. Returns the number of BBJ_RETURN in method
5249  */
5250
5251 unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget)
5252 {
5253     unsigned    retBlocks;
5254     const BYTE* codeBegp = codeAddr;
5255     const BYTE* codeEndp = codeAddr + codeSize;
5256     bool        tailCall = false;
5257     unsigned    curBBoffs;
5258     BasicBlock* curBBdesc;
5259
5260     retBlocks = 0;
5261     /* Clear the beginning offset for the first BB */
5262
5263     curBBoffs = 0;
5264
5265     if (opts.compDbgCode && (info.compVarScopesCount > 0))
5266     {
5267         compResetScopeLists();
5268
5269         // Ignore scopes beginning at offset 0
5270         while (compGetNextEnterScope(0))
5271         { /* do nothing */
5272         }
5273         while (compGetNextExitScope(0))
5274         { /* do nothing */
5275         }
5276     }
5277
5278     BBjumpKinds jmpKind;
5279
5280     do
5281     {
5282         OPCODE     opcode;
5283         unsigned   sz;
5284         unsigned   jmpAddr = DUMMY_INIT(BAD_IL_OFFSET);
5285         unsigned   bbFlags = 0;
5286         BBswtDesc* swtDsc  = nullptr;
5287         unsigned   nxtBBoffs;
5288
5289         opcode = (OPCODE)getU1LittleEndian(codeAddr);
5290         codeAddr += sizeof(__int8);
5291         jmpKind = BBJ_NONE;
5292
5293     DECODE_OPCODE:
5294
5295         /* Get the size of additional parameters */
5296
5297         noway_assert((unsigned)opcode < CEE_COUNT);
5298
5299         sz = opcodeSizes[opcode];
5300
5301         switch (opcode)
5302         {
5303             signed jmpDist;
5304
5305             case CEE_PREFIX1:
5306                 if (jumpTarget[codeAddr - codeBegp] != JT_NONE)
5307                 {
5308                     BADCODE3("jump target between prefix 0xFE and opcode", " at offset %04X",
5309                              (IL_OFFSET)(codeAddr - codeBegp));
5310                 }
5311
5312                 opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr));
5313                 codeAddr += sizeof(__int8);
5314                 goto DECODE_OPCODE;
5315
5316             /* Check to see if we have a jump/return opcode */
5317
5318             case CEE_BRFALSE:
5319             case CEE_BRFALSE_S:
5320             case CEE_BRTRUE:
5321             case CEE_BRTRUE_S:
5322
5323             case CEE_BEQ:
5324             case CEE_BEQ_S:
5325             case CEE_BGE:
5326             case CEE_BGE_S:
5327             case CEE_BGE_UN:
5328             case CEE_BGE_UN_S:
5329             case CEE_BGT:
5330             case CEE_BGT_S:
5331             case CEE_BGT_UN:
5332             case CEE_BGT_UN_S:
5333             case CEE_BLE:
5334             case CEE_BLE_S:
5335             case CEE_BLE_UN:
5336             case CEE_BLE_UN_S:
5337             case CEE_BLT:
5338             case CEE_BLT_S:
5339             case CEE_BLT_UN:
5340             case CEE_BLT_UN_S:
5341             case CEE_BNE_UN:
5342             case CEE_BNE_UN_S:
5343
5344                 jmpKind = BBJ_COND;
5345                 goto JMP;
5346
5347             case CEE_LEAVE:
5348             case CEE_LEAVE_S:
5349
5350                 // We need to check if we are jumping out of a finally-protected try.
5351                 jmpKind = BBJ_LEAVE;
5352                 goto JMP;
5353
5354             case CEE_BR:
5355             case CEE_BR_S:
5356                 jmpKind = BBJ_ALWAYS;
5357                 goto JMP;
5358
5359             JMP:
5360
5361                 /* Compute the target address of the jump */
5362
5363                 jmpDist = (sz == 1) ? getI1LittleEndian(codeAddr) : getI4LittleEndian(codeAddr);
5364
5365                 if (compIsForInlining() && jmpDist == 0 && (opcode == CEE_BR || opcode == CEE_BR_S))
5366                 {
5367                     continue; /* NOP */
5368                 }
5369
5370                 jmpAddr = (IL_OFFSET)(codeAddr - codeBegp) + sz + jmpDist;
5371                 break;
5372
5373             case CEE_SWITCH:
5374             {
5375                 unsigned jmpBase;
5376                 unsigned jmpCnt; // # of switch cases (excluding defualt)
5377
5378                 BasicBlock** jmpTab;
5379                 BasicBlock** jmpPtr;
5380
5381                 /* Allocate the switch descriptor */
5382
5383                 swtDsc = new (this, CMK_BasicBlock) BBswtDesc;
5384
5385                 /* Read the number of entries in the table */
5386
5387                 jmpCnt = getU4LittleEndian(codeAddr);
5388                 codeAddr += 4;
5389
5390                 /* Compute  the base offset for the opcode */
5391
5392                 jmpBase = (IL_OFFSET)((codeAddr - codeBegp) + jmpCnt * sizeof(DWORD));
5393
5394                 /* Allocate the jump table */
5395
5396                 jmpPtr = jmpTab = new (this, CMK_BasicBlock) BasicBlock*[jmpCnt + 1];
5397
5398                 /* Fill in the jump table */
5399
5400                 for (unsigned count = jmpCnt; count; count--)
5401                 {
5402                     jmpDist = getI4LittleEndian(codeAddr);
5403                     codeAddr += 4;
5404
5405                     // store the offset in the pointer.  We change these in fgLinkBasicBlocks().
5406                     *jmpPtr++ = (BasicBlock*)(size_t)(jmpBase + jmpDist);
5407                 }
5408
5409                 /* Append the default label to the target table */
5410
5411                 *jmpPtr++ = (BasicBlock*)(size_t)jmpBase;
5412
5413                 /* Make sure we found the right number of labels */
5414
5415                 noway_assert(jmpPtr == jmpTab + jmpCnt + 1);
5416
5417                 /* Compute the size of the switch opcode operands */
5418
5419                 sz = sizeof(DWORD) + jmpCnt * sizeof(DWORD);
5420
5421                 /* Fill in the remaining fields of the switch descriptor */
5422
5423                 swtDsc->bbsCount  = jmpCnt + 1;
5424                 swtDsc->bbsDstTab = jmpTab;
5425
5426                 /* This is definitely a jump */
5427
5428                 jmpKind     = BBJ_SWITCH;
5429                 fgHasSwitch = true;
5430
5431 #ifndef LEGACY_BACKEND
5432                 if (opts.compProcedureSplitting)
5433                 {
5434                     // TODO-CQ: We might need to create a switch table; we won't know for sure until much later.
5435                     // However, switch tables don't work with hot/cold splitting, currently. The switch table data needs
5436                     // a relocation such that if the base (the first block after the prolog) and target of the switch
5437                     // branch are put in different sections, the difference stored in the table is updated. However, our
5438                     // relocation implementation doesn't support three different pointers (relocation address, base, and
5439                     // target). So, we need to change our switch table implementation to be more like
5440                     // JIT64: put the table in the code section, in the same hot/cold section as the switch jump itself
5441                     // (maybe immediately after the switch jump), and make the "base" address be also in that section,
5442                     // probably the address after the switch jump.
5443                     opts.compProcedureSplitting = false;
5444                     JITDUMP("Turning off procedure splitting for this method, as it might need switch tables; "
5445                             "implementation limitation.\n");
5446                 }
5447 #endif // !LEGACY_BACKEND
5448             }
5449                 goto GOT_ENDP;
5450
5451             case CEE_ENDFILTER:
5452                 bbFlags |= BBF_DONT_REMOVE;
5453                 jmpKind = BBJ_EHFILTERRET;
5454                 break;
5455
5456             case CEE_ENDFINALLY:
5457                 jmpKind = BBJ_EHFINALLYRET;
5458                 break;
5459
5460             case CEE_TAILCALL:
5461                 if (compIsForInlining())
5462                 {
5463                     // TODO-CQ: We can inline some callees with explicit tail calls if we can guarantee that the calls
5464                     // can be dispatched as tail calls from the caller.
5465                     compInlineResult->NoteFatal(InlineObservation::CALLEE_EXPLICIT_TAIL_PREFIX);
5466                     retBlocks++;
5467                     return retBlocks;
5468                 }
5469
5470                 __fallthrough;
5471
5472             case CEE_READONLY:
5473             case CEE_CONSTRAINED:
5474             case CEE_VOLATILE:
5475             case CEE_UNALIGNED:
5476                 // fgFindJumpTargets should have ruled out this possibility
5477                 //   (i.e. a prefix opcodes as last intruction in a block)
5478                 noway_assert(codeAddr < codeEndp);
5479
5480                 if (jumpTarget[codeAddr - codeBegp] != JT_NONE)
5481                 {
5482                     BADCODE3("jump target between prefix and an opcode", " at offset %04X",
5483                              (IL_OFFSET)(codeAddr - codeBegp));
5484                 }
5485                 break;
5486
5487             case CEE_CALL:
5488             case CEE_CALLVIRT:
5489             case CEE_CALLI:
5490             {
5491                 if (compIsForInlining() ||               // Ignore tail call in the inlinee. Period.
5492                     (!tailCall && !compTailCallStress()) // A new BB with BBJ_RETURN would have been created
5493
5494                     // after a tailcall statement.
5495                     // We need to keep this invariant if we want to stress the tailcall.
5496                     // That way, the potential (tail)call statement is always the last
5497                     // statement in the block.
5498                     // Otherwise, we will assert at the following line in fgMorphCall()
5499                     //     noway_assert(fgMorphStmt->gtNext == NULL);
5500                     )
5501                 {
5502                     // Neither .tailcall prefix, no tailcall stress. So move on.
5503                     break;
5504                 }
5505
5506                 // Make sure the code sequence is legal for the tail call.
5507                 // If so, mark this BB as having a BBJ_RETURN.
5508
5509                 if (codeAddr >= codeEndp - sz)
5510                 {
5511                     BADCODE3("No code found after the call instruction", " at offset %04X",
5512                              (IL_OFFSET)(codeAddr - codeBegp));
5513                 }
5514
5515                 if (tailCall)
5516                 {
5517                     bool isCallPopAndRet = false;
5518
5519                     // impIsTailCallILPattern uses isRecursive flag to determine whether ret in a fallthrough block is
5520                     // allowed. We don't know at this point whether the call is recursive so we conservatively pass
5521                     // false. This will only affect explicit tail calls when IL verification is not needed for the
5522                     // method.
5523                     bool isRecursive = false;
5524                     if (!impIsTailCallILPattern(tailCall, opcode, codeAddr + sz, codeEndp, isRecursive,
5525                                                 &isCallPopAndRet))
5526                     {
5527 #if !defined(FEATURE_CORECLR) && defined(_TARGET_AMD64_)
5528                         BADCODE3("tail call not followed by ret or pop+ret", " at offset %04X",
5529                                  (IL_OFFSET)(codeAddr - codeBegp));
5530 #else
5531                         BADCODE3("tail call not followed by ret", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5532 #endif // !FEATURE_CORECLR && _TARGET_AMD64_
5533                     }
5534
5535 #if !defined(FEATURE_CORECLR) && defined(_TARGET_AMD64_)
5536                     if (isCallPopAndRet)
5537                     {
5538                         // By breaking here, we let pop and ret opcodes to be
5539                         // imported after tail call.  If tail prefix is honored,
5540                         // stmts corresponding to pop and ret will be removed
5541                         // in fgMorphCall().
5542                         break;
5543                     }
5544 #endif // !FEATURE_CORECLR && _TARGET_AMD64_
5545                 }
5546                 else
5547                 {
5548                     OPCODE nextOpcode = (OPCODE)getU1LittleEndian(codeAddr + sz);
5549
5550                     if (nextOpcode != CEE_RET)
5551                     {
5552                         noway_assert(compTailCallStress());
5553                         // Next OPCODE is not a CEE_RET, bail the attempt to stress the tailcall.
5554                         // (I.e. We will not make a new BB after the "call" statement.)
5555                         break;
5556                     }
5557                 }
5558             }
5559
5560             /* For tail call, we just call CORINFO_HELP_TAILCALL, and it jumps to the
5561                target. So we don't need an epilog - just like CORINFO_HELP_THROW.
5562                Make the block BBJ_RETURN, but we will change it to BBJ_THROW
5563                if the tailness of the call is satisfied.
5564                NOTE : The next instruction is guaranteed to be a CEE_RET
5565                and it will create another BasicBlock. But there may be an
5566                jump directly to that CEE_RET. If we want to avoid creating
5567                an unnecessary block, we need to check if the CEE_RETURN is
5568                the target of a jump.
5569              */
5570
5571             // fall-through
5572
5573             case CEE_JMP:
5574             /* These are equivalent to a return from the current method
5575                But instead of directly returning to the caller we jump and
5576                execute something else in between */
5577             case CEE_RET:
5578                 retBlocks++;
5579                 jmpKind = BBJ_RETURN;
5580                 break;
5581
5582             case CEE_THROW:
5583             case CEE_RETHROW:
5584                 jmpKind = BBJ_THROW;
5585                 break;
5586
5587 #ifdef DEBUG
5588 // make certain we did not forget any flow of control instructions
5589 // by checking the 'ctrl' field in opcode.def. First filter out all
5590 // non-ctrl instructions
5591 #define BREAK(name)                                                                                                    \
5592     case name:                                                                                                         \
5593         break;
5594 #define NEXT(name)                                                                                                     \
5595     case name:                                                                                                         \
5596         break;
5597 #define CALL(name)
5598 #define THROW(name)
5599 #undef RETURN // undef contract RETURN macro
5600 #define RETURN(name)
5601 #define META(name)
5602 #define BRANCH(name)
5603 #define COND_BRANCH(name)
5604 #define PHI(name)
5605
5606 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) ctrl(name)
5607 #include "opcode.def"
5608 #undef OPDEF
5609
5610 #undef PHI
5611 #undef BREAK
5612 #undef CALL
5613 #undef NEXT
5614 #undef THROW
5615 #undef RETURN
5616 #undef META
5617 #undef BRANCH
5618 #undef COND_BRANCH
5619
5620             // These ctrl-flow opcodes don't need any special handling
5621             case CEE_NEWOBJ: // CTRL_CALL
5622                 break;
5623
5624             // what's left are forgotten instructions
5625             default:
5626                 BADCODE("Unrecognized control Opcode");
5627                 break;
5628 #else  // !DEBUG
5629             default:
5630                 break;
5631 #endif // !DEBUG
5632         }
5633
5634         /* Jump over the operand */
5635
5636         codeAddr += sz;
5637
5638     GOT_ENDP:
5639
5640         tailCall = (opcode == CEE_TAILCALL);
5641
5642         /* Make sure a jump target isn't in the middle of our opcode */
5643
5644         if (sz)
5645         {
5646             IL_OFFSET offs = (IL_OFFSET)(codeAddr - codeBegp) - sz; // offset of the operand
5647
5648             for (unsigned i = 0; i < sz; i++, offs++)
5649             {
5650                 if (jumpTarget[offs] != JT_NONE)
5651                 {
5652                     BADCODE3("jump into the middle of an opcode", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5653                 }
5654             }
5655         }
5656
5657         /* Compute the offset of the next opcode */
5658
5659         nxtBBoffs = (IL_OFFSET)(codeAddr - codeBegp);
5660
5661         bool foundScope = false;
5662
5663         if (opts.compDbgCode && (info.compVarScopesCount > 0))
5664         {
5665             while (compGetNextEnterScope(nxtBBoffs))
5666             {
5667                 foundScope = true;
5668             }
5669             while (compGetNextExitScope(nxtBBoffs))
5670             {
5671                 foundScope = true;
5672             }
5673         }
5674
5675         /* Do we have a jump? */
5676
5677         if (jmpKind == BBJ_NONE)
5678         {
5679             /* No jump; make sure we don't fall off the end of the function */
5680
5681             if (codeAddr == codeEndp)
5682             {
5683                 BADCODE3("missing return opcode", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5684             }
5685
5686             /* If a label follows this opcode, we'll have to make a new BB */
5687
5688             bool makeBlock = (jumpTarget[nxtBBoffs] != JT_NONE);
5689
5690             if (!makeBlock && foundScope)
5691             {
5692                 makeBlock = true;
5693 #ifdef DEBUG
5694                 if (verbose)
5695                 {
5696                     printf("Splitting at BBoffs = %04u\n", nxtBBoffs);
5697                 }
5698 #endif // DEBUG
5699             }
5700
5701             if (!makeBlock)
5702             {
5703                 continue;
5704             }
5705         }
5706
5707         /* We need to create a new basic block */
5708
5709         curBBdesc = fgNewBasicBlock(jmpKind);
5710
5711         curBBdesc->bbFlags |= bbFlags;
5712         curBBdesc->bbRefs = 0;
5713
5714         curBBdesc->bbCodeOffs    = curBBoffs;
5715         curBBdesc->bbCodeOffsEnd = nxtBBoffs;
5716
5717         unsigned profileWeight;
5718         if (fgGetProfileWeightForBasicBlock(curBBoffs, &profileWeight))
5719         {
5720             curBBdesc->setBBProfileWeight(profileWeight);
5721             if (profileWeight == 0)
5722             {
5723                 curBBdesc->bbSetRunRarely();
5724             }
5725             else
5726             {
5727                 // Note that bbNewBasicBlock (called from fgNewBasicBlock) may have
5728                 // already marked the block as rarely run.  In that case (and when we know
5729                 // that the block profile weight is non-zero) we want to unmark that.
5730
5731                 curBBdesc->bbFlags &= ~BBF_RUN_RARELY;
5732             }
5733         }
5734
5735         switch (jmpKind)
5736         {
5737             case BBJ_SWITCH:
5738                 curBBdesc->bbJumpSwt = swtDsc;
5739                 break;
5740
5741             case BBJ_COND:
5742             case BBJ_ALWAYS:
5743             case BBJ_LEAVE:
5744                 noway_assert(jmpAddr != DUMMY_INIT(BAD_IL_OFFSET));
5745                 curBBdesc->bbJumpOffs = jmpAddr;
5746                 break;
5747
5748             default:
5749                 break;
5750         }
5751
5752         DBEXEC(verbose, curBBdesc->dspBlockHeader(this, false, false, false));
5753
5754         /* Remember where the next BB will start */
5755
5756         curBBoffs = nxtBBoffs;
5757     } while (codeAddr < codeEndp);
5758
5759     noway_assert(codeAddr == codeEndp);
5760
5761     /* Finally link up the bbJumpDest of the blocks together */
5762
5763     fgLinkBasicBlocks();
5764
5765     return retBlocks;
5766 }
5767
5768 /*****************************************************************************
5769  *
5770  *  Main entry point to discover the basic blocks for the current function.
5771  */
5772
5773 void Compiler::fgFindBasicBlocks()
5774 {
5775 #ifdef DEBUG
5776     if (verbose)
5777     {
5778         printf("*************** In fgFindBasicBlocks() for %s\n", info.compFullName);
5779     }
5780 #endif
5781
5782     /* Allocate the 'jump target' vector
5783      *
5784      *  We need one extra byte as we mark
5785      *  jumpTarget[info.compILCodeSize] with JT_ADDR
5786      *  when we need to add a dummy block
5787      *  to record the end of a try or handler region.
5788      */
5789     BYTE* jumpTarget = new (this, CMK_Unknown) BYTE[info.compILCodeSize + 1];
5790     memset(jumpTarget, JT_NONE, info.compILCodeSize + 1);
5791     noway_assert(JT_NONE == 0);
5792
5793     /* Walk the instrs to find all jump targets */
5794
5795     fgFindJumpTargets(info.compCode, info.compILCodeSize, jumpTarget);
5796     if (compDonotInline())
5797     {
5798         return;
5799     }
5800
5801     unsigned XTnum;
5802
5803     /* Are there any exception handlers? */
5804
5805     if (info.compXcptnsCount > 0)
5806     {
5807         noway_assert(!compIsForInlining());
5808
5809         /* Check and mark all the exception handlers */
5810
5811         for (XTnum = 0; XTnum < info.compXcptnsCount; XTnum++)
5812         {
5813             DWORD             tmpOffset;
5814             CORINFO_EH_CLAUSE clause;
5815             info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
5816             noway_assert(clause.HandlerLength != (unsigned)-1);
5817
5818             if (clause.TryLength <= 0)
5819             {
5820                 BADCODE("try block length <=0");
5821             }
5822
5823             /* Mark the 'try' block extent and the handler itself */
5824
5825             if (clause.TryOffset > info.compILCodeSize)
5826             {
5827                 BADCODE("try offset is > codesize");
5828             }
5829             if (jumpTarget[clause.TryOffset] == JT_NONE)
5830             {
5831                 jumpTarget[clause.TryOffset] = JT_ADDR;
5832             }
5833
5834             tmpOffset = clause.TryOffset + clause.TryLength;
5835             if (tmpOffset > info.compILCodeSize)
5836             {
5837                 BADCODE("try end is > codesize");
5838             }
5839             if (jumpTarget[tmpOffset] == JT_NONE)
5840             {
5841                 jumpTarget[tmpOffset] = JT_ADDR;
5842             }
5843
5844             if (clause.HandlerOffset > info.compILCodeSize)
5845             {
5846                 BADCODE("handler offset > codesize");
5847             }
5848             if (jumpTarget[clause.HandlerOffset] == JT_NONE)
5849             {
5850                 jumpTarget[clause.HandlerOffset] = JT_ADDR;
5851             }
5852
5853             tmpOffset = clause.HandlerOffset + clause.HandlerLength;
5854             if (tmpOffset > info.compILCodeSize)
5855             {
5856                 BADCODE("handler end > codesize");
5857             }
5858             if (jumpTarget[tmpOffset] == JT_NONE)
5859             {
5860                 jumpTarget[tmpOffset] = JT_ADDR;
5861             }
5862
5863             if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5864             {
5865                 if (clause.FilterOffset > info.compILCodeSize)
5866                 {
5867                     BADCODE("filter offset > codesize");
5868                 }
5869                 if (jumpTarget[clause.FilterOffset] == JT_NONE)
5870                 {
5871                     jumpTarget[clause.FilterOffset] = JT_ADDR;
5872                 }
5873             }
5874         }
5875     }
5876
5877 #ifdef DEBUG
5878     if (verbose)
5879     {
5880         bool anyJumpTargets = false;
5881         printf("Jump targets:\n");
5882         for (unsigned i = 0; i < info.compILCodeSize + 1; i++)
5883         {
5884             if (jumpTarget[i] == JT_NONE)
5885             {
5886                 continue;
5887             }
5888
5889             anyJumpTargets = true;
5890             printf("  IL_%04x", i);
5891
5892             if (jumpTarget[i] & JT_ADDR)
5893             {
5894                 printf(" addr");
5895             }
5896             if (jumpTarget[i] & JT_MULTI)
5897             {
5898                 printf(" multi");
5899             }
5900             printf("\n");
5901         }
5902         if (!anyJumpTargets)
5903         {
5904             printf("  none\n");
5905         }
5906     }
5907 #endif // DEBUG
5908
5909     /* Now create the basic blocks */
5910
5911     unsigned retBlocks = fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget);
5912
5913     if (compIsForInlining())
5914     {
5915
5916 #ifdef DEBUG
5917         // If fgFindJumpTargets marked the call as "no return" there
5918         // really should be no BBJ_RETURN blocks in the method.
5919         bool markedNoReturn = (impInlineInfo->iciCall->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN) != 0;
5920         assert((markedNoReturn && (retBlocks == 0)) || (!markedNoReturn && (retBlocks >= 1)));
5921 #endif // DEBUG
5922
5923         if (compInlineResult->IsFailure())
5924         {
5925             return;
5926         }
5927
5928         noway_assert(info.compXcptnsCount == 0);
5929         compHndBBtab = impInlineInfo->InlinerCompiler->compHndBBtab;
5930         compHndBBtabAllocCount =
5931             impInlineInfo->InlinerCompiler->compHndBBtabAllocCount; // we probably only use the table, not add to it.
5932         compHndBBtabCount    = impInlineInfo->InlinerCompiler->compHndBBtabCount;
5933         info.compXcptnsCount = impInlineInfo->InlinerCompiler->info.compXcptnsCount;
5934
5935         // Use a spill temp for the return value if there are multiple return blocks,
5936         // or if the inlinee has GC ref locals.
5937         if ((info.compRetNativeType != TYP_VOID) && ((retBlocks > 1) || impInlineInfo->HasGcRefLocals()))
5938         {
5939             // The lifetime of this var might expand multiple BBs. So it is a long lifetime compiler temp.
5940             lvaInlineeReturnSpillTemp                  = lvaGrabTemp(false DEBUGARG("Inline return value spill temp"));
5941             lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType;
5942
5943             // If the method returns a ref class, set the class of the spill temp
5944             // to the method's return value. We may update this later if it turns
5945             // out we can prove the method returns a more specific type.
5946             if (info.compRetType == TYP_REF)
5947             {
5948                 CORINFO_CLASS_HANDLE retClassHnd = impInlineInfo->inlineCandidateInfo->methInfo.args.retTypeClass;
5949                 if (retClassHnd != nullptr)
5950                 {
5951                     lvaSetClass(lvaInlineeReturnSpillTemp, retClassHnd);
5952                 }
5953             }
5954         }
5955
5956         return;
5957     }
5958
5959     /* Mark all blocks within 'try' blocks as such */
5960
5961     if (info.compXcptnsCount == 0)
5962     {
5963         return;
5964     }
5965
5966     if (info.compXcptnsCount > MAX_XCPTN_INDEX)
5967     {
5968         IMPL_LIMITATION("too many exception clauses");
5969     }
5970
5971     /* Allocate the exception handler table */
5972
5973     fgAllocEHTable();
5974
5975     /* Assume we don't need to sort the EH table (such that nested try/catch
5976      * appear before their try or handler parent). The EH verifier will notice
5977      * when we do need to sort it.
5978      */
5979
5980     fgNeedToSortEHTable = false;
5981
5982     verInitEHTree(info.compXcptnsCount);
5983     EHNodeDsc* initRoot = ehnNext; // remember the original root since
5984                                    // it may get modified during insertion
5985
5986     // Annotate BBs with exception handling information required for generating correct eh code
5987     // as well as checking for correct IL
5988
5989     EHblkDsc* HBtab;
5990
5991     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
5992     {
5993         CORINFO_EH_CLAUSE clause;
5994         info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
5995         noway_assert(clause.HandlerLength != (unsigned)-1); // @DEPRECATED
5996
5997 #ifdef DEBUG
5998         if (verbose)
5999         {
6000             dispIncomingEHClause(XTnum, clause);
6001         }
6002 #endif // DEBUG
6003
6004         IL_OFFSET tryBegOff    = clause.TryOffset;
6005         IL_OFFSET tryEndOff    = tryBegOff + clause.TryLength;
6006         IL_OFFSET filterBegOff = 0;
6007         IL_OFFSET hndBegOff    = clause.HandlerOffset;
6008         IL_OFFSET hndEndOff    = hndBegOff + clause.HandlerLength;
6009
6010         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
6011         {
6012             filterBegOff = clause.FilterOffset;
6013         }
6014
6015         if (tryEndOff > info.compILCodeSize)
6016         {
6017             BADCODE3("end of try block beyond end of method for try", " at offset %04X", tryBegOff);
6018         }
6019         if (hndEndOff > info.compILCodeSize)
6020         {
6021             BADCODE3("end of hnd block beyond end of method for try", " at offset %04X", tryBegOff);
6022         }
6023
6024         HBtab->ebdTryBegOffset    = tryBegOff;
6025         HBtab->ebdTryEndOffset    = tryEndOff;
6026         HBtab->ebdFilterBegOffset = filterBegOff;
6027         HBtab->ebdHndBegOffset    = hndBegOff;
6028         HBtab->ebdHndEndOffset    = hndEndOff;
6029
6030         /* Convert the various addresses to basic blocks */
6031
6032         BasicBlock* tryBegBB = fgLookupBB(tryBegOff);
6033         BasicBlock* tryEndBB =
6034             fgLookupBB(tryEndOff); // note: this can be NULL if the try region is at the end of the function
6035         BasicBlock* hndBegBB = fgLookupBB(hndBegOff);
6036         BasicBlock* hndEndBB = nullptr;
6037         BasicBlock* filtBB   = nullptr;
6038         BasicBlock* block;
6039
6040         //
6041         // Assert that the try/hnd beginning blocks are set up correctly
6042         //
6043         if (tryBegBB == nullptr)
6044         {
6045             BADCODE("Try Clause is invalid");
6046         }
6047
6048         if (hndBegBB == nullptr)
6049         {
6050             BADCODE("Handler Clause is invalid");
6051         }
6052
6053         tryBegBB->bbFlags |= BBF_HAS_LABEL;
6054         hndBegBB->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
6055
6056 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
6057         // This will change the block weight from 0 to 1
6058         // and clear the rarely run flag
6059         hndBegBB->makeBlockHot();
6060 #else
6061         hndBegBB->bbSetRunRarely();   // handler entry points are rarely executed
6062 #endif
6063
6064         if (hndEndOff < info.compILCodeSize)
6065         {
6066             hndEndBB = fgLookupBB(hndEndOff);
6067         }
6068
6069         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
6070         {
6071             filtBB = HBtab->ebdFilter = fgLookupBB(clause.FilterOffset);
6072
6073             filtBB->bbCatchTyp = BBCT_FILTER;
6074             filtBB->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
6075
6076             hndBegBB->bbCatchTyp = BBCT_FILTER_HANDLER;
6077
6078 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
6079             // This will change the block weight from 0 to 1
6080             // and clear the rarely run flag
6081             filtBB->makeBlockHot();
6082 #else
6083             filtBB->bbSetRunRarely(); // filter entry points are rarely executed
6084 #endif
6085
6086             // Mark all BBs that belong to the filter with the XTnum of the corresponding handler
6087             for (block = filtBB; /**/; block = block->bbNext)
6088             {
6089                 if (block == nullptr)
6090                 {
6091                     BADCODE3("Missing endfilter for filter", " at offset %04X", filtBB->bbCodeOffs);
6092                     return;
6093                 }
6094
6095                 // Still inside the filter
6096                 block->setHndIndex(XTnum);
6097
6098                 if (block->bbJumpKind == BBJ_EHFILTERRET)
6099                 {
6100                     // Mark catch handler as successor.
6101                     block->bbJumpDest = hndBegBB;
6102                     assert(block->bbJumpDest->bbCatchTyp == BBCT_FILTER_HANDLER);
6103                     break;
6104                 }
6105             }
6106
6107             if (!block->bbNext || block->bbNext != hndBegBB)
6108             {
6109                 BADCODE3("Filter does not immediately precede handler for filter", " at offset %04X",
6110                          filtBB->bbCodeOffs);
6111             }
6112         }
6113         else
6114         {
6115             HBtab->ebdTyp = clause.ClassToken;
6116
6117             /* Set bbCatchTyp as appropriate */
6118
6119             if (clause.Flags & CORINFO_EH_CLAUSE_FINALLY)
6120             {
6121                 hndBegBB->bbCatchTyp = BBCT_FINALLY;
6122             }
6123             else
6124             {
6125                 if (clause.Flags & CORINFO_EH_CLAUSE_FAULT)
6126                 {
6127                     hndBegBB->bbCatchTyp = BBCT_FAULT;
6128                 }
6129                 else
6130                 {
6131                     hndBegBB->bbCatchTyp = clause.ClassToken;
6132
6133                     // These values should be non-zero value that will
6134                     // not collide with real tokens for bbCatchTyp
6135                     if (clause.ClassToken == 0)
6136                     {
6137                         BADCODE("Exception catch type is Null");
6138                     }
6139
6140                     noway_assert(clause.ClassToken != BBCT_FAULT);
6141                     noway_assert(clause.ClassToken != BBCT_FINALLY);
6142                     noway_assert(clause.ClassToken != BBCT_FILTER);
6143                     noway_assert(clause.ClassToken != BBCT_FILTER_HANDLER);
6144                 }
6145             }
6146         }
6147
6148         /* Mark the initial block and last blocks in the 'try' region */
6149
6150         tryBegBB->bbFlags |= BBF_TRY_BEG | BBF_HAS_LABEL;
6151
6152         /*  Prevent future optimizations of removing the first block   */
6153         /*  of a TRY block and the first block of an exception handler */
6154
6155         tryBegBB->bbFlags |= BBF_DONT_REMOVE;
6156         hndBegBB->bbFlags |= BBF_DONT_REMOVE;
6157         hndBegBB->bbRefs++; // The first block of a handler gets an extra, "artificial" reference count.
6158
6159         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
6160         {
6161             filtBB->bbFlags |= BBF_DONT_REMOVE;
6162             filtBB->bbRefs++; // The first block of a filter gets an extra, "artificial" reference count.
6163         }
6164
6165         tryBegBB->bbFlags |= BBF_DONT_REMOVE;
6166         hndBegBB->bbFlags |= BBF_DONT_REMOVE;
6167
6168         //
6169         // Store the info to the table of EH block handlers
6170         //
6171
6172         HBtab->ebdHandlerType = ToEHHandlerType(clause.Flags);
6173
6174         HBtab->ebdTryBeg  = tryBegBB;
6175         HBtab->ebdTryLast = (tryEndBB == nullptr) ? fgLastBB : tryEndBB->bbPrev;
6176
6177         HBtab->ebdHndBeg  = hndBegBB;
6178         HBtab->ebdHndLast = (hndEndBB == nullptr) ? fgLastBB : hndEndBB->bbPrev;
6179
6180         //
6181         // Assert that all of our try/hnd blocks are setup correctly.
6182         //
6183         if (HBtab->ebdTryLast == nullptr)
6184         {
6185             BADCODE("Try Clause is invalid");
6186         }
6187
6188         if (HBtab->ebdHndLast == nullptr)
6189         {
6190             BADCODE("Handler Clause is invalid");
6191         }
6192
6193         //
6194         // Verify that it's legal
6195         //
6196
6197         verInsertEhNode(&clause, HBtab);
6198
6199     } // end foreach handler table entry
6200
6201     fgSortEHTable();
6202
6203     // Next, set things related to nesting that depend on the sorting being complete.
6204
6205     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
6206     {
6207         /* Mark all blocks in the finally/fault or catch clause */
6208
6209         BasicBlock* tryBegBB = HBtab->ebdTryBeg;
6210         BasicBlock* hndBegBB = HBtab->ebdHndBeg;
6211
6212         IL_OFFSET tryBegOff = HBtab->ebdTryBegOffset;
6213         IL_OFFSET tryEndOff = HBtab->ebdTryEndOffset;
6214
6215         IL_OFFSET hndBegOff = HBtab->ebdHndBegOffset;
6216         IL_OFFSET hndEndOff = HBtab->ebdHndEndOffset;
6217
6218         BasicBlock* block;
6219
6220         for (block = hndBegBB; block && (block->bbCodeOffs < hndEndOff); block = block->bbNext)
6221         {
6222             if (!block->hasHndIndex())
6223             {
6224                 block->setHndIndex(XTnum);
6225             }
6226
6227             // All blocks in a catch handler or filter are rarely run, except the entry
6228             if ((block != hndBegBB) && (hndBegBB->bbCatchTyp != BBCT_FINALLY))
6229             {
6230                 block->bbSetRunRarely();
6231             }
6232         }
6233
6234         /* Mark all blocks within the covered range of the try */
6235
6236         for (block = tryBegBB; block && (block->bbCodeOffs < tryEndOff); block = block->bbNext)
6237         {
6238             /* Mark this BB as belonging to a 'try' block */
6239
6240             if (!block->hasTryIndex())
6241             {
6242                 block->setTryIndex(XTnum);
6243             }
6244
6245 #ifdef DEBUG
6246             /* Note: the BB can't span the 'try' block */
6247
6248             if (!(block->bbFlags & BBF_INTERNAL))
6249             {
6250                 noway_assert(tryBegOff <= block->bbCodeOffs);
6251                 noway_assert(tryEndOff >= block->bbCodeOffsEnd || tryEndOff == tryBegOff);
6252             }
6253 #endif
6254         }
6255
6256 /*  Init ebdHandlerNestingLevel of current clause, and bump up value for all
6257  *  enclosed clauses (which have to be before it in the table).
6258  *  Innermost try-finally blocks must precede outermost
6259  *  try-finally blocks.
6260  */
6261
6262 #if !FEATURE_EH_FUNCLETS
6263         HBtab->ebdHandlerNestingLevel = 0;
6264 #endif // !FEATURE_EH_FUNCLETS
6265
6266         HBtab->ebdEnclosingTryIndex = EHblkDsc::NO_ENCLOSING_INDEX;
6267         HBtab->ebdEnclosingHndIndex = EHblkDsc::NO_ENCLOSING_INDEX;
6268
6269         noway_assert(XTnum < compHndBBtabCount);
6270         noway_assert(XTnum == ehGetIndex(HBtab));
6271
6272         for (EHblkDsc* xtab = compHndBBtab; xtab < HBtab; xtab++)
6273         {
6274 #if !FEATURE_EH_FUNCLETS
6275             if (jitIsBetween(xtab->ebdHndBegOffs(), hndBegOff, hndEndOff))
6276             {
6277                 xtab->ebdHandlerNestingLevel++;
6278             }
6279 #endif // !FEATURE_EH_FUNCLETS
6280
6281             /* If we haven't recorded an enclosing try index for xtab then see
6282              *  if this EH region should be recorded.  We check if the
6283              *  first offset in the xtab lies within our region.  If so,
6284              *  the last offset also must lie within the region, due to
6285              *  nesting rules. verInsertEhNode(), below, will check for proper nesting.
6286              */
6287             if (xtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
6288             {
6289                 bool begBetween = jitIsBetween(xtab->ebdTryBegOffs(), tryBegOff, tryEndOff);
6290                 if (begBetween)
6291                 {
6292                     // Record the enclosing scope link
6293                     xtab->ebdEnclosingTryIndex = (unsigned short)XTnum;
6294                 }
6295             }
6296
6297             /* Do the same for the enclosing handler index.
6298              */
6299             if (xtab->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX)
6300             {
6301                 bool begBetween = jitIsBetween(xtab->ebdTryBegOffs(), hndBegOff, hndEndOff);
6302                 if (begBetween)
6303                 {
6304                     // Record the enclosing scope link
6305                     xtab->ebdEnclosingHndIndex = (unsigned short)XTnum;
6306                 }
6307             }
6308         }
6309
6310     } // end foreach handler table entry
6311
6312 #if !FEATURE_EH_FUNCLETS
6313
6314     EHblkDsc* HBtabEnd;
6315     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
6316     {
6317         if (ehMaxHndNestingCount <= HBtab->ebdHandlerNestingLevel)
6318             ehMaxHndNestingCount = HBtab->ebdHandlerNestingLevel + 1;
6319     }
6320
6321 #endif // !FEATURE_EH_FUNCLETS
6322
6323 #ifndef DEBUG
6324     if (tiVerificationNeeded)
6325 #endif
6326     {
6327         // always run these checks for a debug build
6328         verCheckNestingLevel(initRoot);
6329     }
6330
6331 #ifndef DEBUG
6332     // fgNormalizeEH assumes that this test has been passed.  And Ssa assumes that fgNormalizeEHTable
6333     // has been run.  So do this unless we're in minOpts mode (and always in debug).
6334     if (tiVerificationNeeded || !opts.MinOpts())
6335 #endif
6336     {
6337         fgCheckBasicBlockControlFlow();
6338     }
6339
6340 #ifdef DEBUG
6341     if (verbose)
6342     {
6343         JITDUMP("*************** After fgFindBasicBlocks() has created the EH table\n");
6344         fgDispHandlerTab();
6345     }
6346
6347     // We can't verify the handler table until all the IL legality checks have been done (above), since bad IL
6348     // (such as illegal nesting of regions) will trigger asserts here.
6349     fgVerifyHandlerTab();
6350 #endif
6351
6352     fgNormalizeEH();
6353 }
6354
6355 /*****************************************************************************
6356  * Check control flow constraints for well formed IL. Bail if any of the constraints
6357  * are violated.
6358  */
6359
6360 void Compiler::fgCheckBasicBlockControlFlow()
6361 {
6362     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6363
6364     EHblkDsc* HBtab;
6365
6366     for (BasicBlock* blk = fgFirstBB; blk; blk = blk->bbNext)
6367     {
6368         if (blk->bbFlags & BBF_INTERNAL)
6369         {
6370             continue;
6371         }
6372
6373         switch (blk->bbJumpKind)
6374         {
6375             case BBJ_NONE: // block flows into the next one (no jump)
6376
6377                 fgControlFlowPermitted(blk, blk->bbNext);
6378
6379                 break;
6380
6381             case BBJ_ALWAYS: // block does unconditional jump to target
6382
6383                 fgControlFlowPermitted(blk, blk->bbJumpDest);
6384
6385                 break;
6386
6387             case BBJ_COND: // block conditionally jumps to the target
6388
6389                 fgControlFlowPermitted(blk, blk->bbNext);
6390
6391                 fgControlFlowPermitted(blk, blk->bbJumpDest);
6392
6393                 break;
6394
6395             case BBJ_RETURN: // block ends with 'ret'
6396
6397                 if (blk->hasTryIndex() || blk->hasHndIndex())
6398                 {
6399                     BADCODE3("Return from a protected block", ". Before offset %04X", blk->bbCodeOffsEnd);
6400                 }
6401                 break;
6402
6403             case BBJ_EHFINALLYRET:
6404             case BBJ_EHFILTERRET:
6405
6406                 if (!blk->hasHndIndex()) // must be part of a handler
6407                 {
6408                     BADCODE3("Missing handler", ". Before offset %04X", blk->bbCodeOffsEnd);
6409                 }
6410
6411                 HBtab = ehGetDsc(blk->getHndIndex());
6412
6413                 // Endfilter allowed only in a filter block
6414                 if (blk->bbJumpKind == BBJ_EHFILTERRET)
6415                 {
6416                     if (!HBtab->HasFilter())
6417                     {
6418                         BADCODE("Unexpected endfilter");
6419                     }
6420                 }
6421                 // endfinally allowed only in a finally/fault block
6422                 else if (!HBtab->HasFinallyOrFaultHandler())
6423                 {
6424                     BADCODE("Unexpected endfinally");
6425                 }
6426
6427                 // The handler block should be the innermost block
6428                 // Exception blocks are listed, innermost first.
6429                 if (blk->hasTryIndex() && (blk->getTryIndex() < blk->getHndIndex()))
6430                 {
6431                     BADCODE("endfinally / endfilter in nested try block");
6432                 }
6433
6434                 break;
6435
6436             case BBJ_THROW: // block ends with 'throw'
6437                 /* throw is permitted from every BB, so nothing to check */
6438                 /* importer makes sure that rethrow is done from a catch */
6439                 break;
6440
6441             case BBJ_LEAVE: // block always jumps to the target, maybe out of guarded
6442                             // region. Used temporarily until importing
6443                 fgControlFlowPermitted(blk, blk->bbJumpDest, TRUE);
6444
6445                 break;
6446
6447             case BBJ_SWITCH: // block ends with a switch statement
6448
6449                 BBswtDesc* swtDesc;
6450                 swtDesc = blk->bbJumpSwt;
6451
6452                 assert(swtDesc);
6453
6454                 unsigned i;
6455                 for (i = 0; i < swtDesc->bbsCount; i++)
6456                 {
6457                     fgControlFlowPermitted(blk, swtDesc->bbsDstTab[i]);
6458                 }
6459
6460                 break;
6461
6462             case BBJ_EHCATCHRET:  // block ends with a leave out of a catch (only #if FEATURE_EH_FUNCLETS)
6463             case BBJ_CALLFINALLY: // block always calls the target finally
6464             default:
6465                 noway_assert(!"Unexpected bbJumpKind"); // these blocks don't get created until importing
6466                 break;
6467         }
6468     }
6469 }
6470
6471 /****************************************************************************
6472  * Check that the leave from the block is legal.
6473  * Consider removing this check here if we  can do it cheaply during importing
6474  */
6475
6476 void Compiler::fgControlFlowPermitted(BasicBlock* blkSrc, BasicBlock* blkDest, BOOL isLeave)
6477 {
6478     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6479
6480     unsigned srcHndBeg, destHndBeg;
6481     unsigned srcHndEnd, destHndEnd;
6482     bool     srcInFilter, destInFilter;
6483     bool     srcInCatch = false;
6484
6485     EHblkDsc* srcHndTab;
6486
6487     srcHndTab = ehInitHndRange(blkSrc, &srcHndBeg, &srcHndEnd, &srcInFilter);
6488     ehInitHndRange(blkDest, &destHndBeg, &destHndEnd, &destInFilter);
6489
6490     /* Impose the rules for leaving or jumping from handler blocks */
6491
6492     if (blkSrc->hasHndIndex())
6493     {
6494         srcInCatch = srcHndTab->HasCatchHandler() && srcHndTab->InHndRegionILRange(blkSrc);
6495
6496         /* Are we jumping within the same handler index? */
6497         if (BasicBlock::sameHndRegion(blkSrc, blkDest))
6498         {
6499             /* Do we have a filter clause? */
6500             if (srcHndTab->HasFilter())
6501             {
6502                 /* filters and catch handlers share same eh index  */
6503                 /* we need to check for control flow between them. */
6504                 if (srcInFilter != destInFilter)
6505                 {
6506                     if (!jitIsBetween(blkDest->bbCodeOffs, srcHndBeg, srcHndEnd))
6507                     {
6508                         BADCODE3("Illegal control flow between filter and handler", ". Before offset %04X",
6509                                  blkSrc->bbCodeOffsEnd);
6510                     }
6511                 }
6512             }
6513         }
6514         else
6515         {
6516             /* The handler indexes of blkSrc and blkDest are different */
6517             if (isLeave)
6518             {
6519                 /* Any leave instructions must not enter the dest handler from outside*/
6520                 if (!jitIsBetween(srcHndBeg, destHndBeg, destHndEnd))
6521                 {
6522                     BADCODE3("Illegal use of leave to enter handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6523                 }
6524             }
6525             else
6526             {
6527                 /* We must use a leave to exit a handler */
6528                 BADCODE3("Illegal control flow out of a handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6529             }
6530
6531             /* Do we have a filter clause? */
6532             if (srcHndTab->HasFilter())
6533             {
6534                 /* It is ok to leave from the handler block of a filter, */
6535                 /* but not from the filter block of a filter             */
6536                 if (srcInFilter != destInFilter)
6537                 {
6538                     BADCODE3("Illegal to leave a filter handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6539                 }
6540             }
6541
6542             /* We should never leave a finally handler */
6543             if (srcHndTab->HasFinallyHandler())
6544             {
6545                 BADCODE3("Illegal to leave a finally handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6546             }
6547
6548             /* We should never leave a fault handler */
6549             if (srcHndTab->HasFaultHandler())
6550             {
6551                 BADCODE3("Illegal to leave a fault handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6552             }
6553         }
6554     }
6555     else if (blkDest->hasHndIndex())
6556     {
6557         /* blkSrc was not inside a handler, but blkDst is inside a handler */
6558         BADCODE3("Illegal control flow into a handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6559     }
6560
6561     /* Are we jumping from a catch handler into the corresponding try? */
6562     /* VB uses this for "on error goto "                               */
6563
6564     if (isLeave && srcInCatch)
6565     {
6566         // inspect all handlers containing the jump source
6567
6568         bool      bValidJumpToTry   = false; // are we jumping in a valid way from a catch to the corresponding try?
6569         bool      bCatchHandlerOnly = true;  // false if we are jumping out of a non-catch handler
6570         EHblkDsc* ehTableEnd;
6571         EHblkDsc* ehDsc;
6572
6573         for (ehDsc = compHndBBtab, ehTableEnd = compHndBBtab + compHndBBtabCount;
6574              bCatchHandlerOnly && ehDsc < ehTableEnd; ehDsc++)
6575         {
6576             if (ehDsc->InHndRegionILRange(blkSrc))
6577             {
6578                 if (ehDsc->HasCatchHandler())
6579                 {
6580                     if (ehDsc->InTryRegionILRange(blkDest))
6581                     {
6582                         // If we already considered the jump for a different try/catch,
6583                         // we would have two overlapping try regions with two overlapping catch
6584                         // regions, which is illegal.
6585                         noway_assert(!bValidJumpToTry);
6586
6587                         // Allowed if it is the first instruction of an inner try
6588                         // (and all trys in between)
6589                         //
6590                         // try {
6591                         //  ..
6592                         // _tryAgain:
6593                         //  ..
6594                         //      try {
6595                         //      _tryNestedInner:
6596                         //        ..
6597                         //          try {
6598                         //          _tryNestedIllegal:
6599                         //            ..
6600                         //          } catch {
6601                         //            ..
6602                         //          }
6603                         //        ..
6604                         //      } catch {
6605                         //        ..
6606                         //      }
6607                         //  ..
6608                         // } catch {
6609                         //  ..
6610                         //  leave _tryAgain         // Allowed
6611                         //  ..
6612                         //  leave _tryNestedInner   // Allowed
6613                         //  ..
6614                         //  leave _tryNestedIllegal // Not Allowed
6615                         //  ..
6616                         // }
6617                         //
6618                         // Note: The leave is allowed also from catches nested inside the catch shown above.
6619
6620                         /* The common case where leave is to the corresponding try */
6621                         if (ehDsc->ebdIsSameTry(this, blkDest->getTryIndex()) ||
6622                             /* Also allowed is a leave to the start of a try which starts in the handler's try */
6623                             fgFlowToFirstBlockOfInnerTry(ehDsc->ebdTryBeg, blkDest, false))
6624                         {
6625                             bValidJumpToTry = true;
6626                         }
6627                     }
6628                 }
6629                 else
6630                 {
6631                     // We are jumping from a handler which is not a catch handler.
6632
6633                     // If it's a handler, but not a catch handler, it must be either a finally or fault
6634                     if (!ehDsc->HasFinallyOrFaultHandler())
6635                     {
6636                         BADCODE3("Handlers must be catch, finally, or fault", ". Before offset %04X",
6637                                  blkSrc->bbCodeOffsEnd);
6638                     }
6639
6640                     // Are we jumping out of this handler?
6641                     if (!ehDsc->InHndRegionILRange(blkDest))
6642                     {
6643                         bCatchHandlerOnly = false;
6644                     }
6645                 }
6646             }
6647             else if (ehDsc->InFilterRegionILRange(blkSrc))
6648             {
6649                 // Are we jumping out of a filter?
6650                 if (!ehDsc->InFilterRegionILRange(blkDest))
6651                 {
6652                     bCatchHandlerOnly = false;
6653                 }
6654             }
6655         }
6656
6657         if (bCatchHandlerOnly)
6658         {
6659             if (bValidJumpToTry)
6660             {
6661                 return;
6662             }
6663             else
6664             {
6665                 // FALL THROUGH
6666                 // This is either the case of a leave to outside the try/catch,
6667                 // or a leave to a try not nested in this try/catch.
6668                 // The first case is allowed, the second one will be checked
6669                 // later when we check the try block rules (it is illegal if we
6670                 // jump to the middle of the destination try).
6671             }
6672         }
6673         else
6674         {
6675             BADCODE3("illegal leave to exit a finally, fault or filter", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6676         }
6677     }
6678
6679     /* Check all the try block rules */
6680
6681     IL_OFFSET srcTryBeg;
6682     IL_OFFSET srcTryEnd;
6683     IL_OFFSET destTryBeg;
6684     IL_OFFSET destTryEnd;
6685
6686     ehInitTryRange(blkSrc, &srcTryBeg, &srcTryEnd);
6687     ehInitTryRange(blkDest, &destTryBeg, &destTryEnd);
6688
6689     /* Are we jumping between try indexes? */
6690     if (!BasicBlock::sameTryRegion(blkSrc, blkDest))
6691     {
6692         // Are we exiting from an inner to outer try?
6693         if (jitIsBetween(srcTryBeg, destTryBeg, destTryEnd) && jitIsBetween(srcTryEnd - 1, destTryBeg, destTryEnd))
6694         {
6695             if (!isLeave)
6696             {
6697                 BADCODE3("exit from try block without a leave", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6698             }
6699         }
6700         else if (jitIsBetween(destTryBeg, srcTryBeg, srcTryEnd))
6701         {
6702             // check that the dest Try is first instruction of an inner try
6703             if (!fgFlowToFirstBlockOfInnerTry(blkSrc, blkDest, false))
6704             {
6705                 BADCODE3("control flow into middle of try", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6706             }
6707         }
6708         else // there is no nesting relationship between src and dest
6709         {
6710             if (isLeave)
6711             {
6712                 // check that the dest Try is first instruction of an inner try sibling
6713                 if (!fgFlowToFirstBlockOfInnerTry(blkSrc, blkDest, true))
6714                 {
6715                     BADCODE3("illegal leave into middle of try", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6716                 }
6717             }
6718             else
6719             {
6720                 BADCODE3("illegal control flow in to/out of try block", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6721             }
6722         }
6723     }
6724 }
6725
6726 /*****************************************************************************
6727  *  Check that blkDest is the first block of an inner try or a sibling
6728  *    with no intervening trys in between
6729  */
6730
6731 bool Compiler::fgFlowToFirstBlockOfInnerTry(BasicBlock* blkSrc, BasicBlock* blkDest, bool sibling)
6732 {
6733     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6734
6735     noway_assert(blkDest->hasTryIndex());
6736
6737     unsigned XTnum     = blkDest->getTryIndex();
6738     unsigned lastXTnum = blkSrc->hasTryIndex() ? blkSrc->getTryIndex() : compHndBBtabCount;
6739     noway_assert(XTnum < compHndBBtabCount);
6740     noway_assert(lastXTnum <= compHndBBtabCount);
6741
6742     EHblkDsc* HBtab = ehGetDsc(XTnum);
6743
6744     // check that we are not jumping into middle of try
6745     if (HBtab->ebdTryBeg != blkDest)
6746     {
6747         return false;
6748     }
6749
6750     if (sibling)
6751     {
6752         noway_assert(!BasicBlock::sameTryRegion(blkSrc, blkDest));
6753
6754         // find the l.u.b of the two try ranges
6755         // Set lastXTnum to the l.u.b.
6756
6757         HBtab = ehGetDsc(lastXTnum);
6758
6759         for (lastXTnum++, HBtab++; lastXTnum < compHndBBtabCount; lastXTnum++, HBtab++)
6760         {
6761             if (jitIsBetweenInclusive(blkDest->bbNum, HBtab->ebdTryBeg->bbNum, HBtab->ebdTryLast->bbNum))
6762             {
6763                 break;
6764             }
6765         }
6766     }
6767
6768     // now check there are no intervening trys between dest and l.u.b
6769     // (it is ok to have intervening trys as long as they all start at
6770     //  the same code offset)
6771
6772     HBtab = ehGetDsc(XTnum);
6773
6774     for (XTnum++, HBtab++; XTnum < lastXTnum; XTnum++, HBtab++)
6775     {
6776         if (HBtab->ebdTryBeg->bbNum < blkDest->bbNum && blkDest->bbNum <= HBtab->ebdTryLast->bbNum)
6777         {
6778             return false;
6779         }
6780     }
6781
6782     return true;
6783 }
6784
6785 /*****************************************************************************
6786  *  Returns the handler nesting level of the block.
6787  *  *pFinallyNesting is set to the nesting level of the inner-most
6788  *  finally-protected try the block is in.
6789  */
6790
6791 unsigned Compiler::fgGetNestingLevel(BasicBlock* block, unsigned* pFinallyNesting)
6792 {
6793     unsigned  curNesting = 0;            // How many handlers is the block in
6794     unsigned  tryFin     = (unsigned)-1; // curNesting when we see innermost finally-protected try
6795     unsigned  XTnum;
6796     EHblkDsc* HBtab;
6797
6798     /* We find the block's handler nesting level by walking over the
6799        complete exception table and find enclosing clauses. */
6800
6801     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
6802     {
6803         noway_assert(HBtab->ebdTryBeg && HBtab->ebdHndBeg);
6804
6805         if (HBtab->HasFinallyHandler() && (tryFin == (unsigned)-1) && bbInTryRegions(XTnum, block))
6806         {
6807             tryFin = curNesting;
6808         }
6809         else if (bbInHandlerRegions(XTnum, block))
6810         {
6811             curNesting++;
6812         }
6813     }
6814
6815     if (tryFin == (unsigned)-1)
6816     {
6817         tryFin = curNesting;
6818     }
6819
6820     if (pFinallyNesting)
6821     {
6822         *pFinallyNesting = curNesting - tryFin;
6823     }
6824
6825     return curNesting;
6826 }
6827
6828 /*****************************************************************************
6829  *
6830  *  Import the basic blocks of the procedure.
6831  */
6832
6833 void Compiler::fgImport()
6834 {
6835     fgHasPostfix = false;
6836
6837     impImport(fgFirstBB);
6838
6839     if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION))
6840     {
6841         CorInfoMethodRuntimeFlags verFlag;
6842         verFlag = tiIsVerifiableCode ? CORINFO_FLG_VERIFIABLE : CORINFO_FLG_UNVERIFIABLE;
6843         info.compCompHnd->setMethodAttribs(info.compMethodHnd, verFlag);
6844     }
6845 }
6846
6847 /*****************************************************************************
6848  * This function returns true if tree is a node with a call
6849  * that unconditionally throws an exception
6850  */
6851
6852 bool Compiler::fgIsThrow(GenTree* tree)
6853 {
6854     if ((tree->gtOper != GT_CALL) || (tree->gtCall.gtCallType != CT_HELPER))
6855     {
6856         return false;
6857     }
6858
6859     // TODO-Throughput: Replace all these calls to eeFindHelper() with a table based lookup
6860
6861     if ((tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_OVERFLOW)) ||
6862         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_VERIFICATION)) ||
6863         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_RNGCHKFAIL)) ||
6864         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWDIVZERO)) ||
6865         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWNULLREF)) ||
6866         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW)) ||
6867         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_RETHROW)) ||
6868         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED)) ||
6869         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED)))
6870     {
6871         noway_assert(tree->gtFlags & GTF_CALL);
6872         noway_assert(tree->gtFlags & GTF_EXCEPT);
6873         return true;
6874     }
6875
6876     // TODO-CQ: there are a bunch of managed methods in [mscorlib]System.ThrowHelper
6877     // that would be nice to recognize.
6878
6879     return false;
6880 }
6881
6882 /*****************************************************************************
6883  * This function returns true for blocks that are in different hot-cold regions.
6884  * It returns false when the blocks are both in the same regions
6885  */
6886
6887 bool Compiler::fgInDifferentRegions(BasicBlock* blk1, BasicBlock* blk2)
6888 {
6889     noway_assert(blk1 != nullptr);
6890     noway_assert(blk2 != nullptr);
6891
6892     if (fgFirstColdBlock == nullptr)
6893     {
6894         return false;
6895     }
6896
6897     // If one block is Hot and the other is Cold then we are in different regions
6898     return ((blk1->bbFlags & BBF_COLD) != (blk2->bbFlags & BBF_COLD));
6899 }
6900
6901 bool Compiler::fgIsBlockCold(BasicBlock* blk)
6902 {
6903     noway_assert(blk != nullptr);
6904
6905     if (fgFirstColdBlock == nullptr)
6906     {
6907         return false;
6908     }
6909
6910     return ((blk->bbFlags & BBF_COLD) != 0);
6911 }
6912
6913 /*****************************************************************************
6914  * This function returns true if tree is a GT_COMMA node with a call
6915  * that unconditionally throws an exception
6916  */
6917
6918 bool Compiler::fgIsCommaThrow(GenTree* tree, bool forFolding /* = false */)
6919 {
6920     // Instead of always folding comma throws,
6921     // with stress enabled we only fold half the time
6922
6923     if (forFolding && compStressCompile(STRESS_FOLD, 50))
6924     {
6925         return false; /* Don't fold */
6926     }
6927
6928     /* Check for cast of a GT_COMMA with a throw overflow */
6929     if ((tree->gtOper == GT_COMMA) && (tree->gtFlags & GTF_CALL) && (tree->gtFlags & GTF_EXCEPT))
6930     {
6931         return (fgIsThrow(tree->gtOp.gtOp1));
6932     }
6933     return false;
6934 }
6935
6936 //------------------------------------------------------------------------
6937 // fgIsIndirOfAddrOfLocal: Determine whether "tree" is an indirection of a local.
6938 //
6939 // Arguments:
6940 //    tree - The tree node under consideration
6941 //
6942 // Return Value:
6943 //    If "tree" is a indirection (GT_IND, GT_BLK, or GT_OBJ) whose arg is an ADDR,
6944 //    whose arg in turn is a LCL_VAR, return that LCL_VAR node, else nullptr.
6945 //
6946 // static
6947 GenTree* Compiler::fgIsIndirOfAddrOfLocal(GenTree* tree)
6948 {
6949     GenTree* res = nullptr;
6950     if (tree->OperIsIndir())
6951     {
6952         GenTree* addr = tree->AsIndir()->Addr();
6953
6954         // Post rationalization, we can have Indir(Lea(..) trees. Therefore to recognize
6955         // Indir of addr of a local, skip over Lea in Indir(Lea(base, index, scale, offset))
6956         // to get to base variable.
6957         if (addr->OperGet() == GT_LEA)
6958         {
6959             // We use this method in backward dataflow after liveness computation - fgInterBlockLocalVarLiveness().
6960             // Therefore it is critical that we don't miss 'uses' of any local.  It may seem this method overlooks
6961             // if the index part of the LEA has indir( someAddrOperator ( lclVar ) ) to search for a use but it's
6962             // covered by the fact we're traversing the expression in execution order and we also visit the index.
6963             GenTreeAddrMode* lea  = addr->AsAddrMode();
6964             GenTree*         base = lea->Base();
6965
6966             if (base != nullptr)
6967             {
6968                 if (base->OperGet() == GT_IND)
6969                 {
6970                     return fgIsIndirOfAddrOfLocal(base);
6971                 }
6972                 // else use base as addr
6973                 addr = base;
6974             }
6975         }
6976
6977         if (addr->OperGet() == GT_ADDR)
6978         {
6979             GenTree* lclvar = addr->gtOp.gtOp1;
6980             if (lclvar->OperGet() == GT_LCL_VAR)
6981             {
6982                 res = lclvar;
6983             }
6984         }
6985         else if (addr->OperGet() == GT_LCL_VAR_ADDR)
6986         {
6987             res = addr;
6988         }
6989     }
6990     return res;
6991 }
6992
6993 GenTreeCall* Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfoHelpFunc helper)
6994 {
6995     bool     bNeedClassID = true;
6996     unsigned callFlags    = 0;
6997
6998     var_types type = TYP_BYREF;
6999
7000     // This is sort of ugly, as we have knowledge of what the helper is returning.
7001     // We need the return type.
7002     switch (helper)
7003     {
7004         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
7005             bNeedClassID = false;
7006             __fallthrough;
7007
7008         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
7009             callFlags |= GTF_CALL_HOISTABLE;
7010             __fallthrough;
7011
7012         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
7013         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
7014         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
7015         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
7016         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
7017             // type = TYP_BYREF;
7018             break;
7019
7020         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
7021             bNeedClassID = false;
7022             __fallthrough;
7023
7024         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
7025             callFlags |= GTF_CALL_HOISTABLE;
7026             __fallthrough;
7027
7028         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
7029         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
7030         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
7031         case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
7032             type = TYP_I_IMPL;
7033             break;
7034
7035         default:
7036             assert(!"unknown shared statics helper");
7037             break;
7038     }
7039
7040     GenTreeArgList* argList = nullptr;
7041
7042     GenTree* opModuleIDArg;
7043     GenTree* opClassIDArg;
7044
7045     // Get the class ID
7046     unsigned clsID;
7047     size_t   moduleID;
7048     void*    pclsID;
7049     void*    pmoduleID;
7050
7051     clsID = info.compCompHnd->getClassDomainID(cls, &pclsID);
7052
7053     moduleID = info.compCompHnd->getClassModuleIdForStatics(cls, nullptr, &pmoduleID);
7054
7055     if (!(callFlags & GTF_CALL_HOISTABLE))
7056     {
7057         if (info.compCompHnd->getClassAttribs(cls) & CORINFO_FLG_BEFOREFIELDINIT)
7058         {
7059             callFlags |= GTF_CALL_HOISTABLE;
7060         }
7061     }
7062
7063     if (pmoduleID)
7064     {
7065         opModuleIDArg = gtNewIndOfIconHandleNode(TYP_I_IMPL, (size_t)pmoduleID, GTF_ICON_CIDMID_HDL, true);
7066     }
7067     else
7068     {
7069         opModuleIDArg = gtNewIconNode((size_t)moduleID, TYP_I_IMPL);
7070     }
7071
7072     if (bNeedClassID)
7073     {
7074         if (pclsID)
7075         {
7076             opClassIDArg = gtNewIndOfIconHandleNode(TYP_INT, (size_t)pclsID, GTF_ICON_CIDMID_HDL, true);
7077         }
7078         else
7079         {
7080             opClassIDArg = gtNewIconNode(clsID, TYP_INT);
7081         }
7082
7083         // call the helper to get the base
7084         argList = gtNewArgList(opModuleIDArg, opClassIDArg);
7085     }
7086     else
7087     {
7088         argList = gtNewArgList(opModuleIDArg);
7089     }
7090
7091     GenTreeCall* result = gtNewHelperCallNode(helper, type, argList);
7092     result->gtFlags |= callFlags;
7093
7094     // If we're importing the special EqualityComparer<T>.Default
7095     // intrinsic, flag the helper call. Later during inlining, we can
7096     // remove the helper call if the associated field lookup is unused.
7097     if ((info.compFlags & CORINFO_FLG_JIT_INTRINSIC) != 0)
7098     {
7099         NamedIntrinsic ni = lookupNamedIntrinsic(info.compMethodHnd);
7100         if (ni == NI_System_Collections_Generic_EqualityComparer_get_Default)
7101         {
7102             JITDUMP("\nmarking helper call [06%u] as special dce...\n", result->gtTreeID);
7103             result->gtCallMoreFlags |= GTF_CALL_M_HELPER_SPECIAL_DCE;
7104         }
7105     }
7106
7107     return result;
7108 }
7109
7110 GenTreeCall* Compiler::fgGetSharedCCtor(CORINFO_CLASS_HANDLE cls)
7111 {
7112 #ifdef FEATURE_READYTORUN_COMPILER
7113     if (opts.IsReadyToRun())
7114     {
7115         CORINFO_RESOLVED_TOKEN resolvedToken;
7116         memset(&resolvedToken, 0, sizeof(resolvedToken));
7117         resolvedToken.hClass = cls;
7118
7119         return impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_STATIC_BASE, TYP_BYREF);
7120     }
7121 #endif
7122
7123     // Call the shared non gc static helper, as its the fastest
7124     return fgGetStaticsCCtorHelper(cls, info.compCompHnd->getSharedCCtorHelper(cls));
7125 }
7126
7127 //------------------------------------------------------------------------------
7128 // fgAddrCouldBeNull : Check whether the address tree can represent null.
7129 //
7130 //
7131 // Arguments:
7132 //    addr     -  Address to check
7133 //
7134 // Return Value:
7135 //    True if address could be null; false otherwise
7136
7137 bool Compiler::fgAddrCouldBeNull(GenTree* addr)
7138 {
7139     addr = addr->gtEffectiveVal();
7140     if ((addr->gtOper == GT_CNS_INT) && addr->IsIconHandle())
7141     {
7142         return false;
7143     }
7144     else if (addr->gtOper == GT_LCL_VAR)
7145     {
7146         unsigned varNum = addr->AsLclVarCommon()->GetLclNum();
7147
7148         if (lvaIsImplicitByRefLocal(varNum))
7149         {
7150             return false;
7151         }
7152
7153         LclVarDsc* varDsc = &lvaTable[varNum];
7154
7155         if (varDsc->lvStackByref)
7156         {
7157             return false;
7158         }
7159     }
7160     else if (addr->gtOper == GT_ADDR)
7161     {
7162         if (addr->gtOp.gtOp1->gtOper == GT_CNS_INT)
7163         {
7164             GenTree* cns1Tree = addr->gtOp.gtOp1;
7165             if (!cns1Tree->IsIconHandle())
7166             {
7167                 // Indirection of some random constant...
7168                 // It is safest just to return true
7169                 return true;
7170             }
7171         }
7172
7173         return false; // we can't have a null address
7174     }
7175     else if (addr->gtOper == GT_ADD)
7176     {
7177         if (addr->gtOp.gtOp1->gtOper == GT_CNS_INT)
7178         {
7179             GenTree* cns1Tree = addr->gtOp.gtOp1;
7180             if (!cns1Tree->IsIconHandle())
7181             {
7182                 if (!fgIsBigOffset(cns1Tree->gtIntCon.gtIconVal))
7183                 {
7184                     // Op1 was an ordinary small constant
7185                     return fgAddrCouldBeNull(addr->gtOp.gtOp2);
7186                 }
7187             }
7188             else // Op1 was a handle represented as a constant
7189             {
7190                 // Is Op2 also a constant?
7191                 if (addr->gtOp.gtOp2->gtOper == GT_CNS_INT)
7192                 {
7193                     GenTree* cns2Tree = addr->gtOp.gtOp2;
7194                     // Is this an addition of a handle and constant
7195                     if (!cns2Tree->IsIconHandle())
7196                     {
7197                         if (!fgIsBigOffset(cns2Tree->gtIntCon.gtIconVal))
7198                         {
7199                             // Op2 was an ordinary small constant
7200                             return false; // we can't have a null address
7201                         }
7202                     }
7203                 }
7204             }
7205         }
7206         else
7207         {
7208             // Op1 is not a constant
7209             // What about Op2?
7210             if (addr->gtOp.gtOp2->gtOper == GT_CNS_INT)
7211             {
7212                 GenTree* cns2Tree = addr->gtOp.gtOp2;
7213                 // Is this an addition of a small constant
7214                 if (!cns2Tree->IsIconHandle())
7215                 {
7216                     if (!fgIsBigOffset(cns2Tree->gtIntCon.gtIconVal))
7217                     {
7218                         // Op2 was an ordinary small constant
7219                         return fgAddrCouldBeNull(addr->gtOp.gtOp1);
7220                     }
7221                 }
7222             }
7223         }
7224     }
7225     return true; // default result: addr could be null
7226 }
7227
7228 /*****************************************************************************
7229  *  Optimize the call to the delegate constructor.
7230  */
7231
7232 GenTree* Compiler::fgOptimizeDelegateConstructor(GenTreeCall*            call,
7233                                                  CORINFO_CONTEXT_HANDLE* ExactContextHnd,
7234                                                  CORINFO_RESOLVED_TOKEN* ldftnToken)
7235 {
7236     noway_assert(call->gtCallType == CT_USER_FUNC);
7237     CORINFO_METHOD_HANDLE methHnd = call->gtCallMethHnd;
7238     CORINFO_CLASS_HANDLE  clsHnd  = info.compCompHnd->getMethodClass(methHnd);
7239
7240     GenTree* targetMethod = call->gtCallArgs->Rest()->Current();
7241     noway_assert(targetMethod->TypeGet() == TYP_I_IMPL);
7242     genTreeOps            oper            = targetMethod->OperGet();
7243     CORINFO_METHOD_HANDLE targetMethodHnd = nullptr;
7244     GenTree*              qmarkNode       = nullptr;
7245     if (oper == GT_FTN_ADDR)
7246     {
7247         targetMethodHnd = targetMethod->gtFptrVal.gtFptrMethod;
7248     }
7249     else if (oper == GT_CALL && targetMethod->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_VIRTUAL_FUNC_PTR))
7250     {
7251         GenTree* handleNode = targetMethod->gtCall.gtCallArgs->Rest()->Rest()->Current();
7252
7253         if (handleNode->OperGet() == GT_CNS_INT)
7254         {
7255             // it's a ldvirtftn case, fetch the methodhandle off the helper for ldvirtftn. It's the 3rd arg
7256             targetMethodHnd = CORINFO_METHOD_HANDLE(handleNode->gtIntCon.gtCompileTimeHandle);
7257         }
7258         // Sometimes the argument to this is the result of a generic dictionary lookup, which shows
7259         // up as a GT_QMARK.
7260         else if (handleNode->OperGet() == GT_QMARK)
7261         {
7262             qmarkNode = handleNode;
7263         }
7264     }
7265     // Sometimes we don't call CORINFO_HELP_VIRTUAL_FUNC_PTR but instead just call
7266     // CORINFO_HELP_RUNTIMEHANDLE_METHOD directly.
7267     else if (oper == GT_QMARK)
7268     {
7269         qmarkNode = targetMethod;
7270     }
7271     if (qmarkNode)
7272     {
7273         noway_assert(qmarkNode->OperGet() == GT_QMARK);
7274         // The argument is actually a generic dictionary lookup.  For delegate creation it looks
7275         // like:
7276         // GT_QMARK
7277         //  GT_COLON
7278         //      op1 -> call
7279         //              Arg 1 -> token (has compile time handle)
7280         //      op2 -> lclvar
7281         //
7282         //
7283         // In this case I can find the token (which is a method handle) and that is the compile time
7284         // handle.
7285         noway_assert(qmarkNode->gtOp.gtOp2->OperGet() == GT_COLON);
7286         noway_assert(qmarkNode->gtOp.gtOp2->gtOp.gtOp1->OperGet() == GT_CALL);
7287         GenTreeCall* runtimeLookupCall = qmarkNode->gtOp.gtOp2->gtOp.gtOp1->AsCall();
7288
7289         // This could be any of CORINFO_HELP_RUNTIMEHANDLE_(METHOD|CLASS)(_LOG?)
7290         GenTree* tokenNode = runtimeLookupCall->gtCallArgs->gtOp.gtOp2->gtOp.gtOp1;
7291         noway_assert(tokenNode->OperGet() == GT_CNS_INT);
7292         targetMethodHnd = CORINFO_METHOD_HANDLE(tokenNode->gtIntCon.gtCompileTimeHandle);
7293     }
7294
7295 #ifdef FEATURE_READYTORUN_COMPILER
7296     if (opts.IsReadyToRun())
7297     {
7298         if (IsTargetAbi(CORINFO_CORERT_ABI))
7299         {
7300             if (ldftnToken != nullptr)
7301             {
7302                 GenTree*             thisPointer       = call->gtCallObjp;
7303                 GenTree*             targetObjPointers = call->gtCallArgs->Current();
7304                 GenTreeArgList*      helperArgs        = nullptr;
7305                 CORINFO_LOOKUP       pLookup;
7306                 CORINFO_CONST_LOOKUP entryPoint;
7307                 info.compCompHnd->getReadyToRunDelegateCtorHelper(ldftnToken, clsHnd, &pLookup);
7308                 if (!pLookup.lookupKind.needsRuntimeLookup)
7309                 {
7310                     helperArgs = gtNewArgList(thisPointer, targetObjPointers);
7311                     entryPoint = pLookup.constLookup;
7312                 }
7313                 else
7314                 {
7315                     assert(oper != GT_FTN_ADDR);
7316                     CORINFO_CONST_LOOKUP genericLookup;
7317                     info.compCompHnd->getReadyToRunHelper(ldftnToken, &pLookup.lookupKind,
7318                                                           CORINFO_HELP_READYTORUN_GENERIC_HANDLE, &genericLookup);
7319                     GenTree* ctxTree = getRuntimeContextTree(pLookup.lookupKind.runtimeLookupKind);
7320                     helperArgs       = gtNewArgList(thisPointer, targetObjPointers, ctxTree);
7321                     entryPoint       = genericLookup;
7322                 }
7323                 call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, helperArgs);
7324                 call->setEntryPoint(entryPoint);
7325             }
7326         }
7327         // ReadyToRun has this optimization for a non-virtual function pointers only for now.
7328         else if (oper == GT_FTN_ADDR)
7329         {
7330             GenTree*        thisPointer       = call->gtCallObjp;
7331             GenTree*        targetObjPointers = call->gtCallArgs->Current();
7332             GenTreeArgList* helperArgs        = gtNewArgList(thisPointer, targetObjPointers);
7333
7334             call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, helperArgs);
7335
7336             CORINFO_LOOKUP entryPoint;
7337             info.compCompHnd->getReadyToRunDelegateCtorHelper(ldftnToken, clsHnd, &entryPoint);
7338             assert(!entryPoint.lookupKind.needsRuntimeLookup);
7339             call->setEntryPoint(entryPoint.constLookup);
7340         }
7341     }
7342     else
7343 #endif
7344         if (targetMethodHnd != nullptr)
7345     {
7346         CORINFO_METHOD_HANDLE alternateCtor = nullptr;
7347         DelegateCtorArgs      ctorData;
7348         ctorData.pMethod = info.compMethodHnd;
7349         ctorData.pArg3   = nullptr;
7350         ctorData.pArg4   = nullptr;
7351         ctorData.pArg5   = nullptr;
7352
7353         alternateCtor = info.compCompHnd->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, &ctorData);
7354         if (alternateCtor != methHnd)
7355         {
7356             // we erase any inline info that may have been set for generics has it is not needed here,
7357             // and in fact it will pass the wrong info to the inliner code
7358             *ExactContextHnd = nullptr;
7359
7360             call->gtCallMethHnd = alternateCtor;
7361
7362             noway_assert(call->gtCallArgs->Rest()->Rest() == nullptr);
7363             GenTreeArgList* addArgs = nullptr;
7364             if (ctorData.pArg5)
7365             {
7366                 GenTree* arg5 = gtNewIconHandleNode(size_t(ctorData.pArg5), GTF_ICON_FTN_ADDR);
7367                 addArgs       = gtNewListNode(arg5, addArgs);
7368             }
7369             if (ctorData.pArg4)
7370             {
7371                 GenTree* arg4 = gtNewIconHandleNode(size_t(ctorData.pArg4), GTF_ICON_FTN_ADDR);
7372                 addArgs       = gtNewListNode(arg4, addArgs);
7373             }
7374             if (ctorData.pArg3)
7375             {
7376                 GenTree* arg3 = gtNewIconHandleNode(size_t(ctorData.pArg3), GTF_ICON_FTN_ADDR);
7377                 addArgs       = gtNewListNode(arg3, addArgs);
7378             }
7379             call->gtCallArgs->Rest()->Rest() = addArgs;
7380         }
7381     }
7382     return call;
7383 }
7384
7385 bool Compiler::fgCastNeeded(GenTree* tree, var_types toType)
7386 {
7387     //
7388     // If tree is a relop and we need an 4-byte integer
7389     //  then we never need to insert a cast
7390     //
7391     if ((tree->OperKind() & GTK_RELOP) && (genActualType(toType) == TYP_INT))
7392     {
7393         return false;
7394     }
7395
7396     var_types fromType;
7397
7398     //
7399     // Is the tree as GT_CAST or a GT_CALL ?
7400     //
7401     if (tree->OperGet() == GT_CAST)
7402     {
7403         fromType = tree->CastToType();
7404     }
7405     else if (tree->OperGet() == GT_CALL)
7406     {
7407         fromType = (var_types)tree->gtCall.gtReturnType;
7408     }
7409     else
7410     {
7411         fromType = tree->TypeGet();
7412     }
7413
7414     //
7415     // If both types are the same then an additional cast is not necessary
7416     //
7417     if (toType == fromType)
7418     {
7419         return false;
7420     }
7421     //
7422     // If the sign-ness of the two types are different then a cast is necessary
7423     //
7424     if (varTypeIsUnsigned(toType) != varTypeIsUnsigned(fromType))
7425     {
7426         return true;
7427     }
7428     //
7429     // If the from type is the same size or smaller then an additional cast is not necessary
7430     //
7431     if (genTypeSize(toType) >= genTypeSize(fromType))
7432     {
7433         return false;
7434     }
7435
7436     //
7437     // Looks like we will need the cast
7438     //
7439     return true;
7440 }
7441
7442 // If assigning to a local var, add a cast if the target is
7443 // marked as NormalizedOnStore. Returns true if any change was made
7444 GenTree* Compiler::fgDoNormalizeOnStore(GenTree* tree)
7445 {
7446     //
7447     // Only normalize the stores in the global morph phase
7448     //
7449     if (fgGlobalMorph)
7450     {
7451         noway_assert(tree->OperGet() == GT_ASG);
7452
7453         GenTree* op1 = tree->gtOp.gtOp1;
7454         GenTree* op2 = tree->gtOp.gtOp2;
7455
7456         if (op1->gtOper == GT_LCL_VAR && genActualType(op1->TypeGet()) == TYP_INT)
7457         {
7458             // Small-typed arguments and aliased locals are normalized on load.
7459             // Other small-typed locals are normalized on store.
7460             // If it is an assignment to one of the latter, insert the cast on RHS
7461             unsigned   varNum = op1->gtLclVarCommon.gtLclNum;
7462             LclVarDsc* varDsc = &lvaTable[varNum];
7463
7464             if (varDsc->lvNormalizeOnStore())
7465             {
7466                 noway_assert(op1->gtType <= TYP_INT);
7467                 op1->gtType = TYP_INT;
7468
7469                 if (fgCastNeeded(op2, varDsc->TypeGet()))
7470                 {
7471                     op2              = gtNewCastNode(TYP_INT, op2, false, varDsc->TypeGet());
7472                     tree->gtOp.gtOp2 = op2;
7473
7474                     // Propagate GTF_COLON_COND
7475                     op2->gtFlags |= (tree->gtFlags & GTF_COLON_COND);
7476                 }
7477             }
7478         }
7479     }
7480
7481     return tree;
7482 }
7483
7484 /*****************************************************************************
7485  *
7486  *  Mark whether the edge "srcBB -> dstBB" forms a loop that will always
7487  *  execute a call or not.
7488  */
7489
7490 inline void Compiler::fgLoopCallTest(BasicBlock* srcBB, BasicBlock* dstBB)
7491 {
7492     /* Bail if this is not a backward edge */
7493
7494     if (srcBB->bbNum < dstBB->bbNum)
7495     {
7496         return;
7497     }
7498
7499     /* Unless we already know that there is a loop without a call here ... */
7500
7501     if (!(dstBB->bbFlags & BBF_LOOP_CALL0))
7502     {
7503         /* Check whether there is a loop path that doesn't call */
7504
7505         if (optReachWithoutCall(dstBB, srcBB))
7506         {
7507             dstBB->bbFlags |= BBF_LOOP_CALL0;
7508             dstBB->bbFlags &= ~BBF_LOOP_CALL1;
7509         }
7510         else
7511         {
7512             dstBB->bbFlags |= BBF_LOOP_CALL1;
7513         }
7514     }
7515     // if this loop will always call, then we can omit the GC Poll
7516     if ((GCPOLL_NONE != opts.compGCPollType) && (dstBB->bbFlags & BBF_LOOP_CALL1))
7517     {
7518         srcBB->bbFlags &= ~BBF_NEEDS_GCPOLL;
7519     }
7520 }
7521
7522 /*****************************************************************************
7523  *
7524  *  Mark which loops are guaranteed to execute a call.
7525  */
7526
7527 void Compiler::fgLoopCallMark()
7528 {
7529     BasicBlock* block;
7530
7531     /* If we've already marked all the block, bail */
7532
7533     if (fgLoopCallMarked)
7534     {
7535         return;
7536     }
7537
7538     fgLoopCallMarked = true;
7539
7540     /* Walk the blocks, looking for backward edges */
7541
7542     for (block = fgFirstBB; block; block = block->bbNext)
7543     {
7544         switch (block->bbJumpKind)
7545         {
7546             case BBJ_COND:
7547             case BBJ_CALLFINALLY:
7548             case BBJ_ALWAYS:
7549             case BBJ_EHCATCHRET:
7550                 fgLoopCallTest(block, block->bbJumpDest);
7551                 break;
7552
7553             case BBJ_SWITCH:
7554
7555                 unsigned jumpCnt;
7556                 jumpCnt = block->bbJumpSwt->bbsCount;
7557                 BasicBlock** jumpPtr;
7558                 jumpPtr = block->bbJumpSwt->bbsDstTab;
7559
7560                 do
7561                 {
7562                     fgLoopCallTest(block, *jumpPtr);
7563                 } while (++jumpPtr, --jumpCnt);
7564
7565                 break;
7566
7567             default:
7568                 break;
7569         }
7570     }
7571 }
7572
7573 /*****************************************************************************
7574  *
7575  *  Note the fact that the given block is a loop header.
7576  */
7577
7578 inline void Compiler::fgMarkLoopHead(BasicBlock* block)
7579 {
7580 #ifdef DEBUG
7581     if (verbose)
7582     {
7583         printf("fgMarkLoopHead: Checking loop head block BB%02u: ", block->bbNum);
7584     }
7585 #endif
7586
7587     /* Have we decided to generate fully interruptible code already? */
7588
7589     if (genInterruptible)
7590     {
7591 #ifdef DEBUG
7592         if (verbose)
7593         {
7594             printf("method is already fully interruptible\n");
7595         }
7596 #endif
7597         return;
7598     }
7599
7600     /* Is the loop head block known to execute a method call? */
7601
7602     if (block->bbFlags & BBF_GC_SAFE_POINT)
7603     {
7604 #ifdef DEBUG
7605         if (verbose)
7606         {
7607             printf("this block will execute a call\n");
7608         }
7609 #endif
7610         // single block loops that contain GC safe points don't need polls.
7611         block->bbFlags &= ~BBF_NEEDS_GCPOLL;
7612         return;
7613     }
7614
7615     /* Are dominator sets available? */
7616
7617     if (fgDomsComputed)
7618     {
7619         /* Make sure that we know which loops will always execute calls */
7620
7621         if (!fgLoopCallMarked)
7622         {
7623             fgLoopCallMark();
7624         }
7625
7626         /* Will every trip through our loop execute a call? */
7627
7628         if (block->bbFlags & BBF_LOOP_CALL1)
7629         {
7630 #ifdef DEBUG
7631             if (verbose)
7632             {
7633                 printf("this block dominates a block that will execute a call\n");
7634             }
7635 #endif
7636             return;
7637         }
7638     }
7639
7640     /*
7641      *  We have to make this method fully interruptible since we can not
7642      *  ensure that this loop will execute a call every time it loops.
7643      *
7644      *  We'll also need to generate a full register map for this method.
7645      */
7646
7647     assert(!codeGen->isGCTypeFixed());
7648
7649     if (!compCanEncodePtrArgCntMax())
7650     {
7651 #ifdef DEBUG
7652         if (verbose)
7653         {
7654             printf("a callsite with more than 1023 pushed args exists\n");
7655         }
7656 #endif
7657         return;
7658     }
7659
7660 #ifdef DEBUG
7661     if (verbose)
7662     {
7663         printf("no guaranteed callsite exits, marking method as fully interruptible\n");
7664     }
7665 #endif
7666
7667     // only enable fully interruptible code for if we're hijacking.
7668     if (GCPOLL_NONE == opts.compGCPollType)
7669     {
7670         genInterruptible = true;
7671     }
7672 }
7673
7674 GenTree* Compiler::fgGetCritSectOfStaticMethod()
7675 {
7676     noway_assert(!compIsForInlining());
7677
7678     noway_assert(info.compIsStatic); // This method should only be called for static methods.
7679
7680     GenTree* tree = nullptr;
7681
7682     CORINFO_LOOKUP_KIND kind = info.compCompHnd->getLocationOfThisType(info.compMethodHnd);
7683
7684     if (!kind.needsRuntimeLookup)
7685     {
7686         void *critSect = nullptr, **pCrit = nullptr;
7687         critSect = info.compCompHnd->getMethodSync(info.compMethodHnd, (void**)&pCrit);
7688         noway_assert((!critSect) != (!pCrit));
7689
7690         tree = gtNewIconEmbHndNode(critSect, pCrit, GTF_ICON_METHOD_HDL, info.compMethodHnd);
7691     }
7692     else
7693     {
7694         // Collectible types requires that for shared generic code, if we use the generic context paramter
7695         // that we report it. (This is a conservative approach, we could detect some cases particularly when the
7696         // context parameter is this that we don't need the eager reporting logic.)
7697         lvaGenericsContextUseCount++;
7698
7699         switch (kind.runtimeLookupKind)
7700         {
7701             case CORINFO_LOOKUP_THISOBJ:
7702             {
7703                 noway_assert(!"Should never get this for static method.");
7704                 break;
7705             }
7706
7707             case CORINFO_LOOKUP_CLASSPARAM:
7708             {
7709                 // In this case, the hidden param is the class handle.
7710                 tree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL);
7711                 break;
7712             }
7713
7714             case CORINFO_LOOKUP_METHODPARAM:
7715             {
7716                 // In this case, the hidden param is the method handle.
7717                 tree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL);
7718                 // Call helper CORINFO_HELP_GETCLASSFROMMETHODPARAM to get the class handle
7719                 // from the method handle.
7720                 tree = gtNewHelperCallNode(CORINFO_HELP_GETCLASSFROMMETHODPARAM, TYP_I_IMPL, gtNewArgList(tree));
7721                 break;
7722             }
7723
7724             default:
7725             {
7726                 noway_assert(!"Unknown LOOKUP_KIND");
7727                 break;
7728             }
7729         }
7730
7731         noway_assert(tree); // tree should now contain the CORINFO_CLASS_HANDLE for the exact class.
7732
7733         // Given the class handle, get the pointer to the Monitor.
7734         tree = gtNewHelperCallNode(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, TYP_I_IMPL, gtNewArgList(tree));
7735     }
7736
7737     noway_assert(tree);
7738     return tree;
7739 }
7740
7741 #if FEATURE_EH_FUNCLETS
7742
7743 /*****************************************************************************
7744  *
7745  *  Add monitor enter/exit calls for synchronized methods, and a try/fault
7746  *  to ensure the 'exit' is called if the 'enter' was successful. On x86, we
7747  *  generate monitor enter/exit calls and tell the VM the code location of
7748  *  these calls. When an exception occurs between those locations, the VM
7749  *  automatically releases the lock. For non-x86 platforms, the JIT is
7750  *  responsible for creating a try/finally to protect the monitor enter/exit,
7751  *  and the VM doesn't need to know anything special about the method during
7752  *  exception processing -- it's just a normal try/finally.
7753  *
7754  *  We generate the following code:
7755  *
7756  *      void Foo()
7757  *      {
7758  *          unsigned byte acquired = 0;
7759  *          try {
7760  *              JIT_MonEnterWorker(<lock object>, &acquired);
7761  *
7762  *              *** all the preexisting user code goes here ***
7763  *
7764  *              JIT_MonExitWorker(<lock object>, &acquired);
7765  *          } fault {
7766  *              JIT_MonExitWorker(<lock object>, &acquired);
7767  *         }
7768  *      L_return:
7769  *         ret
7770  *      }
7771  *
7772  *  If the lock is actually acquired, then the 'acquired' variable is set to 1
7773  *  by the helper call. During normal exit, the finally is called, 'acquired'
7774  *  is 1, and the lock is released. If an exception occurs before the lock is
7775  *  acquired, but within the 'try' (extremely unlikely, but possible), 'acquired'
7776  *  will be 0, and the monitor exit call will quickly return without attempting
7777  *  to release the lock. Otherwise, 'acquired' will be 1, and the lock will be
7778  *  released during exception processing.
7779  *
7780  *  For synchronized methods, we generate a single return block.
7781  *  We can do this without creating additional "step" blocks because "ret" blocks
7782  *  must occur at the top-level (of the original code), not nested within any EH
7783  *  constructs. From the CLI spec, 12.4.2.8.2.3 "ret": "Shall not be enclosed in any
7784  *  protected block, filter, or handler." Also, 3.57: "The ret instruction cannot be
7785  *  used to transfer control out of a try, filter, catch, or finally block. From within
7786  *  a try or catch, use the leave instruction with a destination of a ret instruction
7787  *  that is outside all enclosing exception blocks."
7788  *
7789  *  In addition, we can add a "fault" at the end of a method and be guaranteed that no
7790  *  control falls through. From the CLI spec, section 12.4 "Control flow": "Control is not
7791  *  permitted to simply fall through the end of a method. All paths shall terminate with one
7792  *  of these instructions: ret, throw, jmp, or (tail. followed by call, calli, or callvirt)."
7793  *
7794  *  We only need to worry about "ret" and "throw", as the CLI spec prevents any other
7795  *  alternatives. Section 15.4.3.3 "Implementation information" states about exiting
7796  *  synchronized methods: "Exiting a synchronized method using a tail. call shall be
7797  *  implemented as though the tail. had not been specified." Section 3.37 "jmp" states:
7798  *  "The jmp instruction cannot be used to transferred control out of a try, filter,
7799  *  catch, fault or finally block; or out of a synchronized region." And, "throw" will
7800  *  be handled naturally; no additional work is required.
7801  */
7802
7803 void Compiler::fgAddSyncMethodEnterExit()
7804 {
7805     assert((info.compFlags & CORINFO_FLG_SYNCH) != 0);
7806
7807     // We need to do this transformation before funclets are created.
7808     assert(!fgFuncletsCreated);
7809
7810     // Assume we don't need to update the bbPreds lists.
7811     assert(!fgComputePredsDone);
7812
7813 #if !FEATURE_EH
7814     // If we don't support EH, we can't add the EH needed by synchronized methods.
7815     // Of course, we could simply ignore adding the EH constructs, since we don't
7816     // support exceptions being thrown in this mode, but we would still need to add
7817     // the monitor enter/exit, and that doesn't seem worth it for this minor case.
7818     // By the time EH is working, we can just enable the whole thing.
7819     NYI("No support for synchronized methods");
7820 #endif // !FEATURE_EH
7821
7822     // Create a scratch first BB where we can put the new variable initialization.
7823     // Don't put the scratch BB in the protected region.
7824
7825     fgEnsureFirstBBisScratch();
7826
7827     // Create a block for the start of the try region, where the monitor enter call
7828     // will go.
7829
7830     assert(fgFirstBB->bbFallsThrough());
7831
7832     BasicBlock* tryBegBB  = fgNewBBafter(BBJ_NONE, fgFirstBB, false);
7833     BasicBlock* tryNextBB = tryBegBB->bbNext;
7834     BasicBlock* tryLastBB = fgLastBB;
7835
7836     // If we have profile data the new block will inherit the next block's weight
7837     if (tryNextBB->hasProfileWeight())
7838     {
7839         tryBegBB->inheritWeight(tryNextBB);
7840     }
7841
7842     // Create a block for the fault.
7843
7844     assert(!tryLastBB->bbFallsThrough());
7845     BasicBlock* faultBB = fgNewBBafter(BBJ_EHFINALLYRET, tryLastBB, false);
7846
7847     assert(tryLastBB->bbNext == faultBB);
7848     assert(faultBB->bbNext == nullptr);
7849     assert(faultBB == fgLastBB);
7850
7851     { // Scope the EH region creation
7852
7853         // Add the new EH region at the end, since it is the least nested,
7854         // and thus should be last.
7855
7856         EHblkDsc* newEntry;
7857         unsigned  XTnew = compHndBBtabCount;
7858
7859         newEntry = fgAddEHTableEntry(XTnew);
7860
7861         // Initialize the new entry
7862
7863         newEntry->ebdHandlerType = EH_HANDLER_FAULT;
7864
7865         newEntry->ebdTryBeg  = tryBegBB;
7866         newEntry->ebdTryLast = tryLastBB;
7867
7868         newEntry->ebdHndBeg  = faultBB;
7869         newEntry->ebdHndLast = faultBB;
7870
7871         newEntry->ebdTyp = 0; // unused for fault
7872
7873         newEntry->ebdEnclosingTryIndex = EHblkDsc::NO_ENCLOSING_INDEX;
7874         newEntry->ebdEnclosingHndIndex = EHblkDsc::NO_ENCLOSING_INDEX;
7875
7876         newEntry->ebdTryBegOffset    = tryBegBB->bbCodeOffs;
7877         newEntry->ebdTryEndOffset    = tryLastBB->bbCodeOffsEnd;
7878         newEntry->ebdFilterBegOffset = 0;
7879         newEntry->ebdHndBegOffset    = 0; // handler doesn't correspond to any IL
7880         newEntry->ebdHndEndOffset    = 0; // handler doesn't correspond to any IL
7881
7882         // Set some flags on the new region. This is the same as when we set up
7883         // EH regions in fgFindBasicBlocks(). Note that the try has no enclosing
7884         // handler, and the fault has no enclosing try.
7885
7886         tryBegBB->bbFlags |= BBF_HAS_LABEL | BBF_DONT_REMOVE | BBF_TRY_BEG | BBF_IMPORTED;
7887
7888         faultBB->bbFlags |= BBF_HAS_LABEL | BBF_DONT_REMOVE | BBF_IMPORTED;
7889         faultBB->bbCatchTyp = BBCT_FAULT;
7890
7891         tryBegBB->setTryIndex(XTnew);
7892         tryBegBB->clearHndIndex();
7893
7894         faultBB->clearTryIndex();
7895         faultBB->setHndIndex(XTnew);
7896
7897         // Walk the user code blocks and set all blocks that don't already have a try handler
7898         // to point to the new try handler.
7899
7900         BasicBlock* tmpBB;
7901         for (tmpBB = tryBegBB->bbNext; tmpBB != faultBB; tmpBB = tmpBB->bbNext)
7902         {
7903             if (!tmpBB->hasTryIndex())
7904             {
7905                 tmpBB->setTryIndex(XTnew);
7906             }
7907         }
7908
7909         // Walk the EH table. Make every EH entry that doesn't already have an enclosing
7910         // try index mark this new entry as their enclosing try index.
7911
7912         unsigned  XTnum;
7913         EHblkDsc* HBtab;
7914
7915         for (XTnum = 0, HBtab = compHndBBtab; XTnum < XTnew; XTnum++, HBtab++)
7916         {
7917             if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
7918             {
7919                 HBtab->ebdEnclosingTryIndex =
7920                     (unsigned short)XTnew; // This EH region wasn't previously nested, but now it is.
7921             }
7922         }
7923
7924 #ifdef DEBUG
7925         if (verbose)
7926         {
7927             JITDUMP("Synchronized method - created additional EH descriptor EH#%u for try/fault wrapping monitor "
7928                     "enter/exit\n",
7929                     XTnew);
7930             fgDispBasicBlocks();
7931             fgDispHandlerTab();
7932         }
7933
7934         fgVerifyHandlerTab();
7935 #endif // DEBUG
7936     }
7937
7938     // Create a 'monitor acquired' boolean (actually, an unsigned byte: 1 = acquired, 0 = not acquired).
7939
7940     var_types typeMonAcquired = TYP_UBYTE;
7941     this->lvaMonAcquired      = lvaGrabTemp(true DEBUGARG("Synchronized method monitor acquired boolean"));
7942
7943     lvaTable[lvaMonAcquired].lvType = typeMonAcquired;
7944
7945     { // Scope the variables of the variable initialization
7946
7947         // Initialize the 'acquired' boolean.
7948
7949         GenTree* zero     = gtNewZeroConNode(genActualType(typeMonAcquired));
7950         GenTree* varNode  = gtNewLclvNode(lvaMonAcquired, typeMonAcquired);
7951         GenTree* initNode = gtNewAssignNode(varNode, zero);
7952
7953         fgInsertStmtAtEnd(fgFirstBB, initNode);
7954
7955 #ifdef DEBUG
7956         if (verbose)
7957         {
7958             printf("\nSynchronized method - Add 'acquired' initialization in first block %s\n",
7959                    fgFirstBB->dspToString());
7960             gtDispTree(initNode);
7961             printf("\n");
7962         }
7963 #endif
7964     }
7965
7966     // Make a copy of the 'this' pointer to be used in the handler so it does not inhibit enregistration
7967     // of all uses of the variable.
7968     unsigned lvaCopyThis = 0;
7969     if (!info.compIsStatic)
7970     {
7971         lvaCopyThis                  = lvaGrabTemp(true DEBUGARG("Synchronized method monitor acquired boolean"));
7972         lvaTable[lvaCopyThis].lvType = TYP_REF;
7973
7974         GenTree* thisNode = gtNewLclvNode(info.compThisArg, TYP_REF);
7975         GenTree* copyNode = gtNewLclvNode(lvaCopyThis, TYP_REF);
7976         GenTree* initNode = gtNewAssignNode(copyNode, thisNode);
7977
7978         fgInsertStmtAtEnd(tryBegBB, initNode);
7979     }
7980
7981     fgCreateMonitorTree(lvaMonAcquired, info.compThisArg, tryBegBB, true /*enter*/);
7982
7983     // exceptional case
7984     fgCreateMonitorTree(lvaMonAcquired, lvaCopyThis, faultBB, false /*exit*/);
7985
7986     // non-exceptional cases
7987     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
7988     {
7989         if (block->bbJumpKind == BBJ_RETURN)
7990         {
7991             fgCreateMonitorTree(lvaMonAcquired, info.compThisArg, block, false /*exit*/);
7992         }
7993     }
7994 }
7995
7996 // fgCreateMonitorTree: Create tree to execute a monitor enter or exit operation for synchronized methods
7997 //    lvaMonAcquired: lvaNum of boolean variable that tracks if monitor has been acquired.
7998 //    lvaThisVar: lvaNum of variable being used as 'this' pointer, may not be the original one.  Is only used for
7999 //    nonstatic methods
8000 //    block: block to insert the tree in.  It is inserted at the end or in the case of a return, immediately before the
8001 //    GT_RETURN
8002 //    enter: whether to create a monitor enter or exit
8003
8004 GenTree* Compiler::fgCreateMonitorTree(unsigned lvaMonAcquired, unsigned lvaThisVar, BasicBlock* block, bool enter)
8005 {
8006     // Insert the expression "enter/exitCrit(this, &acquired)" or "enter/exitCrit(handle, &acquired)"
8007
8008     var_types typeMonAcquired = TYP_UBYTE;
8009     GenTree*  varNode         = gtNewLclvNode(lvaMonAcquired, typeMonAcquired);
8010     GenTree*  varAddrNode     = gtNewOperNode(GT_ADDR, TYP_BYREF, varNode);
8011     GenTree*  tree;
8012
8013     if (info.compIsStatic)
8014     {
8015         tree = fgGetCritSectOfStaticMethod();
8016         tree = gtNewHelperCallNode(enter ? CORINFO_HELP_MON_ENTER_STATIC : CORINFO_HELP_MON_EXIT_STATIC, TYP_VOID,
8017                                    gtNewArgList(tree, varAddrNode));
8018     }
8019     else
8020     {
8021         tree = gtNewLclvNode(lvaThisVar, TYP_REF);
8022         tree = gtNewHelperCallNode(enter ? CORINFO_HELP_MON_ENTER : CORINFO_HELP_MON_EXIT, TYP_VOID,
8023                                    gtNewArgList(tree, varAddrNode));
8024     }
8025
8026 #ifdef DEBUG
8027     if (verbose)
8028     {
8029         printf("\nSynchronized method - Add monitor %s call to block %s\n", enter ? "enter" : "exit",
8030                block->dspToString());
8031         gtDispTree(tree);
8032         printf("\n");
8033     }
8034 #endif
8035
8036     if (block->bbJumpKind == BBJ_RETURN && block->lastStmt()->gtStmtExpr->gtOper == GT_RETURN)
8037     {
8038         GenTree* retNode = block->lastStmt()->gtStmtExpr;
8039         GenTree* retExpr = retNode->gtOp.gtOp1;
8040
8041         if (retExpr != nullptr)
8042         {
8043             // have to insert this immediately before the GT_RETURN so we transform:
8044             // ret(...) ->
8045             // ret(comma(comma(tmp=...,call mon_exit), tmp)
8046             //
8047             //
8048             // Before morph stage, it is possible to have a case of GT_RETURN(TYP_LONG, op1) where op1's type is
8049             // TYP_STRUCT (of 8-bytes) and op1 is call node. See the big comment block in impReturnInstruction()
8050             // for details for the case where info.compRetType is not the same as info.compRetNativeType.  For
8051             // this reason pass compMethodInfo->args.retTypeClass which is guaranteed to be a valid class handle
8052             // if the return type is a value class.  Note that fgInsertCommFormTemp() in turn uses this class handle
8053             // if the type of op1 is TYP_STRUCT to perform lvaSetStruct() on the new temp that is created, which
8054             // in turn passes it to VM to know the size of value type.
8055             GenTree* temp = fgInsertCommaFormTemp(&retNode->gtOp.gtOp1, info.compMethodInfo->args.retTypeClass);
8056
8057             GenTree* lclVar                 = retNode->gtOp.gtOp1->gtOp.gtOp2;
8058             retNode->gtOp.gtOp1->gtOp.gtOp2 = gtNewOperNode(GT_COMMA, retExpr->TypeGet(), tree, lclVar);
8059         }
8060         else
8061         {
8062             // Insert this immediately before the GT_RETURN
8063             fgInsertStmtNearEnd(block, tree);
8064         }
8065     }
8066     else
8067     {
8068         fgInsertStmtAtEnd(block, tree);
8069     }
8070
8071     return tree;
8072 }
8073
8074 // Convert a BBJ_RETURN block in a synchronized method to a BBJ_ALWAYS.
8075 // We've previously added a 'try' block around the original program code using fgAddSyncMethodEnterExit().
8076 // Thus, we put BBJ_RETURN blocks inside a 'try'. In IL this is illegal. Instead, we would
8077 // see a 'leave' inside a 'try' that would get transformed into BBJ_CALLFINALLY/BBJ_ALWAYS blocks
8078 // during importing, and the BBJ_ALWAYS would point at an outer block with the BBJ_RETURN.
8079 // Here, we mimic some of the logic of importing a LEAVE to get the same effect for synchronized methods.
8080 void Compiler::fgConvertSyncReturnToLeave(BasicBlock* block)
8081 {
8082     assert(!fgFuncletsCreated);
8083     assert(info.compFlags & CORINFO_FLG_SYNCH);
8084     assert(genReturnBB != nullptr);
8085     assert(genReturnBB != block);
8086     assert(fgReturnCount <= 1); // We have a single return for synchronized methods
8087     assert(block->bbJumpKind == BBJ_RETURN);
8088     assert((block->bbFlags & BBF_HAS_JMP) == 0);
8089     assert(block->hasTryIndex());
8090     assert(!block->hasHndIndex());
8091     assert(compHndBBtabCount >= 1);
8092
8093     unsigned tryIndex = block->getTryIndex();
8094     assert(tryIndex == compHndBBtabCount - 1); // The BBJ_RETURN must be at the top-level before we inserted the
8095                                                // try/finally, which must be the last EH region.
8096
8097     EHblkDsc* ehDsc = ehGetDsc(tryIndex);
8098     assert(ehDsc->ebdEnclosingTryIndex ==
8099            EHblkDsc::NO_ENCLOSING_INDEX); // There are no enclosing regions of the BBJ_RETURN block
8100     assert(ehDsc->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
8101
8102     // Convert the BBJ_RETURN to BBJ_ALWAYS, jumping to genReturnBB.
8103     block->bbJumpKind = BBJ_ALWAYS;
8104     block->bbJumpDest = genReturnBB;
8105     block->bbJumpDest->bbRefs++;
8106
8107 #ifdef DEBUG
8108     if (verbose)
8109     {
8110         printf("Synchronized method - convert block BB%02u to BBJ_ALWAYS [targets BB%02u]\n", block->bbNum,
8111                block->bbJumpDest->bbNum);
8112     }
8113 #endif
8114 }
8115
8116 #endif // FEATURE_EH_FUNCLETS
8117
8118 //------------------------------------------------------------------------
8119 // fgAddReversePInvokeEnterExit: Add enter/exit calls for reverse PInvoke methods
8120 //
8121 // Arguments:
8122 //      None.
8123 //
8124 // Return Value:
8125 //      None.
8126
8127 void Compiler::fgAddReversePInvokeEnterExit()
8128 {
8129     assert(opts.IsReversePInvoke());
8130
8131     lvaReversePInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Reverse Pinvoke FrameVar"));
8132
8133     LclVarDsc* varDsc   = &lvaTable[lvaReversePInvokeFrameVar];
8134     varDsc->lvType      = TYP_BLK;
8135     varDsc->lvExactSize = eeGetEEInfo()->sizeOfReversePInvokeFrame;
8136
8137     GenTree* tree;
8138
8139     // Add enter pinvoke exit callout at the start of prolog
8140
8141     tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));
8142
8143     tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, TYP_VOID, gtNewArgList(tree));
8144
8145     fgEnsureFirstBBisScratch();
8146
8147     fgInsertStmtAtBeg(fgFirstBB, tree);
8148
8149 #ifdef DEBUG
8150     if (verbose)
8151     {
8152         printf("\nReverse PInvoke method - Add reverse pinvoke enter in first basic block %s\n",
8153                fgFirstBB->dspToString());
8154         gtDispTree(tree);
8155         printf("\n");
8156     }
8157 #endif
8158
8159     // Add reverse pinvoke exit callout at the end of epilog
8160
8161     tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));
8162
8163     tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, TYP_VOID, gtNewArgList(tree));
8164
8165     assert(genReturnBB != nullptr);
8166
8167     fgInsertStmtNearEnd(genReturnBB, tree);
8168
8169 #ifdef DEBUG
8170     if (verbose)
8171     {
8172         printf("\nReverse PInvoke method - Add reverse pinvoke exit in return basic block %s\n",
8173                genReturnBB->dspToString());
8174         gtDispTree(tree);
8175         printf("\n");
8176     }
8177 #endif
8178 }
8179
8180 /*****************************************************************************
8181  *
8182  *  Return 'true' if there is more than one BBJ_RETURN block.
8183  */
8184
8185 bool Compiler::fgMoreThanOneReturnBlock()
8186 {
8187     unsigned retCnt = 0;
8188
8189     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
8190     {
8191         if (block->bbJumpKind == BBJ_RETURN)
8192         {
8193             retCnt++;
8194             if (retCnt > 1)
8195             {
8196                 return true;
8197             }
8198         }
8199     }
8200
8201     return false;
8202 }
8203
8204 namespace
8205 {
8206 // Define a helper class for merging return blocks (which we do when the input has
8207 // more than the limit for this configuration).
8208 //
8209 // Notes: sets fgReturnCount, genReturnBB, and genReturnLocal.
8210 class MergedReturns
8211 {
8212 public:
8213 #ifdef JIT32_GCENCODER
8214
8215     // X86 GC encoding has a hard limit of SET_EPILOGCNT_MAX epilogs.
8216     const static unsigned ReturnCountHardLimit = SET_EPILOGCNT_MAX;
8217 #else  // JIT32_GCENCODER
8218
8219     // We currently apply a hard limit of '4' to all other targets (see
8220     // the other uses of SET_EPILOGCNT_MAX), though it would be good
8221     // to revisit that decision based on CQ analysis.
8222     const static unsigned ReturnCountHardLimit = 4;
8223 #endif // JIT32_GCENCODER
8224
8225 private:
8226     Compiler* comp;
8227
8228     // As we discover returns, we'll record them in `returnBlocks`, until
8229     // the limit is reached, at which point we'll keep track of the merged
8230     // return blocks in `returnBlocks`.
8231     BasicBlock* returnBlocks[ReturnCountHardLimit];
8232
8233     // Each constant value returned gets its own merged return block that
8234     // returns that constant (up to the limit on number of returns); in
8235     // `returnConstants` we track the constant values returned by these
8236     // merged constant return blocks.
8237     INT64 returnConstants[ReturnCountHardLimit];
8238
8239     // Indicators of where in the lexical block list we'd like to place
8240     // each constant return block.
8241     BasicBlock* insertionPoints[ReturnCountHardLimit];
8242
8243     // Number of return blocks allowed
8244     PhasedVar<unsigned> maxReturns;
8245
8246     // Flag to keep track of when we've hit the limit of returns and are
8247     // actively merging returns together.
8248     bool mergingReturns = false;
8249
8250 public:
8251     MergedReturns(Compiler* comp) : comp(comp)
8252     {
8253         comp->fgReturnCount = 0;
8254     }
8255
8256     void SetMaxReturns(unsigned value)
8257     {
8258         maxReturns = value;
8259         maxReturns.MarkAsReadOnly();
8260     }
8261
8262     //------------------------------------------------------------------------
8263     // Record: Make note of a return block in the input program.
8264     //
8265     // Arguments:
8266     //    returnBlock - Block in the input that has jump kind BBJ_RETURN
8267     //
8268     // Notes:
8269     //    Updates fgReturnCount appropriately, and generates a merged return
8270     //    block if necessary.  If a constant merged return block is used,
8271     //    `returnBlock` is rewritten to jump to it.  If a non-constant return
8272     //    block is used, `genReturnBB` is set to that block, and `genReturnLocal`
8273     //    is set to the lclvar that it returns; morph will need to rewrite
8274     //    `returnBlock` to set the local and jump to the return block in such
8275     //    cases, which it will do after some key transformations like rewriting
8276     //    tail calls and calls that return to hidden buffers.  In either of these
8277     //    cases, `fgReturnCount` and the merged return block's profile information
8278     //    will be updated to reflect or anticipate the rewrite of `returnBlock`.
8279     //
8280     void Record(BasicBlock* returnBlock)
8281     {
8282         // Add this return to our tally
8283         unsigned oldReturnCount = comp->fgReturnCount++;
8284
8285         if (!mergingReturns)
8286         {
8287             if (oldReturnCount < maxReturns)
8288             {
8289                 // No need to merge just yet; simply record this return.
8290                 returnBlocks[oldReturnCount] = returnBlock;
8291                 return;
8292             }
8293
8294             // We'e reached our threshold
8295             mergingReturns = true;
8296
8297             // Merge any returns we've already identified
8298             for (unsigned i = 0, searchLimit = 0; i < oldReturnCount; ++i)
8299             {
8300                 BasicBlock* mergedReturnBlock = Merge(returnBlocks[i], searchLimit);
8301                 if (returnBlocks[searchLimit] == mergedReturnBlock)
8302                 {
8303                     // We've added a new block to the searchable set
8304                     ++searchLimit;
8305                 }
8306             }
8307         }
8308
8309         // We have too many returns, so merge this one in.
8310         // Search limit is new return count minus one (to exclude this block).
8311         unsigned searchLimit = comp->fgReturnCount - 1;
8312         Merge(returnBlock, searchLimit);
8313     }
8314
8315     //------------------------------------------------------------------------
8316     // EagerCreate: Force creation of a non-constant merged return block `genReturnBB`.
8317     //
8318     // Return Value:
8319     //    The newly-created block which returns `genReturnLocal`.
8320     //
8321     BasicBlock* EagerCreate()
8322     {
8323         mergingReturns = true;
8324         return Merge(nullptr, 0);
8325     }
8326
8327     //------------------------------------------------------------------------
8328     // PlaceReturns: Move any generated const return blocks to an appropriate
8329     //     spot in the lexical block list.
8330     //
8331     // Notes:
8332     //    The goal is to set things up favorably for a reasonable layout without
8333     //    putting too much burden on fgReorderBlocks; in particular, since that
8334     //    method doesn't (currently) shuffle non-profile, non-rare code to create
8335     //    fall-through and reduce gotos, this method places each const return
8336     //    block immediately after its last predecessor, so that the flow from
8337     //    there to it can become fallthrough without requiring any motion to be
8338     //    performed by fgReorderBlocks.
8339     //
8340     void PlaceReturns()
8341     {
8342         if (!mergingReturns)
8343         {
8344             // No returns generated => no returns to place.
8345             return;
8346         }
8347
8348         for (unsigned index = 0; index < comp->fgReturnCount; ++index)
8349         {
8350             BasicBlock* returnBlock    = returnBlocks[index];
8351             BasicBlock* genReturnBlock = comp->genReturnBB;
8352             if (returnBlock == genReturnBlock)
8353             {
8354                 continue;
8355             }
8356
8357             BasicBlock* insertionPoint = insertionPoints[index];
8358             assert(insertionPoint != nullptr);
8359
8360             comp->fgUnlinkBlock(returnBlock);
8361             comp->fgMoveBlocksAfter(returnBlock, returnBlock, insertionPoint);
8362             // Treat the merged return block as belonging to the same EH region
8363             // as the insertion point block, to make sure we don't break up
8364             // EH regions; since returning a constant won't throw, this won't
8365             // affect program behavior.
8366             comp->fgExtendEHRegionAfter(insertionPoint);
8367         }
8368     }
8369
8370 private:
8371     //------------------------------------------------------------------------
8372     // CreateReturnBB: Create a basic block to serve as a merged return point, stored to
8373     //    `returnBlocks` at the given index, and optionally returning the given constant.
8374     //
8375     // Arguments:
8376     //    index - Index into `returnBlocks` to store the new block into.
8377     //    returnConst - Constant that the new block should return; may be nullptr to
8378     //      indicate that the new merged return is for the non-constant case, in which
8379     //      case, if the method's return type is non-void, `comp->genReturnLocal` will
8380     //      be initialized to a new local of the appropriate type, and the new block will
8381     //      return it.
8382     //
8383     // Return Value:
8384     //    The new merged return block.
8385     //
8386     BasicBlock* CreateReturnBB(unsigned index, GenTreeIntConCommon* returnConst = nullptr)
8387     {
8388         BasicBlock* newReturnBB = comp->fgNewBBinRegion(BBJ_RETURN);
8389         newReturnBB->bbRefs     = 1; // bbRefs gets update later, for now it should be 1
8390         comp->fgReturnCount++;
8391
8392         newReturnBB->bbFlags |= BBF_INTERNAL;
8393
8394         noway_assert(newReturnBB->bbNext == nullptr);
8395
8396 #ifdef DEBUG
8397         if (comp->verbose)
8398         {
8399             printf("\n newReturnBB [BB%02u] created\n", newReturnBB->bbNum);
8400         }
8401 #endif
8402
8403         // We have profile weight, the weight is zero, and the block is run rarely,
8404         // until we prove otherwise by merging other returns into this one.
8405         newReturnBB->bbFlags |= (BBF_PROF_WEIGHT | BBF_RUN_RARELY);
8406         newReturnBB->bbWeight = 0;
8407
8408         GenTree* returnExpr;
8409
8410         if (returnConst != nullptr)
8411         {
8412             returnExpr             = comp->gtNewOperNode(GT_RETURN, returnConst->gtType, returnConst);
8413             returnConstants[index] = returnConst->IntegralValue();
8414         }
8415         else if (comp->compMethodHasRetVal())
8416         {
8417             // There is a return value, so create a temp for it.  Real returns will store the value in there and
8418             // it'll be reloaded by the single return.
8419             unsigned returnLocalNum   = comp->lvaGrabTemp(true DEBUGARG("Single return block return value"));
8420             comp->genReturnLocal      = returnLocalNum;
8421             LclVarDsc& returnLocalDsc = comp->lvaTable[returnLocalNum];
8422
8423             if (comp->compMethodReturnsNativeScalarType())
8424             {
8425                 returnLocalDsc.lvType = genActualType(comp->info.compRetNativeType);
8426             }
8427             else if (comp->compMethodReturnsRetBufAddr())
8428             {
8429                 returnLocalDsc.lvType = TYP_BYREF;
8430             }
8431             else if (comp->compMethodReturnsMultiRegRetType())
8432             {
8433                 returnLocalDsc.lvType = TYP_STRUCT;
8434                 comp->lvaSetStruct(returnLocalNum, comp->info.compMethodInfo->args.retTypeClass, true);
8435                 returnLocalDsc.lvIsMultiRegRet = true;
8436             }
8437             else
8438             {
8439                 assert(!"unreached");
8440             }
8441
8442             if (varTypeIsFloating(returnLocalDsc.lvType))
8443             {
8444                 comp->compFloatingPointUsed = true;
8445             }
8446
8447             if (!varTypeIsFloating(comp->info.compRetType))
8448             {
8449                 returnLocalDsc.setPrefReg(REG_INTRET, comp);
8450             }
8451 #ifdef REG_FLOATRET
8452             else
8453             {
8454                 returnLocalDsc.setPrefReg(REG_FLOATRET, comp);
8455             }
8456 #endif
8457
8458 #ifdef DEBUG
8459             // This temporary should not be converted to a double in stress mode,
8460             // because we introduce assigns to it after the stress conversion
8461             returnLocalDsc.lvKeepType = 1;
8462 #endif
8463
8464             GenTree* retTemp = comp->gtNewLclvNode(returnLocalNum, returnLocalDsc.TypeGet());
8465
8466             // make sure copy prop ignores this node (make sure it always does a reload from the temp).
8467             retTemp->gtFlags |= GTF_DONT_CSE;
8468             returnExpr = comp->gtNewOperNode(GT_RETURN, retTemp->gtType, retTemp);
8469         }
8470         else
8471         {
8472             // return void
8473             noway_assert(comp->info.compRetType == TYP_VOID || varTypeIsStruct(comp->info.compRetType));
8474             comp->genReturnLocal = BAD_VAR_NUM;
8475
8476             returnExpr = new (comp, GT_RETURN) GenTreeOp(GT_RETURN, TYP_VOID);
8477         }
8478
8479         // Add 'return' expression to the return block
8480         comp->fgInsertStmtAtEnd(newReturnBB, returnExpr);
8481         // Flag that this 'return' was generated by return merging so that subsequent
8482         // return block morhping will know to leave it alone.
8483         returnExpr->gtFlags |= GTF_RET_MERGED;
8484
8485 #ifdef DEBUG
8486         if (comp->verbose)
8487         {
8488             printf("\nmergeReturns statement tree ");
8489             Compiler::printTreeID(returnExpr);
8490             printf(" added to genReturnBB %s\n", newReturnBB->dspToString());
8491             comp->gtDispTree(returnExpr);
8492             printf("\n");
8493         }
8494 #endif
8495         assert(index < maxReturns);
8496         returnBlocks[index] = newReturnBB;
8497         return newReturnBB;
8498     }
8499
8500     //------------------------------------------------------------------------
8501     // Merge: Find or create an appropriate merged return block for the given input block.
8502     //
8503     // Arguments:
8504     //    returnBlock - Return block from the input program to find a merged return for.
8505     //                  May be nullptr to indicate that new block suitable for non-constant
8506     //                  returns should be generated but no existing block modified.
8507     //    searchLimit - Blocks in `returnBlocks` up to but not including index `searchLimit`
8508     //                  will be checked to see if we already have an appropriate merged return
8509     //                  block for this case.  If a new block must be created, it will be stored
8510     //                  to `returnBlocks` at index `searchLimit`.
8511     //
8512     // Return Value:
8513     //    Merged return block suitable for handling this return value.  May be newly-created
8514     //    or pre-existing.
8515     //
8516     // Notes:
8517     //    If a constant-valued merged return block is used, `returnBlock` will be rewritten to
8518     //    jump to the merged return block and its `GT_RETURN` statement will be removed.  If
8519     //    a non-constant-valued merged return block is used, `genReturnBB` and `genReturnLocal`
8520     //    will be set so that Morph can perform that rewrite, which it will do after some key
8521     //    transformations like rewriting tail calls and calls that return to hidden buffers.
8522     //    In either of these cases, `fgReturnCount` and the merged return block's profile
8523     //    information will be updated to reflect or anticipate the rewrite of `returnBlock`.
8524     //
8525     BasicBlock* Merge(BasicBlock* returnBlock, unsigned searchLimit)
8526     {
8527         assert(mergingReturns);
8528
8529         BasicBlock* mergedReturnBlock = nullptr;
8530
8531         // Do not look for mergable constant returns in debug codegen as
8532         // we may lose track of sequence points.
8533         if ((returnBlock != nullptr) && (maxReturns > 1) && !comp->opts.compDbgCode)
8534         {
8535             // Check to see if this is a constant return so that we can search
8536             // for and/or create a constant return block for it.
8537
8538             GenTreeIntConCommon* retConst = GetReturnConst(returnBlock);
8539             if (retConst != nullptr)
8540             {
8541                 // We have a constant.  Now find or create a corresponding return block.
8542
8543                 unsigned    index;
8544                 BasicBlock* constReturnBlock = FindConstReturnBlock(retConst, searchLimit, &index);
8545
8546                 if (constReturnBlock == nullptr)
8547                 {
8548                     // We didn't find a const return block.  See if we have space left
8549                     // to make one.
8550
8551                     // We have already allocated `searchLimit` slots.
8552                     unsigned slotsReserved = searchLimit;
8553                     if (comp->genReturnBB == nullptr)
8554                     {
8555                         // We haven't made a non-const return yet, so we have to reserve
8556                         // a slot for one.
8557                         ++slotsReserved;
8558                     }
8559
8560                     if (slotsReserved < maxReturns)
8561                     {
8562                         // We have enough space to allocate a slot for this constant.
8563                         constReturnBlock = CreateReturnBB(searchLimit, retConst);
8564                     }
8565                 }
8566
8567                 if (constReturnBlock != nullptr)
8568                 {
8569                     // Found a constant merged return block.
8570                     mergedReturnBlock = constReturnBlock;
8571
8572                     // Change BBJ_RETURN to BBJ_ALWAYS targeting const return block.
8573                     assert((comp->info.compFlags & CORINFO_FLG_SYNCH) == 0);
8574                     returnBlock->bbJumpKind = BBJ_ALWAYS;
8575                     returnBlock->bbJumpDest = constReturnBlock;
8576
8577                     // Remove GT_RETURN since constReturnBlock returns the constant.
8578                     assert(returnBlock->lastStmt()->gtStmtExpr->OperIs(GT_RETURN));
8579                     assert(returnBlock->lastStmt()->gtStmtExpr->gtGetOp1()->IsIntegralConst());
8580                     comp->fgRemoveStmt(returnBlock, returnBlock->lastStmt());
8581
8582                     // Using 'returnBlock' as the insertion point for 'mergedReturnBlock'
8583                     // will give it a chance to use fallthrough rather than BBJ_ALWAYS.
8584                     // Resetting this after each merge ensures that any branches to the
8585                     // merged return block are lexically forward.
8586
8587                     insertionPoints[index] = returnBlock;
8588                 }
8589             }
8590         }
8591
8592         if (mergedReturnBlock == nullptr)
8593         {
8594             // No constant return block for this return; use the general one.
8595             mergedReturnBlock = comp->genReturnBB;
8596             if (mergedReturnBlock == nullptr)
8597             {
8598                 // No general merged return for this function yet; create one.
8599                 // There had better still be room left in the array.
8600                 assert(searchLimit < maxReturns);
8601                 mergedReturnBlock = CreateReturnBB(searchLimit);
8602                 comp->genReturnBB = mergedReturnBlock;
8603                 // Downstream code expects the `genReturnBB` to always remain
8604                 // once created, so that it can redirect flow edges to it.
8605                 mergedReturnBlock->bbFlags |= BBF_DONT_REMOVE;
8606             }
8607         }
8608
8609         if (returnBlock != nullptr)
8610         {
8611             // Propagate profile weight and related annotations to the merged block.
8612             // Return weight should never exceed entry weight, so cap it to avoid nonsensical
8613             // hot returns in synthetic profile settings.
8614             mergedReturnBlock->bbWeight =
8615                 min(mergedReturnBlock->bbWeight + returnBlock->bbWeight, comp->fgFirstBB->bbWeight);
8616             if (!returnBlock->hasProfileWeight())
8617             {
8618                 mergedReturnBlock->bbFlags &= ~BBF_PROF_WEIGHT;
8619             }
8620             if (mergedReturnBlock->bbWeight > 0)
8621             {
8622                 mergedReturnBlock->bbFlags &= ~BBF_RUN_RARELY;
8623             }
8624
8625             // Update fgReturnCount to reflect or anticipate that `returnBlock` will no longer
8626             // be a return point.
8627             comp->fgReturnCount--;
8628         }
8629
8630         return mergedReturnBlock;
8631     }
8632
8633     //------------------------------------------------------------------------
8634     // GetReturnConst: If the given block returns an integral constant, return the
8635     //     GenTreeIntConCommon that represents the constant.
8636     //
8637     // Arguments:
8638     //    returnBlock - Block whose return value is to be inspected.
8639     //
8640     // Return Value:
8641     //    GenTreeIntCommon that is the argument of `returnBlock`'s `GT_RETURN` if
8642     //    such exists; nullptr otherwise.
8643     //
8644     static GenTreeIntConCommon* GetReturnConst(BasicBlock* returnBlock)
8645     {
8646         GenTreeStmt* lastStmt = returnBlock->lastStmt();
8647         if (lastStmt == nullptr)
8648         {
8649             return nullptr;
8650         }
8651
8652         GenTree* lastExpr = lastStmt->gtStmtExpr;
8653         if (!lastExpr->OperIs(GT_RETURN))
8654         {
8655             return nullptr;
8656         }
8657
8658         GenTree* retExpr = lastExpr->gtGetOp1();
8659         if ((retExpr == nullptr) || !retExpr->IsIntegralConst())
8660         {
8661             return nullptr;
8662         }
8663
8664         return retExpr->AsIntConCommon();
8665     }
8666
8667     //------------------------------------------------------------------------
8668     // FindConstReturnBlock: Scan the already-created merged return blocks, up to `searchLimit`,
8669     //     and return the one corresponding to the given const expression if it exists.
8670     //
8671     // Arguments:
8672     //    constExpr - GenTreeIntCommon representing the constant return value we're
8673     //        searching for.
8674     //    searchLimit - Check `returnBlocks`/`returnConstants` up to but not including
8675     //        this index.
8676     //    index - [out] Index of return block in the `returnBlocks` array, if found;
8677     //        searchLimit otherwise.
8678     //
8679     // Return Value:
8680     //    A block that returns the same constant, if one is found; otherwise nullptr.
8681     //
8682     BasicBlock* FindConstReturnBlock(GenTreeIntConCommon* constExpr, unsigned searchLimit, unsigned* index)
8683     {
8684         INT64 constVal = constExpr->IntegralValue();
8685
8686         for (unsigned i = 0; i < searchLimit; ++i)
8687         {
8688             // Need to check both for matching const val and for genReturnBB
8689             // because genReturnBB is used for non-constant returns and its
8690             // corresponding entry in the returnConstants array is garbage.
8691             if (returnConstants[i] == constVal)
8692             {
8693                 BasicBlock* returnBlock = returnBlocks[i];
8694
8695                 if (returnBlock == comp->genReturnBB)
8696                 {
8697                     // This is the block used for non-constant returns, so
8698                     // its returnConstants entry is just garbage; don't be
8699                     // fooled.
8700                     continue;
8701                 }
8702
8703                 *index = i;
8704                 return returnBlock;
8705             }
8706         }
8707
8708         *index = searchLimit;
8709         return nullptr;
8710     }
8711 };
8712 }
8713
8714 /*****************************************************************************
8715 *
8716 *  Add any internal blocks/trees we may need
8717 */
8718
8719 void Compiler::fgAddInternal()
8720 {
8721     noway_assert(!compIsForInlining());
8722
8723 #ifndef LEGACY_BACKEND
8724     // The RyuJIT backend requires a scratch BB into which it can safely insert a P/Invoke method prolog if one is
8725     // required. Create it here.
8726     if (info.compCallUnmanaged != 0)
8727     {
8728         fgEnsureFirstBBisScratch();
8729         fgFirstBB->bbFlags |= BBF_DONT_REMOVE;
8730     }
8731 #endif // !LEGACY_BACKEND
8732
8733     /*
8734     <BUGNUM> VSW441487 </BUGNUM>
8735
8736     The "this" pointer is implicitly used in the following cases:
8737     1. Locking of synchronized methods
8738     2. Dictionary access of shared generics code
8739     3. If a method has "catch(FooException<T>)", the EH code accesses "this" to determine T.
8740     4. Initializing the type from generic methods which require precise cctor semantics
8741     5. Verifier does special handling of "this" in the .ctor
8742
8743     However, we might overwrite it with a "starg 0".
8744     In this case, we will redirect all "ldarg(a)/starg(a) 0" to a temp lvaTable[lvaArg0Var]
8745     */
8746
8747     if (!info.compIsStatic)
8748     {
8749         if (lvaArg0Var != info.compThisArg)
8750         {
8751             // When we're using the general encoder, we mark compThisArg address-taken to ensure that it is not
8752             // enregistered (since the decoder always reports a stack location for "this" for generics
8753             // context vars).
8754             bool lva0CopiedForGenericsCtxt;
8755 #ifndef JIT32_GCENCODER
8756             lva0CopiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0);
8757 #else  // JIT32_GCENCODER
8758             lva0CopiedForGenericsCtxt          = false;
8759 #endif // JIT32_GCENCODER
8760             noway_assert(lva0CopiedForGenericsCtxt || !lvaTable[info.compThisArg].lvAddrExposed);
8761             noway_assert(!lvaTable[info.compThisArg].lvHasILStoreOp);
8762             noway_assert(lvaTable[lvaArg0Var].lvAddrExposed || lvaTable[lvaArg0Var].lvHasILStoreOp ||
8763                          lva0CopiedForGenericsCtxt);
8764
8765             var_types thisType = lvaTable[info.compThisArg].TypeGet();
8766
8767             // Now assign the original input "this" to the temp
8768
8769             GenTree* tree;
8770
8771             tree = gtNewLclvNode(lvaArg0Var, thisType);
8772
8773             tree = gtNewAssignNode(tree,                                     // dst
8774                                    gtNewLclvNode(info.compThisArg, thisType) // src
8775                                    );
8776
8777             /* Create a new basic block and stick the assignment in it */
8778
8779             fgEnsureFirstBBisScratch();
8780
8781             fgInsertStmtAtEnd(fgFirstBB, tree);
8782
8783 #ifdef DEBUG
8784             if (verbose)
8785             {
8786                 printf("\nCopy \"this\" to lvaArg0Var in first basic block %s\n", fgFirstBB->dspToString());
8787                 gtDispTree(tree);
8788                 printf("\n");
8789             }
8790 #endif
8791         }
8792     }
8793
8794     // Grab a temp for the security object.
8795     // (Note: opts.compDbgEnC currently also causes the security object to be generated. See Compiler::compCompile)
8796     if (opts.compNeedSecurityCheck)
8797     {
8798         noway_assert(lvaSecurityObject == BAD_VAR_NUM);
8799         lvaSecurityObject                  = lvaGrabTempWithImplicitUse(false DEBUGARG("security check"));
8800         lvaTable[lvaSecurityObject].lvType = TYP_REF;
8801     }
8802
8803     // Merge return points if required or beneficial
8804     MergedReturns merger(this);
8805
8806 #if FEATURE_EH_FUNCLETS
8807     // Add the synchronized method enter/exit calls and try/finally protection. Note
8808     // that this must happen before the one BBJ_RETURN block is created below, so the
8809     // BBJ_RETURN block gets placed at the top-level, not within an EH region. (Otherwise,
8810     // we'd have to be really careful when creating the synchronized method try/finally
8811     // not to include the BBJ_RETURN block.)
8812     if ((info.compFlags & CORINFO_FLG_SYNCH) != 0)
8813     {
8814         fgAddSyncMethodEnterExit();
8815     }
8816 #endif // FEATURE_EH_FUNCLETS
8817
8818     //
8819     //  We will generate just one epilog (return block)
8820     //   when we are asked to generate enter/leave callbacks
8821     //   or for methods with PInvoke
8822     //   or for methods calling into unmanaged code
8823     //   or for synchronized methods.
8824     //
8825     BasicBlock* lastBlockBeforeGenReturns = fgLastBB;
8826     if (compIsProfilerHookNeeded() || (info.compCallUnmanaged != 0) || opts.IsReversePInvoke() ||
8827         ((info.compFlags & CORINFO_FLG_SYNCH) != 0))
8828     {
8829         // We will generate only one return block
8830         // We will transform the BBJ_RETURN blocks
8831         //  into jumps to the one return block
8832         //
8833         merger.SetMaxReturns(1);
8834
8835         // Eagerly create the genReturnBB since the lowering of these constructs
8836         // will expect to find it.
8837         BasicBlock* mergedReturn = merger.EagerCreate();
8838         assert(mergedReturn == genReturnBB);
8839         // Assume weight equal to entry weight for this BB.
8840         mergedReturn->bbFlags &= ~BBF_PROF_WEIGHT;
8841         mergedReturn->bbWeight = fgFirstBB->bbWeight;
8842         if (mergedReturn->bbWeight > 0)
8843         {
8844             mergedReturn->bbFlags &= ~BBF_RUN_RARELY;
8845         }
8846     }
8847     else
8848     {
8849         //
8850         // We are allowed to have multiple individual exits
8851         // However we can still decide to have a single return
8852         //
8853         if (compCodeOpt() == SMALL_CODE)
8854         {
8855             // For the Small_Code case we always generate a
8856             // single return block when we have multiple
8857             // return points
8858             //
8859             merger.SetMaxReturns(1);
8860         }
8861         else
8862         {
8863             merger.SetMaxReturns(MergedReturns::ReturnCountHardLimit);
8864         }
8865     }
8866
8867     // Visit the BBJ_RETURN blocks and merge as necessary.
8868
8869     for (BasicBlock* block = fgFirstBB; block != lastBlockBeforeGenReturns->bbNext; block = block->bbNext)
8870     {
8871         if ((block->bbJumpKind == BBJ_RETURN) && ((block->bbFlags & BBF_HAS_JMP) == 0))
8872         {
8873             merger.Record(block);
8874         }
8875     }
8876
8877     merger.PlaceReturns();
8878
8879     if (info.compCallUnmanaged != 0)
8880     {
8881         // The P/Invoke helpers only require a frame variable, so only allocate the
8882         // TCB variable if we're not using them.
8883         if (!opts.ShouldUsePInvokeHelpers())
8884         {
8885             info.compLvFrameListRoot = lvaGrabTemp(false DEBUGARG("Pinvoke FrameListRoot"));
8886         }
8887
8888         lvaInlinedPInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Pinvoke FrameVar"));
8889
8890         LclVarDsc* varDsc = &lvaTable[lvaInlinedPInvokeFrameVar];
8891         varDsc->addPrefReg(RBM_PINVOKE_TCB, this);
8892         varDsc->lvType = TYP_BLK;
8893         // Make room for the inlined frame.
8894         varDsc->lvExactSize = eeGetEEInfo()->inlinedCallFrameInfo.size;
8895 #if FEATURE_FIXED_OUT_ARGS
8896         // Grab and reserve space for TCB, Frame regs used in PInvoke epilog to pop the inlined frame.
8897         // See genPInvokeMethodEpilog() for use of the grabbed var. This is only necessary if we are
8898         // not using the P/Invoke helpers.
8899         if (!opts.ShouldUsePInvokeHelpers() && compJmpOpUsed)
8900         {
8901             lvaPInvokeFrameRegSaveVar = lvaGrabTempWithImplicitUse(false DEBUGARG("PInvokeFrameRegSave Var"));
8902             varDsc                    = &lvaTable[lvaPInvokeFrameRegSaveVar];
8903             varDsc->lvType            = TYP_BLK;
8904             varDsc->lvExactSize       = 2 * REGSIZE_BYTES;
8905         }
8906 #endif
8907     }
8908
8909     // Do we need to insert a "JustMyCode" callback?
8910
8911     CORINFO_JUST_MY_CODE_HANDLE* pDbgHandle = nullptr;
8912     CORINFO_JUST_MY_CODE_HANDLE  dbgHandle  = nullptr;
8913     if (opts.compDbgCode && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB))
8914     {
8915         dbgHandle = info.compCompHnd->getJustMyCodeHandle(info.compMethodHnd, &pDbgHandle);
8916     }
8917
8918 #ifdef _TARGET_ARM64_
8919     // TODO-ARM64-NYI: don't do just-my-code
8920     dbgHandle  = nullptr;
8921     pDbgHandle = nullptr;
8922 #endif // _TARGET_ARM64_
8923
8924     noway_assert(!dbgHandle || !pDbgHandle);
8925
8926     if (dbgHandle || pDbgHandle)
8927     {
8928         GenTree* embNode        = gtNewIconEmbHndNode(dbgHandle, pDbgHandle, GTF_ICON_TOKEN_HDL, info.compMethodHnd);
8929         GenTree* guardCheckVal  = gtNewOperNode(GT_IND, TYP_INT, embNode);
8930         GenTree* guardCheckCond = gtNewOperNode(GT_EQ, TYP_INT, guardCheckVal, gtNewZeroConNode(TYP_INT));
8931         guardCheckCond->gtFlags |= GTF_RELOP_QMARK;
8932
8933         // Create the callback which will yield the final answer
8934
8935         GenTree* callback = gtNewHelperCallNode(CORINFO_HELP_DBG_IS_JUST_MY_CODE, TYP_VOID);
8936         callback          = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), callback);
8937
8938         // Stick the conditional call at the start of the method
8939
8940         fgEnsureFirstBBisScratch();
8941         fgInsertStmtAtEnd(fgFirstBB, gtNewQmarkNode(TYP_VOID, guardCheckCond, callback));
8942     }
8943
8944     /* Do we need to call out for security ? */
8945
8946     if (tiSecurityCalloutNeeded)
8947     {
8948         // We must have grabbed this local.
8949         noway_assert(opts.compNeedSecurityCheck);
8950         noway_assert(lvaSecurityObject != BAD_VAR_NUM);
8951
8952         GenTree* tree;
8953
8954         /* Insert the expression "call JIT_Security_Prolog(MethodHnd, &SecurityObject)" */
8955
8956         tree = gtNewIconEmbMethHndNode(info.compMethodHnd);
8957
8958         tree = gtNewHelperCallNode(info.compCompHnd->getSecurityPrologHelper(info.compMethodHnd), TYP_VOID,
8959                                    gtNewArgList(tree, gtNewOperNode(GT_ADDR, TYP_BYREF,
8960                                                                     gtNewLclvNode(lvaSecurityObject, TYP_REF))));
8961
8962         /* Create a new basic block and stick the call in it */
8963
8964         fgEnsureFirstBBisScratch();
8965
8966         fgInsertStmtAtEnd(fgFirstBB, tree);
8967
8968 #ifdef DEBUG
8969         if (verbose)
8970         {
8971             printf("\ntiSecurityCalloutNeeded - Add call JIT_Security_Prolog(%08p) statement ",
8972                    dspPtr(info.compMethodHnd));
8973             printTreeID(tree);
8974             printf(" in first basic block %s\n", fgFirstBB->dspToString());
8975             gtDispTree(tree);
8976             printf("\n");
8977         }
8978 #endif
8979     }
8980
8981 #if !FEATURE_EH_FUNCLETS
8982
8983     /* Is this a 'synchronized' method? */
8984
8985     if (info.compFlags & CORINFO_FLG_SYNCH)
8986     {
8987         GenTree* tree = NULL;
8988
8989         /* Insert the expression "enterCrit(this)" or "enterCrit(handle)" */
8990
8991         if (info.compIsStatic)
8992         {
8993             tree = fgGetCritSectOfStaticMethod();
8994
8995             tree = gtNewHelperCallNode(CORINFO_HELP_MON_ENTER_STATIC, TYP_VOID, gtNewArgList(tree));
8996         }
8997         else
8998         {
8999             noway_assert(lvaTable[info.compThisArg].lvType == TYP_REF);
9000
9001             tree = gtNewLclvNode(info.compThisArg, TYP_REF);
9002
9003             tree = gtNewHelperCallNode(CORINFO_HELP_MON_ENTER, TYP_VOID, gtNewArgList(tree));
9004         }
9005
9006         /* Create a new basic block and stick the call in it */
9007
9008         fgEnsureFirstBBisScratch();
9009
9010         fgInsertStmtAtEnd(fgFirstBB, tree);
9011
9012 #ifdef DEBUG
9013         if (verbose)
9014         {
9015             printf("\nSynchronized method - Add enterCrit statement in first basic block %s\n",
9016                    fgFirstBB->dspToString());
9017             gtDispTree(tree);
9018             printf("\n");
9019         }
9020 #endif
9021
9022         /* We must be generating a single exit point for this to work */
9023
9024         noway_assert(genReturnBB != nullptr);
9025
9026         /* Create the expression "exitCrit(this)" or "exitCrit(handle)" */
9027
9028         if (info.compIsStatic)
9029         {
9030             tree = fgGetCritSectOfStaticMethod();
9031
9032             tree = gtNewHelperCallNode(CORINFO_HELP_MON_EXIT_STATIC, TYP_VOID, gtNewArgList(tree));
9033         }
9034         else
9035         {
9036             tree = gtNewLclvNode(info.compThisArg, TYP_REF);
9037
9038             tree = gtNewHelperCallNode(CORINFO_HELP_MON_EXIT, TYP_VOID, gtNewArgList(tree));
9039         }
9040
9041         fgInsertStmtNearEnd(genReturnBB, tree);
9042
9043 #ifdef DEBUG
9044         if (verbose)
9045         {
9046             printf("\nSynchronized method - Add exit expression ");
9047             printTreeID(tree);
9048             printf("\n");
9049         }
9050 #endif
9051
9052         // Reset cookies used to track start and end of the protected region in synchronized methods
9053         syncStartEmitCookie = NULL;
9054         syncEndEmitCookie   = NULL;
9055     }
9056
9057 #endif // !FEATURE_EH_FUNCLETS
9058
9059     /* Do we need to do runtime call out to check the security? */
9060
9061     if (tiRuntimeCalloutNeeded)
9062     {
9063         GenTree* tree;
9064
9065         /* Insert the expression "call verificationRuntimeCheck(MethodHnd)" */
9066
9067         tree = gtNewIconEmbMethHndNode(info.compMethodHnd);
9068
9069         tree = gtNewHelperCallNode(CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, TYP_VOID, gtNewArgList(tree));
9070
9071         /* Create a new basic block and stick the call in it */
9072
9073         fgEnsureFirstBBisScratch();
9074
9075         fgInsertStmtAtEnd(fgFirstBB, tree);
9076
9077 #ifdef DEBUG
9078         if (verbose)
9079         {
9080             printf("\ntiRuntimeCalloutNeeded - Call verificationRuntimeCheck(%08p) statement in first basic block %s\n",
9081                    dspPtr(info.compMethodHnd), fgFirstBB->dspToString());
9082             gtDispTree(tree);
9083             printf("\n");
9084         }
9085 #endif
9086     }
9087
9088     if (opts.IsReversePInvoke())
9089     {
9090         fgAddReversePInvokeEnterExit();
9091     }
9092
9093 #ifdef DEBUG
9094     if (verbose)
9095     {
9096         printf("\n*************** After fgAddInternal()\n");
9097         fgDispBasicBlocks();
9098         fgDispHandlerTab();
9099     }
9100 #endif
9101 }
9102
9103 /*****************************************************************************
9104  *
9105  *  Create a new statement from tree and wire the links up.
9106  */
9107 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTree* tree, BasicBlock* block, IL_OFFSETX offs)
9108 {
9109     GenTreeStmt* stmt = gtNewStmt(tree, offs);
9110
9111     if (fgStmtListThreaded)
9112     {
9113         gtSetStmtInfo(stmt);
9114         fgSetStmtSeq(stmt);
9115     }
9116
9117 #if DEBUG
9118     if (block != nullptr)
9119     {
9120         fgDebugCheckNodeLinks(block, stmt);
9121     }
9122 #endif
9123
9124     return stmt;
9125 }
9126
9127 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTree* tree)
9128 {
9129     return fgNewStmtFromTree(tree, nullptr, BAD_IL_OFFSET);
9130 }
9131
9132 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTree* tree, BasicBlock* block)
9133 {
9134     return fgNewStmtFromTree(tree, block, BAD_IL_OFFSET);
9135 }
9136
9137 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTree* tree, IL_OFFSETX offs)
9138 {
9139     return fgNewStmtFromTree(tree, nullptr, offs);
9140 }
9141
9142 //------------------------------------------------------------------------
9143 // fgFindBlockILOffset: Given a block, find the IL offset corresponding to the first statement
9144 //      in the block with a legal IL offset. Skip any leading statements that have BAD_IL_OFFSET.
9145 //      If no statement has an initialized statement offset (including the case where there are
9146 //      no statements in the block), then return BAD_IL_OFFSET. This function is used when
9147 //      blocks are split or modified, and we want to maintain the IL offset as much as possible
9148 //      to preserve good debugging behavior.
9149 //
9150 // Arguments:
9151 //      block - The block to check.
9152 //
9153 // Return Value:
9154 //      The first good IL offset of a statement in the block, or BAD_IL_OFFSET if such an IL offset
9155 //      cannot be found.
9156 //
9157 IL_OFFSET Compiler::fgFindBlockILOffset(BasicBlock* block)
9158 {
9159     // This function searches for IL offsets in statement nodes, so it can't be used in LIR. We
9160     // could have a similar function for LIR that searches for GT_IL_OFFSET nodes.
9161     assert(!block->IsLIR());
9162
9163     for (GenTree* stmt = block->bbTreeList; stmt != nullptr; stmt = stmt->gtNext)
9164     {
9165         assert(stmt->IsStatement());
9166         if (stmt->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET)
9167         {
9168             return jitGetILoffs(stmt->gtStmt.gtStmtILoffsx);
9169         }
9170     }
9171
9172     return BAD_IL_OFFSET;
9173 }
9174
9175 //------------------------------------------------------------------------------
9176 // fgSplitBlockAtEnd - split the given block into two blocks.
9177 //                   All code in the block stays in the original block.
9178 //                   Control falls through from original to new block, and
9179 //                   the new block is returned.
9180 //------------------------------------------------------------------------------
9181 BasicBlock* Compiler::fgSplitBlockAtEnd(BasicBlock* curr)
9182 {
9183     // We'd like to use fgNewBBafter(), but we need to update the preds list before linking in the new block.
9184     // (We need the successors of 'curr' to be correct when we do this.)
9185     BasicBlock* newBlock = bbNewBasicBlock(curr->bbJumpKind);
9186
9187     // Start the new block with no refs. When we set the preds below, this will get updated correctly.
9188     newBlock->bbRefs = 0;
9189
9190     // For each successor of the original block, set the new block as their predecessor.
9191     // Note we are using the "rational" version of the successor iterator that does not hide the finallyret arcs.
9192     // Without these arcs, a block 'b' may not be a member of succs(preds(b))
9193     if (curr->bbJumpKind != BBJ_SWITCH)
9194     {
9195         unsigned numSuccs = curr->NumSucc(this);
9196         for (unsigned i = 0; i < numSuccs; i++)
9197         {
9198             BasicBlock* succ = curr->GetSucc(i, this);
9199             if (succ != newBlock)
9200             {
9201                 JITDUMP("BB%02u previous predecessor was BB%02u, now is BB%02u\n", succ->bbNum, curr->bbNum,
9202                         newBlock->bbNum);
9203                 fgReplacePred(succ, curr, newBlock);
9204             }
9205         }
9206
9207         newBlock->bbJumpDest = curr->bbJumpDest;
9208         curr->bbJumpDest     = nullptr;
9209     }
9210     else
9211     {
9212         // In the case of a switch statement there's more complicated logic in order to wire up the predecessor lists
9213         // but fortunately there's an existing method that implements this functionality.
9214         newBlock->bbJumpSwt = curr->bbJumpSwt;
9215
9216         fgChangeSwitchBlock(curr, newBlock);
9217
9218         curr->bbJumpSwt = nullptr;
9219     }
9220
9221     newBlock->inheritWeight(curr);
9222
9223     // Set the new block's flags. Note that the new block isn't BBF_INTERNAL unless the old block is.
9224     newBlock->bbFlags = curr->bbFlags;
9225
9226     // Remove flags that the new block can't have.
9227     newBlock->bbFlags &= ~(BBF_TRY_BEG | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1 | BBF_HAS_LABEL |
9228                            BBF_JMP_TARGET | BBF_FUNCLET_BEG | BBF_LOOP_PREHEADER | BBF_KEEP_BBJ_ALWAYS);
9229
9230     // Remove the GC safe bit on the new block. It seems clear that if we split 'curr' at the end,
9231     // such that all the code is left in 'curr', and 'newBlock' just gets the control flow, then
9232     // both 'curr' and 'newBlock' could accurately retain an existing GC safe bit. However, callers
9233     // use this function to split blocks in the middle, or at the beginning, and they don't seem to
9234     // be careful about updating this flag appropriately. So, removing the GC safe bit is simply
9235     // conservative: some functions might end up being fully interruptible that could be partially
9236     // interruptible if we exercised more care here.
9237     newBlock->bbFlags &= ~BBF_GC_SAFE_POINT;
9238
9239 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9240     newBlock->bbFlags &= ~(BBF_FINALLY_TARGET);
9241 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9242
9243     // The new block has no code, so we leave bbCodeOffs/bbCodeOffsEnd set to BAD_IL_OFFSET. If a caller
9244     // puts code in the block, then it needs to update these.
9245
9246     // Insert the new block in the block list after the 'curr' block.
9247     fgInsertBBafter(curr, newBlock);
9248     fgExtendEHRegionAfter(curr); // The new block is in the same EH region as the old block.
9249
9250     // Remove flags from the old block that are no longer possible.
9251     curr->bbFlags &= ~(BBF_HAS_JMP | BBF_RETLESS_CALL);
9252
9253     // Default to fallthru, and add the arc for that.
9254     curr->bbJumpKind = BBJ_NONE;
9255     fgAddRefPred(newBlock, curr);
9256
9257     return newBlock;
9258 }
9259
9260 //------------------------------------------------------------------------------
9261 // fgSplitBlockAfterStatement - Split the given block, with all code after
9262 //                              the given statement going into the second block.
9263 //------------------------------------------------------------------------------
9264 BasicBlock* Compiler::fgSplitBlockAfterStatement(BasicBlock* curr, GenTree* stmt)
9265 {
9266     assert(!curr->IsLIR()); // No statements in LIR, so you can't use this function.
9267
9268     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
9269
9270     if (stmt)
9271     {
9272         newBlock->bbTreeList = stmt->gtNext;
9273         if (newBlock->bbTreeList)
9274         {
9275             newBlock->bbTreeList->gtPrev = curr->bbTreeList->gtPrev;
9276         }
9277         curr->bbTreeList->gtPrev = stmt;
9278         stmt->gtNext             = nullptr;
9279
9280         // Update the IL offsets of the blocks to match the split.
9281
9282         assert(newBlock->bbCodeOffs == BAD_IL_OFFSET);
9283         assert(newBlock->bbCodeOffsEnd == BAD_IL_OFFSET);
9284
9285         // curr->bbCodeOffs remains the same
9286         newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
9287
9288         IL_OFFSET splitPointILOffset = fgFindBlockILOffset(newBlock);
9289
9290         curr->bbCodeOffsEnd  = splitPointILOffset;
9291         newBlock->bbCodeOffs = splitPointILOffset;
9292     }
9293     else
9294     {
9295         assert(curr->bbTreeList == nullptr); // if no tree was given then it better be an empty block
9296     }
9297
9298     return newBlock;
9299 }
9300
9301 //------------------------------------------------------------------------------
9302 // fgSplitBlockAfterNode - Split the given block, with all code after
9303 //                         the given node going into the second block.
9304 //                         This function is only used in LIR.
9305 //------------------------------------------------------------------------------
9306 BasicBlock* Compiler::fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node)
9307 {
9308     assert(curr->IsLIR());
9309
9310     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
9311
9312     if (node != nullptr)
9313     {
9314         LIR::Range& currBBRange = LIR::AsRange(curr);
9315
9316         if (node != currBBRange.LastNode())
9317         {
9318             LIR::Range nodesToMove = currBBRange.Remove(node->gtNext, currBBRange.LastNode());
9319             LIR::AsRange(newBlock).InsertAtBeginning(std::move(nodesToMove));
9320         }
9321
9322         // Update the IL offsets of the blocks to match the split.
9323
9324         assert(newBlock->bbCodeOffs == BAD_IL_OFFSET);
9325         assert(newBlock->bbCodeOffsEnd == BAD_IL_OFFSET);
9326
9327         // curr->bbCodeOffs remains the same
9328         newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
9329
9330         // Search backwards from the end of the current block looking for the IL offset to use
9331         // for the end IL offset for the original block.
9332         IL_OFFSET                   splitPointILOffset = BAD_IL_OFFSET;
9333         LIR::Range::ReverseIterator riter;
9334         LIR::Range::ReverseIterator riterEnd;
9335         for (riter = currBBRange.rbegin(), riterEnd = currBBRange.rend(); riter != riterEnd; ++riter)
9336         {
9337             if ((*riter)->gtOper == GT_IL_OFFSET)
9338             {
9339                 GenTreeStmt* stmt = (*riter)->AsStmt();
9340                 if (stmt->gtStmtILoffsx != BAD_IL_OFFSET)
9341                 {
9342                     splitPointILOffset = jitGetILoffs(stmt->gtStmtILoffsx);
9343                     break;
9344                 }
9345             }
9346         }
9347
9348         curr->bbCodeOffsEnd = splitPointILOffset;
9349
9350         // Also use this as the beginning offset of the next block. Presumably we could/should
9351         // look to see if the first node is a GT_IL_OFFSET node, and use that instead.
9352         newBlock->bbCodeOffs = splitPointILOffset;
9353     }
9354     else
9355     {
9356         assert(curr->bbTreeList == nullptr); // if no node was given then it better be an empty block
9357     }
9358
9359     return newBlock;
9360 }
9361
9362 //------------------------------------------------------------------------------
9363 // fgSplitBlockAtBeginning - Split the given block into two blocks.
9364 //                         Control falls through from original to new block,
9365 //                         and the new block is returned.
9366 //                         All code in the original block goes into the new block
9367 //------------------------------------------------------------------------------
9368 BasicBlock* Compiler::fgSplitBlockAtBeginning(BasicBlock* curr)
9369 {
9370     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
9371
9372     newBlock->bbTreeList = curr->bbTreeList;
9373     curr->bbTreeList     = nullptr;
9374
9375     // The new block now has all the code, and the old block has none. Update the
9376     // IL offsets for the block to reflect this.
9377
9378     newBlock->bbCodeOffs    = curr->bbCodeOffs;
9379     newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
9380
9381     curr->bbCodeOffs    = BAD_IL_OFFSET;
9382     curr->bbCodeOffsEnd = BAD_IL_OFFSET;
9383
9384     return newBlock;
9385 }
9386
9387 //------------------------------------------------------------------------
9388 // fgSplitEdge: Splits the edge between a block 'curr' and its successor 'succ' by creating a new block
9389 //              that replaces 'succ' as a successor of 'curr', and which branches unconditionally
9390 //              to (or falls through to) 'succ'. Note that for a BBJ_COND block 'curr',
9391 //              'succ' might be the fall-through path or the branch path from 'curr'.
9392 //
9393 // Arguments:
9394 //    curr - A block which branches conditionally to 'succ'
9395 //    succ - The target block
9396 //
9397 // Return Value:
9398 //    Returns a new block, that is a successor of 'curr' and which branches unconditionally to 'succ'
9399 //
9400 // Assumptions:
9401 //    'curr' must have a bbJumpKind of BBJ_COND or BBJ_SWITCH
9402 //
9403 // Notes:
9404 //    The returned block is empty.
9405
9406 BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ)
9407 {
9408     assert(curr->bbJumpKind == BBJ_COND || curr->bbJumpKind == BBJ_SWITCH);
9409     assert(fgGetPredForBlock(succ, curr) != nullptr);
9410
9411     BasicBlock* newBlock;
9412     if (succ == curr->bbNext)
9413     {
9414         // The successor is the fall-through path of a BBJ_COND, or
9415         // an immediately following block of a BBJ_SWITCH (which has
9416         // no fall-through path). For this case, simply insert a new
9417         // fall-through block after 'curr'.
9418         newBlock = fgNewBBafter(BBJ_NONE, curr, true /*extendRegion*/);
9419     }
9420     else
9421     {
9422         newBlock = fgNewBBinRegion(BBJ_ALWAYS, curr, curr->isRunRarely());
9423         // The new block always jumps to 'succ'
9424         newBlock->bbJumpDest = succ;
9425     }
9426     newBlock->bbFlags |= (curr->bbFlags & succ->bbFlags & (BBF_BACKWARD_JUMP));
9427
9428     JITDUMP("Splitting edge from BB%02u to BB%02u; adding BB%02u\n", curr->bbNum, succ->bbNum, newBlock->bbNum);
9429
9430     if (curr->bbJumpKind == BBJ_COND)
9431     {
9432         fgReplacePred(succ, curr, newBlock);
9433         if (curr->bbJumpDest == succ)
9434         {
9435             // Now 'curr' jumps to newBlock
9436             curr->bbJumpDest = newBlock;
9437             newBlock->bbFlags |= BBF_JMP_TARGET;
9438         }
9439         fgAddRefPred(newBlock, curr);
9440     }
9441     else
9442     {
9443         assert(curr->bbJumpKind == BBJ_SWITCH);
9444
9445         // newBlock replaces 'succ' in the switch.
9446         fgReplaceSwitchJumpTarget(curr, newBlock, succ);
9447
9448         // And 'succ' has 'newBlock' as a new predecessor.
9449         fgAddRefPred(succ, newBlock);
9450     }
9451
9452     // This isn't accurate, but it is complex to compute a reasonable number so just assume that we take the
9453     // branch 50% of the time.
9454     newBlock->inheritWeightPercentage(curr, 50);
9455
9456     // The bbLiveIn and bbLiveOut are both equal to the bbLiveIn of 'succ'
9457     if (fgLocalVarLivenessDone)
9458     {
9459         VarSetOps::Assign(this, newBlock->bbLiveIn, succ->bbLiveIn);
9460         VarSetOps::Assign(this, newBlock->bbLiveOut, succ->bbLiveIn);
9461     }
9462
9463     return newBlock;
9464 }
9465
9466 /*****************************************************************************/
9467 /*****************************************************************************/
9468
9469 void Compiler::fgFindOperOrder()
9470 {
9471 #ifdef DEBUG
9472     if (verbose)
9473     {
9474         printf("*************** In fgFindOperOrder()\n");
9475     }
9476 #endif
9477
9478     BasicBlock*  block;
9479     GenTreeStmt* stmt;
9480
9481     /* Walk the basic blocks and for each statement determine
9482      * the evaluation order, cost, FP levels, etc... */
9483
9484     for (block = fgFirstBB; block; block = block->bbNext)
9485     {
9486         compCurBB = block;
9487         for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
9488         {
9489             /* Recursively process the statement */
9490
9491             compCurStmt = stmt;
9492             gtSetStmtInfo(stmt);
9493         }
9494     }
9495 }
9496
9497 //------------------------------------------------------------------------
9498 // fgSimpleLowering: do full walk of all IR, lowering selected operations
9499 // and computing lvaOutgoingArgumentAreaSize.
9500 //
9501 // Notes:
9502 //    Lowers GT_ARR_LENGTH, GT_ARR_BOUNDS_CHECK, and GT_SIMD_CHK.
9503 //
9504 //    For target ABIs with fixed out args area, computes upper bound on
9505 //    the size of this area from the calls in the IR.
9506 //
9507 //    Outgoing arg area size is computed here because we want to run it
9508 //    after optimization (in case calls are removed) and need to look at
9509 //    all possible calls in the method.
9510
9511 void Compiler::fgSimpleLowering()
9512 {
9513 #if FEATURE_FIXED_OUT_ARGS
9514     unsigned outgoingArgSpaceSize = 0;
9515 #endif // FEATURE_FIXED_OUT_ARGS
9516
9517     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
9518     {
9519         // Walk the statement trees in this basic block.
9520         compCurBB = block; // Used in fgRngChkTarget.
9521
9522 #ifdef LEGACY_BACKEND
9523         for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt)
9524         {
9525             for (GenTree* tree = stmt->gtStmtList; tree; tree = tree->gtNext)
9526             {
9527 #else
9528
9529         LIR::Range& range = LIR::AsRange(block);
9530         for (GenTree* tree : range)
9531         {
9532             {
9533 #endif
9534
9535                 switch (tree->OperGet())
9536                 {
9537                     case GT_ARR_LENGTH:
9538                     {
9539                         GenTreeArrLen* arrLen = tree->AsArrLen();
9540                         GenTree*       arr    = arrLen->gtArrLen.ArrRef();
9541                         GenTree*       add;
9542                         GenTree*       con;
9543
9544                         /* Create the expression "*(array_addr + ArrLenOffs)" */
9545
9546                         noway_assert(arr->gtNext == tree);
9547
9548                         noway_assert(arrLen->ArrLenOffset() == offsetof(CORINFO_Array, length) ||
9549                                      arrLen->ArrLenOffset() == offsetof(CORINFO_String, stringLen));
9550
9551                         if ((arr->gtOper == GT_CNS_INT) && (arr->gtIntCon.gtIconVal == 0))
9552                         {
9553                             // If the array is NULL, then we should get a NULL reference
9554                             // exception when computing its length.  We need to maintain
9555                             // an invariant where there is no sum of two constants node, so
9556                             // let's simply return an indirection of NULL.
9557
9558                             add = arr;
9559                         }
9560                         else
9561                         {
9562                             con             = gtNewIconNode(arrLen->ArrLenOffset(), TYP_I_IMPL);
9563                             con->gtRsvdRegs = RBM_NONE;
9564
9565                             add             = gtNewOperNode(GT_ADD, TYP_REF, arr, con);
9566                             add->gtRsvdRegs = arr->gtRsvdRegs;
9567
9568 #ifdef LEGACY_BACKEND
9569                             con->gtCopyFPlvl(arr);
9570
9571                             add->gtCopyFPlvl(arr);
9572                             add->CopyCosts(arr);
9573
9574                             arr->gtNext = con;
9575                             con->gtPrev = arr;
9576
9577                             con->gtNext = add;
9578                             add->gtPrev = con;
9579
9580                             add->gtNext  = tree;
9581                             tree->gtPrev = add;
9582 #else
9583                             range.InsertAfter(arr, con, add);
9584 #endif
9585                         }
9586
9587                         // Change to a GT_IND.
9588                         tree->ChangeOperUnchecked(GT_IND);
9589
9590                         tree->gtOp.gtOp1 = add;
9591                         break;
9592                     }
9593
9594                     case GT_ARR_BOUNDS_CHECK:
9595 #ifdef FEATURE_SIMD
9596                     case GT_SIMD_CHK:
9597 #endif // FEATURE_SIMD
9598 #ifdef FEATURE_HW_INTRINSICS
9599                     case GT_HW_INTRINSIC_CHK:
9600 #endif // FEATURE_HW_INTRINSICS
9601                     {
9602                         // Add in a call to an error routine.
9603                         fgSetRngChkTarget(tree, false);
9604                         break;
9605                     }
9606
9607 #if FEATURE_FIXED_OUT_ARGS
9608                     case GT_CALL:
9609                     {
9610                         GenTreeCall* call = tree->AsCall();
9611                         // Fast tail calls use the caller-supplied scratch
9612                         // space so have no impact on this method's outgoing arg size.
9613                         if (!call->IsFastTailCall())
9614                         {
9615                             // Update outgoing arg size to handle this call
9616                             const unsigned thisCallOutAreaSize = call->fgArgInfo->GetOutArgSize();
9617                             assert(thisCallOutAreaSize >= MIN_ARG_AREA_FOR_CALL);
9618
9619                             if (thisCallOutAreaSize > outgoingArgSpaceSize)
9620                             {
9621                                 outgoingArgSpaceSize = thisCallOutAreaSize;
9622                                 JITDUMP("Bumping outgoingArgSpaceSize to %u for call [%06d]\n", outgoingArgSpaceSize,
9623                                         dspTreeID(tree));
9624                             }
9625                             else
9626                             {
9627                                 JITDUMP("outgoingArgSpaceSize %u sufficient for call [%06d], which needs %u\n",
9628                                         outgoingArgSpaceSize, dspTreeID(tree), thisCallOutAreaSize);
9629                             }
9630                         }
9631                         else
9632                         {
9633                             JITDUMP("outgoingArgSpaceSize not impacted by fast tail call [%06d]\n", dspTreeID(tree));
9634                         }
9635                         break;
9636                     }
9637 #endif // FEATURE_FIXED_OUT_ARGS
9638
9639                     default:
9640                     {
9641                         // No other operators need processing.
9642                         break;
9643                     }
9644                 }
9645             } // foreach gtNext
9646         }     // foreach Stmt
9647     }         // foreach BB
9648
9649 #if FEATURE_FIXED_OUT_ARGS
9650     // Finish computing the outgoing args area size
9651     //
9652     // Need to make sure the MIN_ARG_AREA_FOR_CALL space is added to the frame if:
9653     // 1. there are calls to THROW_HEPLPER methods.
9654     // 2. we are generating profiling Enter/Leave/TailCall hooks. This will ensure
9655     //    that even methods without any calls will have outgoing arg area space allocated.
9656     //
9657     // An example for these two cases is Windows Amd64, where the ABI requires to have 4 slots for
9658     // the outgoing arg space if the method makes any calls.
9659     if (outgoingArgSpaceSize < MIN_ARG_AREA_FOR_CALL)
9660     {
9661         if (compUsesThrowHelper || compIsProfilerHookNeeded())
9662         {
9663             outgoingArgSpaceSize = MIN_ARG_AREA_FOR_CALL;
9664             JITDUMP("Bumping outgoingArgSpaceSize to %u for throw helper or profile hook", outgoingArgSpaceSize);
9665         }
9666     }
9667
9668     // If a function has localloc, we will need to move the outgoing arg space when the
9669     // localloc happens. When we do this, we need to maintain stack alignment. To avoid
9670     // leaving alignment-related holes when doing this move, make sure the outgoing
9671     // argument space size is a multiple of the stack alignment by aligning up to the next
9672     // stack alignment boundary.
9673     if (compLocallocUsed)
9674     {
9675         outgoingArgSpaceSize = (unsigned)roundUp(outgoingArgSpaceSize, STACK_ALIGN);
9676         JITDUMP("Bumping outgoingArgSpaceSize to %u for localloc", outgoingArgSpaceSize);
9677     }
9678
9679     // Publish the final value and mark it as read only so any update
9680     // attempt later will cause an assert.
9681     lvaOutgoingArgSpaceSize = outgoingArgSpaceSize;
9682     lvaOutgoingArgSpaceSize.MarkAsReadOnly();
9683
9684 #endif // FEATURE_FIXED_OUT_ARGS
9685
9686 #ifdef DEBUG
9687     if (verbose && fgRngChkThrowAdded)
9688     {
9689         printf("\nAfter fgSimpleLowering() added some RngChk throw blocks");
9690         fgDispBasicBlocks();
9691         fgDispHandlerTab();
9692         printf("\n");
9693     }
9694 #endif
9695 }
9696
9697 /*****************************************************************************
9698  */
9699
9700 void Compiler::fgUpdateRefCntForClone(BasicBlock* addedToBlock, GenTree* clonedTree)
9701 {
9702     assert(clonedTree->gtOper != GT_STMT);
9703
9704     if (lvaLocalVarRefCounted)
9705     {
9706         compCurBB = addedToBlock;
9707         IncLclVarRefCountsVisitor::WalkTree(this, clonedTree);
9708     }
9709 }
9710
9711 /*****************************************************************************
9712  */
9713
9714 void Compiler::fgUpdateRefCntForExtract(GenTree* wholeTree, GenTree* keptTree)
9715 {
9716     if (lvaLocalVarRefCounted)
9717     {
9718         /*  Update the refCnts of removed lcl vars - The problem is that
9719          *  we have to consider back the side effects trees so we first
9720          *  increment all refCnts for side effects then decrement everything
9721          *  in the statement
9722          */
9723         if (keptTree)
9724         {
9725             IncLclVarRefCountsVisitor::WalkTree(this, keptTree);
9726         }
9727
9728         DecLclVarRefCountsVisitor::WalkTree(this, wholeTree);
9729     }
9730 }
9731
9732 VARSET_VALRET_TP Compiler::fgGetVarBits(GenTree* tree)
9733 {
9734     VARSET_TP varBits(VarSetOps::MakeEmpty(this));
9735
9736     assert(tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_LCL_FLD || tree->gtOper == GT_REG_VAR);
9737
9738     unsigned int lclNum = tree->gtLclVarCommon.gtLclNum;
9739     LclVarDsc*   varDsc = lvaTable + lclNum;
9740     if (varDsc->lvTracked)
9741     {
9742         VarSetOps::AddElemD(this, varBits, varDsc->lvVarIndex);
9743     }
9744     // We have to check type of root tree, not Local Var descriptor because
9745     // for legacy backend we promote TYP_STRUCT to TYP_INT if it is an unused or
9746     // independently promoted non-argument struct local.
9747     // For more details see Compiler::raAssignVars() method.
9748     else if (tree->gtType == TYP_STRUCT && varDsc->lvPromoted)
9749     {
9750 #ifndef LEGACY_BACKEND
9751         assert(varDsc->lvType == TYP_STRUCT);
9752 #endif
9753         for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i)
9754         {
9755             noway_assert(lvaTable[i].lvIsStructField);
9756             if (lvaTable[i].lvTracked)
9757             {
9758                 unsigned varIndex = lvaTable[i].lvVarIndex;
9759                 noway_assert(varIndex < lvaTrackedCount);
9760                 VarSetOps::AddElemD(this, varBits, varIndex);
9761             }
9762         }
9763     }
9764     return varBits;
9765 }
9766
9767 /*****************************************************************************
9768  *
9769  *  Find and remove any basic blocks that are useless (e.g. they have not been
9770  *  imported because they are not reachable, or they have been optimized away).
9771  */
9772
9773 void Compiler::fgRemoveEmptyBlocks()
9774 {
9775     BasicBlock* cur;
9776     BasicBlock* nxt;
9777
9778     /* If we remove any blocks, we'll have to do additional work */
9779
9780     unsigned removedBlks = 0;
9781
9782     for (cur = fgFirstBB; cur != nullptr; cur = nxt)
9783     {
9784         /* Get hold of the next block (in case we delete 'cur') */
9785
9786         nxt = cur->bbNext;
9787
9788         /* Should this block be removed? */
9789
9790         if (!(cur->bbFlags & BBF_IMPORTED))
9791         {
9792             noway_assert(cur->isEmpty());
9793
9794             if (ehCanDeleteEmptyBlock(cur))
9795             {
9796                 /* Mark the block as removed */
9797
9798                 cur->bbFlags |= BBF_REMOVED;
9799
9800                 /* Remember that we've removed a block from the list */
9801
9802                 removedBlks++;
9803
9804 #ifdef DEBUG
9805                 if (verbose)
9806                 {
9807                     printf("BB%02u was not imported, marked as removed (%d)\n", cur->bbNum, removedBlks);
9808                 }
9809 #endif // DEBUG
9810
9811                 /* Drop the block from the list */
9812
9813                 fgUnlinkBlock(cur);
9814             }
9815             else
9816             {
9817                 // We were prevented from deleting this block by EH normalization. Mark the block as imported.
9818                 cur->bbFlags |= BBF_IMPORTED;
9819             }
9820         }
9821     }
9822
9823     /* If no blocks were removed, we're done */
9824
9825     if (removedBlks == 0)
9826     {
9827         return;
9828     }
9829
9830     /*  Update all references in the exception handler table.
9831      *  Mark the new blocks as non-removable.
9832      *
9833      *  We may have made the entire try block unreachable.
9834      *  Check for this case and remove the entry from the EH table.
9835      */
9836
9837     unsigned  XTnum;
9838     EHblkDsc* HBtab;
9839     INDEBUG(unsigned delCnt = 0;)
9840
9841     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
9842     {
9843     AGAIN:
9844         /* If the beginning of the try block was not imported, we
9845          * need to remove the entry from the EH table. */
9846
9847         if (HBtab->ebdTryBeg->bbFlags & BBF_REMOVED)
9848         {
9849             noway_assert(!(HBtab->ebdTryBeg->bbFlags & BBF_IMPORTED));
9850 #ifdef DEBUG
9851             if (verbose)
9852             {
9853                 printf("Beginning of try block (BB%02u) not imported "
9854                        "- remove index #%u from the EH table\n",
9855                        HBtab->ebdTryBeg->bbNum, XTnum + delCnt);
9856             }
9857             delCnt++;
9858 #endif // DEBUG
9859
9860             fgRemoveEHTableEntry(XTnum);
9861
9862             if (XTnum < compHndBBtabCount)
9863             {
9864                 // There are more entries left to process, so do more. Note that
9865                 // HBtab now points to the next entry, that we copied down to the
9866                 // current slot. XTnum also stays the same.
9867                 goto AGAIN;
9868             }
9869
9870             break; // no more entries (we deleted the last one), so exit the loop
9871         }
9872
9873 /* At this point we know we have a valid try block */
9874
9875 #ifdef DEBUG
9876         assert(HBtab->ebdTryBeg->bbFlags & BBF_IMPORTED);
9877         assert(HBtab->ebdTryBeg->bbFlags & BBF_DONT_REMOVE);
9878
9879         assert(HBtab->ebdHndBeg->bbFlags & BBF_IMPORTED);
9880         assert(HBtab->ebdHndBeg->bbFlags & BBF_DONT_REMOVE);
9881
9882         if (HBtab->HasFilter())
9883         {
9884             assert(HBtab->ebdFilter->bbFlags & BBF_IMPORTED);
9885             assert(HBtab->ebdFilter->bbFlags & BBF_DONT_REMOVE);
9886         }
9887 #endif // DEBUG
9888
9889         fgSkipRmvdBlocks(HBtab);
9890     } /* end of the for loop over XTnum */
9891
9892     // Renumber the basic blocks
9893     JITDUMP("\nRenumbering the basic blocks for fgRemoveEmptyBlocks\n");
9894     fgRenumberBlocks();
9895
9896 #ifdef DEBUG
9897     fgVerifyHandlerTab();
9898 #endif // DEBUG
9899 }
9900
9901 /*****************************************************************************
9902  *
9903  * Remove a useless statement from a basic block.
9904  * The default is to decrement ref counts of included vars
9905  *
9906  */
9907
9908 void Compiler::fgRemoveStmt(BasicBlock* block,
9909                             GenTree*    node,
9910                             // whether to decrement ref counts for tracked vars in statement
9911                             bool updateRefCount)
9912 {
9913     noway_assert(node);
9914     assert(fgOrder == FGOrderTree);
9915
9916     GenTreeStmt* tree = block->firstStmt();
9917     GenTreeStmt* stmt = node->AsStmt();
9918
9919 #ifdef DEBUG
9920     if (verbose &&
9921         stmt->gtStmtExpr->gtOper != GT_NOP) // Don't print if it is a GT_NOP. Too much noise from the inliner.
9922     {
9923         printf("\nRemoving statement ");
9924         printTreeID(stmt);
9925         printf(" in BB%02u as useless:\n", block->bbNum);
9926         gtDispTree(stmt);
9927     }
9928 #endif // DEBUG
9929
9930     if (opts.compDbgCode && stmt->gtPrev != stmt && stmt->gtStmtILoffsx != BAD_IL_OFFSET)
9931     {
9932         /* TODO: For debuggable code, should we remove significant
9933            statement boundaries. Or should we leave a GT_NO_OP in its place? */
9934     }
9935
9936     /* Is it the first statement in the list? */
9937
9938     GenTreeStmt* firstStmt = block->firstStmt();
9939     if (firstStmt == stmt)
9940     {
9941         if (firstStmt->gtNext == nullptr)
9942         {
9943             assert(firstStmt == block->lastStmt());
9944
9945             /* this is the only statement - basic block becomes empty */
9946             block->bbTreeList = nullptr;
9947         }
9948         else
9949         {
9950             block->bbTreeList         = tree->gtNext;
9951             block->bbTreeList->gtPrev = tree->gtPrev;
9952         }
9953         goto DONE;
9954     }
9955
9956     /* Is it the last statement in the list? */
9957
9958     if (stmt == block->lastStmt())
9959     {
9960         stmt->gtPrev->gtNext      = nullptr;
9961         block->bbTreeList->gtPrev = stmt->gtPrev;
9962         goto DONE;
9963     }
9964
9965     tree = stmt->gtPrevStmt;
9966     noway_assert(tree);
9967
9968     tree->gtNext         = stmt->gtNext;
9969     stmt->gtNext->gtPrev = tree;
9970
9971 DONE:
9972     fgStmtRemoved = true;
9973
9974     noway_assert(!optValnumCSE_phase);
9975
9976     if (updateRefCount)
9977     {
9978         if (fgStmtListThreaded)
9979         {
9980             DecLclVarRefCountsVisitor::WalkTree(this, stmt->gtStmtExpr);
9981         }
9982     }
9983
9984 #ifdef DEBUG
9985     if (verbose)
9986     {
9987         if (block->bbTreeList == nullptr)
9988         {
9989             printf("\nBB%02u becomes empty", block->bbNum);
9990         }
9991         printf("\n");
9992     }
9993 #endif // DEBUG
9994 }
9995
9996 /******************************************************************************/
9997 // Returns true if the operator is involved in control-flow
9998 // TODO-Cleanup: Move this into genTreeKinds in genTree.h
9999
10000 inline bool OperIsControlFlow(genTreeOps oper)
10001 {
10002     switch (oper)
10003     {
10004         case GT_JTRUE:
10005         case GT_JCMP:
10006         case GT_JCC:
10007         case GT_SWITCH:
10008         case GT_LABEL:
10009
10010         case GT_CALL:
10011         case GT_JMP:
10012
10013         case GT_RETURN:
10014         case GT_RETFILT:
10015 #if !FEATURE_EH_FUNCLETS
10016         case GT_END_LFIN:
10017 #endif // !FEATURE_EH_FUNCLETS
10018             return true;
10019
10020         default:
10021             return false;
10022     }
10023 }
10024
10025 /******************************************************************************
10026  *  Tries to throw away a stmt. The statement can be anywhere in block->bbTreeList.
10027  *  Returns true if it did remove the statement.
10028  */
10029
10030 bool Compiler::fgCheckRemoveStmt(BasicBlock* block, GenTree* node)
10031 {
10032     if (opts.compDbgCode)
10033     {
10034         return false;
10035     }
10036
10037     GenTreeStmt* stmt = node->AsStmt();
10038
10039     GenTree*   tree = stmt->gtStmtExpr;
10040     genTreeOps oper = tree->OperGet();
10041
10042     if (OperIsControlFlow(oper) || GenTree::OperIsHWIntrinsic(oper) || oper == GT_NO_OP)
10043     {
10044         return false;
10045     }
10046
10047     // TODO: Use a recursive version of gtNodeHasSideEffects()
10048     if (tree->gtFlags & GTF_SIDE_EFFECT)
10049     {
10050         return false;
10051     }
10052
10053     fgRemoveStmt(block, stmt);
10054     return true;
10055 }
10056
10057 /****************************************************************************************************
10058  *
10059  *
10060  */
10061 bool Compiler::fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext)
10062 {
10063     if ((block == nullptr) || (bNext == nullptr))
10064     {
10065         return false;
10066     }
10067
10068     noway_assert(block->bbNext == bNext);
10069
10070     if (block->bbJumpKind != BBJ_NONE)
10071     {
10072         return false;
10073     }
10074
10075     // If the next block has multiple incoming edges, we can still compact if the first block is empty.
10076     // However, not if it is the beginning of a handler.
10077     if (bNext->countOfInEdges() != 1 &&
10078         (!block->isEmpty() || (block->bbFlags & BBF_FUNCLET_BEG) || (block->bbCatchTyp != BBCT_NONE)))
10079     {
10080         return false;
10081     }
10082
10083     if (bNext->bbFlags & BBF_DONT_REMOVE)
10084     {
10085         return false;
10086     }
10087
10088     // Don't compact the first block if it was specially created as a scratch block.
10089     if (fgBBisScratch(block))
10090     {
10091         return false;
10092     }
10093
10094 #if defined(_TARGET_ARM_)
10095     // We can't compact a finally target block, as we need to generate special code for such blocks during code
10096     // generation
10097     if ((bNext->bbFlags & BBF_FINALLY_TARGET) != 0)
10098         return false;
10099 #endif
10100
10101     // We don't want to compact blocks that are in different Hot/Cold regions
10102     //
10103     if (fgInDifferentRegions(block, bNext))
10104     {
10105         return false;
10106     }
10107
10108     // We cannot compact two blocks in different EH regions.
10109     //
10110     if (fgCanRelocateEHRegions)
10111     {
10112         if (!BasicBlock::sameEHRegion(block, bNext))
10113         {
10114             return false;
10115         }
10116     }
10117     // if there is a switch predecessor don't bother because we'd have to update the uniquesuccs as well
10118     // (if they are valid)
10119     for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext)
10120     {
10121         if (pred->flBlock->bbJumpKind == BBJ_SWITCH)
10122         {
10123             return false;
10124         }
10125     }
10126
10127     return true;
10128 }
10129
10130 /*****************************************************************************************************
10131  *
10132  *  Function called to compact two given blocks in the flowgraph
10133  *  Assumes that all necessary checks have been performed,
10134  *  i.e. fgCanCompactBlocks returns true.
10135  *
10136  *  Uses for this function - whenever we change links, insert blocks,...
10137  *  It will keep the flowgraph data in synch - bbNum, bbRefs, bbPreds
10138  */
10139
10140 void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext)
10141 {
10142     noway_assert(block != nullptr);
10143     noway_assert((block->bbFlags & BBF_REMOVED) == 0);
10144     noway_assert(block->bbJumpKind == BBJ_NONE);
10145
10146     noway_assert(bNext == block->bbNext);
10147     noway_assert(bNext != nullptr);
10148     noway_assert((bNext->bbFlags & BBF_REMOVED) == 0);
10149     noway_assert(bNext->countOfInEdges() == 1 || block->isEmpty());
10150     noway_assert(bNext->bbPreds);
10151
10152 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10153     noway_assert((bNext->bbFlags & BBF_FINALLY_TARGET) == 0);
10154 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10155
10156     // Make sure the second block is not the start of a TRY block or an exception handler
10157
10158     noway_assert(bNext->bbCatchTyp == BBCT_NONE);
10159     noway_assert((bNext->bbFlags & BBF_TRY_BEG) == 0);
10160     noway_assert((bNext->bbFlags & BBF_DONT_REMOVE) == 0);
10161
10162     /* both or none must have an exception handler */
10163     noway_assert(block->hasTryIndex() == bNext->hasTryIndex());
10164
10165 #ifdef DEBUG
10166     if (verbose)
10167     {
10168         printf("\nCompacting blocks BB%02u and BB%02u:\n", block->bbNum, bNext->bbNum);
10169     }
10170 #endif
10171
10172     if (bNext->countOfInEdges() > 1)
10173     {
10174         JITDUMP("Second block has multiple incoming edges\n");
10175
10176         assert(block->isEmpty());
10177         block->bbFlags |= BBF_JMP_TARGET;
10178         for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext)
10179         {
10180             fgReplaceJumpTarget(pred->flBlock, block, bNext);
10181
10182             if (pred->flBlock != block)
10183             {
10184                 fgAddRefPred(block, pred->flBlock);
10185             }
10186         }
10187         bNext->bbPreds = nullptr;
10188     }
10189     else
10190     {
10191         noway_assert(bNext->bbPreds->flNext == nullptr);
10192         noway_assert(bNext->bbPreds->flBlock == block);
10193     }
10194
10195     /* Start compacting - move all the statements in the second block to the first block */
10196
10197     // First move any phi definitions of the second block after the phi defs of the first.
10198     // TODO-CQ: This may be the wrong thing to do.  If we're compacting blocks, it's because a
10199     // control-flow choice was constant-folded away.  So probably phi's need to go away,
10200     // as well, in favor of one of the incoming branches.  Or at least be modified.
10201
10202     assert(block->IsLIR() == bNext->IsLIR());
10203     if (block->IsLIR())
10204     {
10205         LIR::Range& blockRange = LIR::AsRange(block);
10206         LIR::Range& nextRange  = LIR::AsRange(bNext);
10207
10208         // Does the next block have any phis?
10209         GenTree*           nextFirstNonPhi = nullptr;
10210         LIR::ReadOnlyRange nextPhis        = nextRange.PhiNodes();
10211         if (!nextPhis.IsEmpty())
10212         {
10213             GenTree* blockLastPhi = blockRange.LastPhiNode();
10214             nextFirstNonPhi       = nextPhis.LastNode()->gtNext;
10215
10216             LIR::Range phisToMove = nextRange.Remove(std::move(nextPhis));
10217             blockRange.InsertAfter(blockLastPhi, std::move(phisToMove));
10218         }
10219         else
10220         {
10221             nextFirstNonPhi = nextRange.FirstNode();
10222         }
10223
10224         // Does the block have any other code?
10225         if (nextFirstNonPhi != nullptr)
10226         {
10227             LIR::Range nextNodes = nextRange.Remove(nextFirstNonPhi, nextRange.LastNode());
10228             blockRange.InsertAtEnd(std::move(nextNodes));
10229         }
10230     }
10231     else
10232     {
10233         GenTree* blkNonPhi1   = block->FirstNonPhiDef();
10234         GenTree* bNextNonPhi1 = bNext->FirstNonPhiDef();
10235         GenTree* blkFirst     = block->firstStmt();
10236         GenTree* bNextFirst   = bNext->firstStmt();
10237
10238         // Does the second have any phis?
10239         if (bNextFirst != nullptr && bNextFirst != bNextNonPhi1)
10240         {
10241             GenTree* bNextLast = bNextFirst->gtPrev;
10242             assert(bNextLast->gtNext == nullptr);
10243
10244             // Does "blk" have phis?
10245             if (blkNonPhi1 != blkFirst)
10246             {
10247                 // Yes, has phis.
10248                 // Insert after the last phi of "block."
10249                 // First, bNextPhis after last phi of block.
10250                 GenTree* blkLastPhi;
10251                 if (blkNonPhi1 != nullptr)
10252                 {
10253                     blkLastPhi = blkNonPhi1->gtPrev;
10254                 }
10255                 else
10256                 {
10257                     blkLastPhi = blkFirst->gtPrev;
10258                 }
10259
10260                 blkLastPhi->gtNext = bNextFirst;
10261                 bNextFirst->gtPrev = blkLastPhi;
10262
10263                 // Now, rest of "block" after last phi of "bNext".
10264                 GenTree* bNextLastPhi = nullptr;
10265                 if (bNextNonPhi1 != nullptr)
10266                 {
10267                     bNextLastPhi = bNextNonPhi1->gtPrev;
10268                 }
10269                 else
10270                 {
10271                     bNextLastPhi = bNextFirst->gtPrev;
10272                 }
10273
10274                 bNextLastPhi->gtNext = blkNonPhi1;
10275                 if (blkNonPhi1 != nullptr)
10276                 {
10277                     blkNonPhi1->gtPrev = bNextLastPhi;
10278                 }
10279                 else
10280                 {
10281                     // block has no non phis, so make the last statement be the last added phi.
10282                     blkFirst->gtPrev = bNextLastPhi;
10283                 }
10284
10285                 // Now update the bbTreeList of "bNext".
10286                 bNext->bbTreeList = bNextNonPhi1;
10287                 if (bNextNonPhi1 != nullptr)
10288                 {
10289                     bNextNonPhi1->gtPrev = bNextLast;
10290                 }
10291             }
10292             else
10293             {
10294                 if (blkFirst != nullptr) // If "block" has no statements, fusion will work fine...
10295                 {
10296                     // First, bNextPhis at start of block.
10297                     GenTree* blkLast  = blkFirst->gtPrev;
10298                     block->bbTreeList = bNextFirst;
10299                     // Now, rest of "block" (if it exists) after last phi of "bNext".
10300                     GenTree* bNextLastPhi = nullptr;
10301                     if (bNextNonPhi1 != nullptr)
10302                     {
10303                         // There is a first non phi, so the last phi is before it.
10304                         bNextLastPhi = bNextNonPhi1->gtPrev;
10305                     }
10306                     else
10307                     {
10308                         // All the statements are phi defns, so the last one is the prev of the first.
10309                         bNextLastPhi = bNextFirst->gtPrev;
10310                     }
10311                     bNextFirst->gtPrev   = blkLast;
10312                     bNextLastPhi->gtNext = blkFirst;
10313                     blkFirst->gtPrev     = bNextLastPhi;
10314                     // Now update the bbTreeList of "bNext"
10315                     bNext->bbTreeList = bNextNonPhi1;
10316                     if (bNextNonPhi1 != nullptr)
10317                     {
10318                         bNextNonPhi1->gtPrev = bNextLast;
10319                     }
10320                 }
10321             }
10322         }
10323
10324         // Now proceed with the updated bbTreeLists.
10325         GenTree* stmtList1 = block->firstStmt();
10326         GenTree* stmtList2 = bNext->firstStmt();
10327
10328         /* the block may have an empty list */
10329
10330         if (stmtList1)
10331         {
10332             GenTree* stmtLast1 = block->lastStmt();
10333
10334             /* The second block may be a GOTO statement or something with an empty bbTreeList */
10335             if (stmtList2)
10336             {
10337                 GenTree* stmtLast2 = bNext->lastStmt();
10338
10339                 /* append list2 to list 1 */
10340
10341                 stmtLast1->gtNext = stmtList2;
10342                 stmtList2->gtPrev = stmtLast1;
10343                 stmtList1->gtPrev = stmtLast2;
10344             }
10345         }
10346         else
10347         {
10348             /* block was formerly empty and now has bNext's statements */
10349             block->bbTreeList = stmtList2;
10350         }
10351     }
10352
10353     // Note we could update the local variable weights here by
10354     // calling lvaMarkLocalVars, with the block and weight adjustment.
10355
10356     // If either block or bNext has a profile weight
10357     // or if both block and bNext have non-zero weights
10358     // then we select the highest weight block.
10359
10360     if (block->hasProfileWeight() || bNext->hasProfileWeight() || (block->bbWeight && bNext->bbWeight))
10361     {
10362         // We are keeping block so update its fields
10363         // when bNext has a greater weight
10364
10365         if (block->bbWeight < bNext->bbWeight)
10366         {
10367             block->bbWeight = bNext->bbWeight;
10368
10369             block->bbFlags |= (bNext->bbFlags & BBF_PROF_WEIGHT); // Set the profile weight flag (if necessary)
10370             if (block->bbWeight != 0)
10371             {
10372                 block->bbFlags &= ~BBF_RUN_RARELY; // Clear any RarelyRun flag
10373             }
10374         }
10375     }
10376     // otherwise if either block has a zero weight we select the zero weight
10377     else
10378     {
10379         noway_assert((block->bbWeight == BB_ZERO_WEIGHT) || (bNext->bbWeight == BB_ZERO_WEIGHT));
10380         block->bbWeight = BB_ZERO_WEIGHT;
10381         block->bbFlags |= BBF_RUN_RARELY; // Set the RarelyRun flag
10382     }
10383
10384     /* set the right links */
10385
10386     block->bbJumpKind = bNext->bbJumpKind;
10387     VarSetOps::AssignAllowUninitRhs(this, block->bbLiveOut, bNext->bbLiveOut);
10388
10389     // Update the beginning and ending IL offsets (bbCodeOffs and bbCodeOffsEnd).
10390     // Set the beginning IL offset to the minimum, and the ending offset to the maximum, of the respective blocks.
10391     // If one block has an unknown offset, we take the other block.
10392     // We are merging into 'block', so if its values are correct, just leave them alone.
10393     // TODO: we should probably base this on the statements within.
10394
10395     if (block->bbCodeOffs == BAD_IL_OFFSET)
10396     {
10397         block->bbCodeOffs = bNext->bbCodeOffs; // If they are both BAD_IL_OFFSET, this doesn't change anything.
10398     }
10399     else if (bNext->bbCodeOffs != BAD_IL_OFFSET)
10400     {
10401         // The are both valid offsets; compare them.
10402         if (block->bbCodeOffs > bNext->bbCodeOffs)
10403         {
10404             block->bbCodeOffs = bNext->bbCodeOffs;
10405         }
10406     }
10407
10408     if (block->bbCodeOffsEnd == BAD_IL_OFFSET)
10409     {
10410         block->bbCodeOffsEnd = bNext->bbCodeOffsEnd; // If they are both BAD_IL_OFFSET, this doesn't change anything.
10411     }
10412     else if (bNext->bbCodeOffsEnd != BAD_IL_OFFSET)
10413     {
10414         // The are both valid offsets; compare them.
10415         if (block->bbCodeOffsEnd < bNext->bbCodeOffsEnd)
10416         {
10417             block->bbCodeOffsEnd = bNext->bbCodeOffsEnd;
10418         }
10419     }
10420
10421     if (((block->bbFlags & BBF_INTERNAL) != 0) && ((bNext->bbFlags & BBF_INTERNAL) == 0))
10422     {
10423         // If 'block' is an internal block and 'bNext' isn't, then adjust the flags set on 'block'.
10424         block->bbFlags &= ~BBF_INTERNAL; // Clear the BBF_INTERNAL flag
10425         block->bbFlags |= BBF_IMPORTED;  // Set the BBF_IMPORTED flag
10426     }
10427
10428     /* Update the flags for block with those found in bNext */
10429
10430     block->bbFlags |= (bNext->bbFlags & BBF_COMPACT_UPD);
10431
10432     /* mark bNext as removed */
10433
10434     bNext->bbFlags |= BBF_REMOVED;
10435
10436     /* Unlink bNext and update all the marker pointers if necessary */
10437
10438     fgUnlinkRange(block->bbNext, bNext);
10439
10440     // If bNext was the last block of a try or handler, update the EH table.
10441
10442     ehUpdateForDeletedBlock(bNext);
10443
10444     /* If we're collapsing a block created after the dominators are
10445        computed, rename the block and reuse dominator information from
10446        the other block */
10447     if (fgDomsComputed && block->bbNum > fgDomBBcount)
10448     {
10449         BlockSetOps::Assign(this, block->bbReach, bNext->bbReach);
10450         BlockSetOps::ClearD(this, bNext->bbReach);
10451
10452         block->bbIDom = bNext->bbIDom;
10453         bNext->bbIDom = nullptr;
10454
10455         // In this case, there's no need to update the preorder and postorder numbering
10456         // since we're changing the bbNum, this makes the basic block all set.
10457         block->bbNum = bNext->bbNum;
10458     }
10459
10460     /* Set the jump targets */
10461
10462     switch (bNext->bbJumpKind)
10463     {
10464         case BBJ_CALLFINALLY:
10465             // Propagate RETLESS property
10466             block->bbFlags |= (bNext->bbFlags & BBF_RETLESS_CALL);
10467
10468             __fallthrough;
10469
10470         case BBJ_COND:
10471         case BBJ_ALWAYS:
10472         case BBJ_EHCATCHRET:
10473             block->bbJumpDest = bNext->bbJumpDest;
10474
10475             /* Update the predecessor list for 'bNext->bbJumpDest' */
10476             fgReplacePred(bNext->bbJumpDest, bNext, block);
10477
10478             /* Update the predecessor list for 'bNext->bbNext' if it is different than 'bNext->bbJumpDest' */
10479             if (bNext->bbJumpKind == BBJ_COND && bNext->bbJumpDest != bNext->bbNext)
10480             {
10481                 fgReplacePred(bNext->bbNext, bNext, block);
10482             }
10483             break;
10484
10485         case BBJ_NONE:
10486             /* Update the predecessor list for 'bNext->bbNext' */
10487             fgReplacePred(bNext->bbNext, bNext, block);
10488             break;
10489
10490         case BBJ_EHFILTERRET:
10491             fgReplacePred(bNext->bbJumpDest, bNext, block);
10492             break;
10493
10494         case BBJ_EHFINALLYRET:
10495         {
10496             unsigned  hndIndex = block->getHndIndex();
10497             EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
10498
10499             if (ehDsc->HasFinallyHandler()) // No need to do this for fault handlers
10500             {
10501                 BasicBlock* begBlk;
10502                 BasicBlock* endBlk;
10503                 ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
10504
10505                 BasicBlock* finBeg = ehDsc->ebdHndBeg;
10506
10507                 for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
10508                 {
10509                     if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
10510                     {
10511                         continue;
10512                     }
10513
10514                     noway_assert(bcall->isBBCallAlwaysPair());
10515                     fgReplacePred(bcall->bbNext, bNext, block);
10516                 }
10517             }
10518         }
10519         break;
10520
10521         case BBJ_THROW:
10522         case BBJ_RETURN:
10523             /* no jumps or fall through blocks to set here */
10524             break;
10525
10526         case BBJ_SWITCH:
10527             block->bbJumpSwt = bNext->bbJumpSwt;
10528             // We are moving the switch jump from bNext to block.  Examine the jump targets
10529             // of the BBJ_SWITCH at bNext and replace the predecessor to 'bNext' with ones to 'block'
10530             fgChangeSwitchBlock(bNext, block);
10531             break;
10532
10533         default:
10534             noway_assert(!"Unexpected bbJumpKind");
10535             break;
10536     }
10537
10538     fgUpdateLoopsAfterCompacting(block, bNext);
10539
10540 #if DEBUG
10541     if (verbose && 0)
10542     {
10543         printf("\nAfter compacting:\n");
10544         fgDispBasicBlocks(false);
10545     }
10546 #endif
10547
10548 #if DEBUG
10549     if (JitConfig.JitSlowDebugChecksEnabled() != 0)
10550     {
10551         // Make sure that the predecessor lists are accurate
10552         fgDebugCheckBBlist();
10553     }
10554 #endif // DEBUG
10555 }
10556
10557 void Compiler::fgUpdateLoopsAfterCompacting(BasicBlock* block, BasicBlock* bNext)
10558 {
10559     /* Check if the removed block is not part the loop table */
10560     noway_assert(bNext);
10561
10562     for (unsigned loopNum = 0; loopNum < optLoopCount; loopNum++)
10563     {
10564         /* Some loops may have been already removed by
10565          * loop unrolling or conditional folding */
10566
10567         if (optLoopTable[loopNum].lpFlags & LPFLG_REMOVED)
10568         {
10569             continue;
10570         }
10571
10572         /* Check the loop head (i.e. the block preceding the loop) */
10573
10574         if (optLoopTable[loopNum].lpHead == bNext)
10575         {
10576             optLoopTable[loopNum].lpHead = block;
10577         }
10578
10579         /* Check the loop bottom */
10580
10581         if (optLoopTable[loopNum].lpBottom == bNext)
10582         {
10583             optLoopTable[loopNum].lpBottom = block;
10584         }
10585
10586         /* Check the loop exit */
10587
10588         if (optLoopTable[loopNum].lpExit == bNext)
10589         {
10590             noway_assert(optLoopTable[loopNum].lpExitCnt == 1);
10591             optLoopTable[loopNum].lpExit = block;
10592         }
10593
10594         /* Check the loop entry */
10595
10596         if (optLoopTable[loopNum].lpEntry == bNext)
10597         {
10598             optLoopTable[loopNum].lpEntry = block;
10599         }
10600     }
10601 }
10602
10603 /*****************************************************************************************************
10604  *
10605  *  Function called to remove a block when it is unreachable.
10606  *
10607  *  This function cannot remove the first block.
10608  */
10609
10610 void Compiler::fgUnreachableBlock(BasicBlock* block)
10611 {
10612     // genReturnBB should never be removed, as we might have special hookups there.
10613     // Therefore, we should never come here to remove the statements in the genReturnBB block.
10614     // For example, <BUGNUM> in VSW 364383, </BUGNUM>
10615     // the profiler hookup needs to have the "void GT_RETURN" statement
10616     // to properly set the info.compProfilerCallback flag.
10617     noway_assert(block != genReturnBB);
10618
10619     if (block->bbFlags & BBF_REMOVED)
10620     {
10621         return;
10622     }
10623
10624 /* Removing an unreachable block */
10625
10626 #ifdef DEBUG
10627     if (verbose)
10628     {
10629         printf("\nRemoving unreachable BB%02u\n", block->bbNum);
10630     }
10631 #endif // DEBUG
10632
10633     noway_assert(block->bbPrev != nullptr); // Can use this function to remove the first block
10634
10635 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10636     assert(!block->bbPrev->isBBCallAlwaysPair()); // can't remove the BBJ_ALWAYS of a BBJ_CALLFINALLY / BBJ_ALWAYS pair
10637 #endif                                            // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10638
10639     /* First walk the statement trees in this basic block and delete each stmt */
10640
10641     /* Make the block publicly available */
10642     compCurBB = block;
10643
10644     if (block->IsLIR())
10645     {
10646         LIR::Range& blockRange = LIR::AsRange(block);
10647         if (!blockRange.IsEmpty())
10648         {
10649             blockRange.Delete(this, block, blockRange.FirstNode(), blockRange.LastNode());
10650         }
10651     }
10652     else
10653     {
10654         // TODO-Cleanup: I'm not sure why this happens -- if the block is unreachable, why does it have phis?
10655         // Anyway, remove any phis.
10656
10657         GenTree* firstNonPhi = block->FirstNonPhiDef();
10658         if (block->bbTreeList != firstNonPhi)
10659         {
10660             if (firstNonPhi != nullptr)
10661             {
10662                 firstNonPhi->gtPrev = block->lastStmt();
10663             }
10664             block->bbTreeList = firstNonPhi;
10665         }
10666
10667         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
10668         {
10669             fgRemoveStmt(block, stmt);
10670         }
10671         noway_assert(block->bbTreeList == nullptr);
10672     }
10673
10674     /* Next update the loop table and bbWeights */
10675     optUpdateLoopsBeforeRemoveBlock(block);
10676
10677     /* Mark the block as removed */
10678     block->bbFlags |= BBF_REMOVED;
10679
10680     /* update bbRefs and bbPreds for the blocks reached by this block */
10681     fgRemoveBlockAsPred(block);
10682 }
10683
10684 /*****************************************************************************************************
10685  *
10686  *  Function called to remove or morph a jump when we jump to the same
10687  *  block when both the condition is true or false.
10688  */
10689 void Compiler::fgRemoveConditionalJump(BasicBlock* block)
10690 {
10691     noway_assert(block->bbJumpKind == BBJ_COND && block->bbJumpDest == block->bbNext);
10692     assert(compRationalIRForm == block->IsLIR());
10693
10694     flowList* flow = fgGetPredForBlock(block->bbNext, block);
10695     noway_assert(flow->flDupCount == 2);
10696
10697     // Change the BBJ_COND to BBJ_NONE, and adjust the refCount and dupCount.
10698     block->bbJumpKind = BBJ_NONE;
10699     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
10700     --block->bbNext->bbRefs;
10701     --flow->flDupCount;
10702
10703 #ifdef DEBUG
10704     block->bbJumpDest = nullptr;
10705     if (verbose)
10706     {
10707         printf("Block BB%02u becoming a BBJ_NONE to BB%02u (jump target is the same whether the condition is true or "
10708                "false)\n",
10709                block->bbNum, block->bbNext->bbNum);
10710     }
10711 #endif
10712
10713     /* Remove the block jump condition */
10714
10715     if (block->IsLIR())
10716     {
10717         LIR::Range& blockRange = LIR::AsRange(block);
10718
10719         GenTree* test = blockRange.LastNode();
10720         assert(test->OperIsConditionalJump());
10721
10722         bool               isClosed;
10723         unsigned           sideEffects;
10724         LIR::ReadOnlyRange testRange = blockRange.GetTreeRange(test, &isClosed, &sideEffects);
10725
10726         // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable
10727         //            diffs compared to the existing backend.
10728         if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0))
10729         {
10730             // If the jump and its operands form a contiguous, side-effect-free range,
10731             // remove them.
10732             blockRange.Delete(this, block, std::move(testRange));
10733         }
10734         else
10735         {
10736             // Otherwise, just remove the jump node itself.
10737             blockRange.Remove(test, true);
10738         }
10739     }
10740     else
10741     {
10742         GenTreeStmt* test = block->lastStmt();
10743         GenTree*     tree = test->gtStmtExpr;
10744
10745         noway_assert(tree->gtOper == GT_JTRUE);
10746
10747         GenTree* sideEffList = nullptr;
10748
10749         if (tree->gtFlags & GTF_SIDE_EFFECT)
10750         {
10751             gtExtractSideEffList(tree, &sideEffList);
10752
10753             if (sideEffList)
10754             {
10755                 noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
10756 #ifdef DEBUG
10757                 if (verbose)
10758                 {
10759                     printf("Extracted side effects list from condition...\n");
10760                     gtDispTree(sideEffList);
10761                     printf("\n");
10762                 }
10763 #endif
10764             }
10765         }
10766
10767         // Delete the cond test or replace it with the side effect tree
10768         if (sideEffList == nullptr)
10769         {
10770             fgRemoveStmt(block, test);
10771         }
10772         else
10773         {
10774             test->gtStmtExpr = sideEffList;
10775
10776             fgMorphBlockStmt(block, test DEBUGARG("fgRemoveConditionalJump"));
10777         }
10778     }
10779 }
10780
10781 /*****************************************************************************************************
10782  *
10783  *  Function to return the last basic block in the main part of the function. With funclets, it is
10784  *  the block immediately before the first funclet.
10785  *  An inclusive end of the main method.
10786  */
10787
10788 BasicBlock* Compiler::fgLastBBInMainFunction()
10789 {
10790 #if FEATURE_EH_FUNCLETS
10791
10792     if (fgFirstFuncletBB != nullptr)
10793     {
10794         return fgFirstFuncletBB->bbPrev;
10795     }
10796
10797 #endif // FEATURE_EH_FUNCLETS
10798
10799     assert(fgLastBB->bbNext == nullptr);
10800
10801     return fgLastBB;
10802 }
10803
10804 /*****************************************************************************************************
10805  *
10806  *  Function to return the first basic block after the main part of the function. With funclets, it is
10807  *  the block of the first funclet.  Otherwise it is NULL if there are no funclets (fgLastBB->bbNext).
10808  *  This is equivalent to fgLastBBInMainFunction()->bbNext
10809  *  An exclusive end of the main method.
10810  */
10811
10812 BasicBlock* Compiler::fgEndBBAfterMainFunction()
10813 {
10814 #if FEATURE_EH_FUNCLETS
10815
10816     if (fgFirstFuncletBB != nullptr)
10817     {
10818         return fgFirstFuncletBB;
10819     }
10820
10821 #endif // FEATURE_EH_FUNCLETS
10822
10823     assert(fgLastBB->bbNext == nullptr);
10824
10825     return nullptr;
10826 }
10827
10828 // Removes the block from the bbPrev/bbNext chain
10829 // Updates fgFirstBB and fgLastBB if necessary
10830 // Does not update fgFirstFuncletBB or fgFirstColdBlock (fgUnlinkRange does)
10831
10832 void Compiler::fgUnlinkBlock(BasicBlock* block)
10833 {
10834     if (block->bbPrev)
10835     {
10836         block->bbPrev->bbNext = block->bbNext;
10837         if (block->bbNext)
10838         {
10839             block->bbNext->bbPrev = block->bbPrev;
10840         }
10841         else
10842         {
10843             fgLastBB = block->bbPrev;
10844         }
10845     }
10846     else
10847     {
10848         assert(block == fgFirstBB);
10849         assert(block != fgLastBB);
10850         assert((fgFirstBBScratch == nullptr) || (fgFirstBBScratch == fgFirstBB));
10851
10852         fgFirstBB         = block->bbNext;
10853         fgFirstBB->bbPrev = nullptr;
10854
10855         if (fgFirstBBScratch != nullptr)
10856         {
10857 #ifdef DEBUG
10858             // We had created an initial scratch BB, but now we're deleting it.
10859             if (verbose)
10860             {
10861                 printf("Unlinking scratch BB%02u\n", block->bbNum);
10862             }
10863 #endif // DEBUG
10864             fgFirstBBScratch = nullptr;
10865         }
10866     }
10867 }
10868
10869 /*****************************************************************************************************
10870  *
10871  *  Function called to unlink basic block range [bBeg .. bEnd] from the basic block list.
10872  *
10873  *  'bBeg' can't be the first block.
10874  */
10875
10876 void Compiler::fgUnlinkRange(BasicBlock* bBeg, BasicBlock* bEnd)
10877 {
10878     assert(bBeg != nullptr);
10879     assert(bEnd != nullptr);
10880
10881     BasicBlock* bPrev = bBeg->bbPrev;
10882     assert(bPrev != nullptr); // Can't unlink a range starting with the first block
10883
10884     bPrev->setNext(bEnd->bbNext);
10885
10886     /* If we removed the last block in the method then update fgLastBB */
10887     if (fgLastBB == bEnd)
10888     {
10889         fgLastBB = bPrev;
10890         noway_assert(fgLastBB->bbNext == nullptr);
10891     }
10892
10893     // If bEnd was the first Cold basic block update fgFirstColdBlock
10894     if (fgFirstColdBlock == bEnd)
10895     {
10896         fgFirstColdBlock = bPrev->bbNext;
10897     }
10898
10899 #if FEATURE_EH_FUNCLETS
10900 #ifdef DEBUG
10901     // You can't unlink a range that includes the first funclet block. A range certainly
10902     // can't cross the non-funclet/funclet region. And you can't unlink the first block
10903     // of the first funclet with this, either. (If that's necessary, it could be allowed
10904     // by updating fgFirstFuncletBB to bEnd->bbNext.)
10905     for (BasicBlock* tempBB = bBeg; tempBB != bEnd->bbNext; tempBB = tempBB->bbNext)
10906     {
10907         assert(tempBB != fgFirstFuncletBB);
10908     }
10909 #endif // DEBUG
10910 #endif // FEATURE_EH_FUNCLETS
10911 }
10912
10913 /*****************************************************************************************************
10914  *
10915  *  Function called to remove a basic block
10916  */
10917
10918 void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable)
10919 {
10920     BasicBlock* bPrev = block->bbPrev;
10921
10922     /* The block has to be either unreachable or empty */
10923
10924     PREFIX_ASSUME(block != nullptr);
10925
10926     JITDUMP("fgRemoveBlock BB%02u\n", block->bbNum);
10927
10928     // If we've cached any mappings from switch blocks to SwitchDesc's (which contain only the
10929     // *unique* successors of the switch block), invalidate that cache, since an entry in one of
10930     // the SwitchDescs might be removed.
10931     InvalidateUniqueSwitchSuccMap();
10932
10933     noway_assert((block == fgFirstBB) || (bPrev && (bPrev->bbNext == block)));
10934     noway_assert(!(block->bbFlags & BBF_DONT_REMOVE));
10935
10936     // Should never remove a genReturnBB, as we might have special hookups there.
10937     noway_assert(block != genReturnBB);
10938
10939 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10940     // Don't remove a finally target
10941     assert(!(block->bbFlags & BBF_FINALLY_TARGET));
10942 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10943
10944     if (unreachable)
10945     {
10946         PREFIX_ASSUME(bPrev != nullptr);
10947
10948         fgUnreachableBlock(block);
10949
10950         /* If this is the last basic block update fgLastBB */
10951         if (block == fgLastBB)
10952         {
10953             fgLastBB = bPrev;
10954         }
10955
10956 #if FEATURE_EH_FUNCLETS
10957         // If block was the fgFirstFuncletBB then set fgFirstFuncletBB to block->bbNext
10958         if (block == fgFirstFuncletBB)
10959         {
10960             fgFirstFuncletBB = block->bbNext;
10961         }
10962 #endif // FEATURE_EH_FUNCLETS
10963
10964         if (bPrev->bbJumpKind == BBJ_CALLFINALLY)
10965         {
10966             // bPrev CALL becomes RETLESS as the BBJ_ALWAYS block is unreachable
10967             bPrev->bbFlags |= BBF_RETLESS_CALL;
10968
10969 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10970             NO_WAY("No retless call finally blocks; need unwind target instead");
10971 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10972         }
10973         else if (bPrev->bbJumpKind == BBJ_ALWAYS && bPrev->bbJumpDest == block->bbNext &&
10974                  !(bPrev->bbFlags & BBF_KEEP_BBJ_ALWAYS) && (block != fgFirstColdBlock) &&
10975                  (block->bbNext != fgFirstColdBlock))
10976         {
10977             // previous block is a BBJ_ALWAYS to the next block: change to BBJ_NONE.
10978             // Note that we don't do it if bPrev follows a BBJ_CALLFINALLY block (BBF_KEEP_BBJ_ALWAYS),
10979             // because that would violate our invariant that BBJ_CALLFINALLY blocks are followed by
10980             // BBJ_ALWAYS blocks.
10981             bPrev->bbJumpKind = BBJ_NONE;
10982             bPrev->bbFlags &= ~BBF_NEEDS_GCPOLL;
10983         }
10984
10985         // If this is the first Cold basic block update fgFirstColdBlock
10986         if (block == fgFirstColdBlock)
10987         {
10988             fgFirstColdBlock = block->bbNext;
10989         }
10990
10991         /* Unlink this block from the bbNext chain */
10992         fgUnlinkBlock(block);
10993
10994         /* At this point the bbPreds and bbRefs had better be zero */
10995         noway_assert((block->bbRefs == 0) && (block->bbPreds == nullptr));
10996
10997         /*  A BBJ_CALLFINALLY is usually paired with a BBJ_ALWAYS.
10998          *  If we delete such a BBJ_CALLFINALLY we also delete the BBJ_ALWAYS
10999          */
11000         if (block->isBBCallAlwaysPair())
11001         {
11002             BasicBlock* leaveBlk = block->bbNext;
11003             noway_assert(leaveBlk->bbJumpKind == BBJ_ALWAYS);
11004
11005             leaveBlk->bbFlags &= ~BBF_DONT_REMOVE;
11006             leaveBlk->bbRefs  = 0;
11007             leaveBlk->bbPreds = nullptr;
11008
11009             fgRemoveBlock(leaveBlk, true);
11010
11011 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
11012             fgClearFinallyTargetBit(leaveBlk->bbJumpDest);
11013 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
11014         }
11015         else if (block->bbJumpKind == BBJ_RETURN)
11016         {
11017             fgRemoveReturnBlock(block);
11018         }
11019     }
11020     else // block is empty
11021     {
11022         noway_assert(block->isEmpty());
11023
11024         /* The block cannot follow a non-retless BBJ_CALLFINALLY (because we don't know who may jump to it) */
11025         noway_assert((bPrev == nullptr) || !bPrev->isBBCallAlwaysPair());
11026
11027         /* This cannot be the last basic block */
11028         noway_assert(block != fgLastBB);
11029
11030 #ifdef DEBUG
11031         if (verbose)
11032         {
11033             printf("Removing empty BB%02u\n", block->bbNum);
11034         }
11035 #endif // DEBUG
11036
11037 #ifdef DEBUG
11038         /* Some extra checks for the empty case */
11039
11040         switch (block->bbJumpKind)
11041         {
11042             case BBJ_NONE:
11043                 break;
11044
11045             case BBJ_ALWAYS:
11046                 /* Do not remove a block that jumps to itself - used for while (true){} */
11047                 noway_assert(block->bbJumpDest != block);
11048
11049                 /* Empty GOTO can be removed iff bPrev is BBJ_NONE */
11050                 noway_assert(bPrev && bPrev->bbJumpKind == BBJ_NONE);
11051                 break;
11052
11053             default:
11054                 noway_assert(!"Empty block of this type cannot be removed!");
11055                 break;
11056         }
11057 #endif // DEBUG
11058
11059         noway_assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS);
11060
11061         /* Who is the "real" successor of this block? */
11062
11063         BasicBlock* succBlock;
11064
11065         if (block->bbJumpKind == BBJ_ALWAYS)
11066         {
11067             succBlock = block->bbJumpDest;
11068         }
11069         else
11070         {
11071             succBlock = block->bbNext;
11072         }
11073
11074         bool skipUnmarkLoop = false;
11075
11076         // If block is the backedge for a loop and succBlock precedes block
11077         // then the succBlock becomes the new LOOP HEAD
11078         // NOTE: there's an assumption here that the blocks are numbered in increasing bbNext order.
11079         // NOTE 2: if fgDomsComputed is false, then we can't check reachability. However, if this is
11080         // the case, then the loop structures probably are also invalid, and shouldn't be used. This
11081         // can be the case late in compilation (such as Lower), where remnants of earlier created
11082         // structures exist, but haven't been maintained.
11083         if (block->isLoopHead() && (succBlock->bbNum <= block->bbNum))
11084         {
11085             succBlock->bbFlags |= BBF_LOOP_HEAD;
11086             if (fgDomsComputed && fgReachable(succBlock, block))
11087             {
11088                 /* Mark all the reachable blocks between 'succBlock' and 'block', excluding 'block' */
11089                 optMarkLoopBlocks(succBlock, block, true);
11090             }
11091         }
11092         else if (succBlock->isLoopHead() && bPrev && (succBlock->bbNum <= bPrev->bbNum))
11093         {
11094             skipUnmarkLoop = true;
11095         }
11096
11097         noway_assert(succBlock);
11098
11099         // If this is the first Cold basic block update fgFirstColdBlock
11100         if (block == fgFirstColdBlock)
11101         {
11102             fgFirstColdBlock = block->bbNext;
11103         }
11104
11105 #if FEATURE_EH_FUNCLETS
11106         // Update fgFirstFuncletBB if necessary
11107         if (block == fgFirstFuncletBB)
11108         {
11109             fgFirstFuncletBB = block->bbNext;
11110         }
11111 #endif // FEATURE_EH_FUNCLETS
11112
11113         /* First update the loop table and bbWeights */
11114         optUpdateLoopsBeforeRemoveBlock(block, skipUnmarkLoop);
11115
11116         /* Remove the block */
11117
11118         if (bPrev == nullptr)
11119         {
11120             /* special case if this is the first BB */
11121
11122             noway_assert(block == fgFirstBB);
11123
11124             /* Must be a fall through to next block */
11125
11126             noway_assert(block->bbJumpKind == BBJ_NONE);
11127
11128             /* old block no longer gets the extra ref count for being the first block */
11129             block->bbRefs--;
11130             succBlock->bbRefs++;
11131
11132             /* Set the new firstBB */
11133             fgUnlinkBlock(block);
11134
11135             /* Always treat the initial block as a jump target */
11136             fgFirstBB->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
11137         }
11138         else
11139         {
11140             fgUnlinkBlock(block);
11141         }
11142
11143         /* mark the block as removed and set the change flag */
11144
11145         block->bbFlags |= BBF_REMOVED;
11146
11147         /* Update bbRefs and bbPreds.
11148          * All blocks jumping to 'block' now jump to 'succBlock'.
11149          * First, remove 'block' from the predecessor list of succBlock.
11150          */
11151
11152         fgRemoveRefPred(succBlock, block);
11153
11154         for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
11155         {
11156             BasicBlock* predBlock = pred->flBlock;
11157
11158             /* Are we changing a loop backedge into a forward jump? */
11159
11160             if (block->isLoopHead() && (predBlock->bbNum >= block->bbNum) && (predBlock->bbNum <= succBlock->bbNum))
11161             {
11162                 /* First update the loop table and bbWeights */
11163                 optUpdateLoopsBeforeRemoveBlock(predBlock);
11164             }
11165
11166             /* If predBlock is a new predecessor, then add it to succBlock's
11167                predecessor's list. */
11168             if (predBlock->bbJumpKind != BBJ_SWITCH)
11169             {
11170                 // Even if the pred is not a switch, we could have a conditional branch
11171                 // to the fallthrough, so duplicate there could be preds
11172                 for (unsigned i = 0; i < pred->flDupCount; i++)
11173                 {
11174                     fgAddRefPred(succBlock, predBlock);
11175                 }
11176             }
11177
11178             /* change all jumps to the removed block */
11179             switch (predBlock->bbJumpKind)
11180             {
11181                 default:
11182                     noway_assert(!"Unexpected bbJumpKind in fgRemoveBlock()");
11183                     break;
11184
11185                 case BBJ_NONE:
11186                     noway_assert(predBlock == bPrev);
11187                     PREFIX_ASSUME(bPrev != nullptr);
11188
11189                     /* In the case of BBJ_ALWAYS we have to change the type of its predecessor */
11190                     if (block->bbJumpKind == BBJ_ALWAYS)
11191                     {
11192                         /* bPrev now becomes a BBJ_ALWAYS */
11193                         bPrev->bbJumpKind = BBJ_ALWAYS;
11194                         bPrev->bbJumpDest = succBlock;
11195                     }
11196                     break;
11197
11198                 case BBJ_COND:
11199                     /* The links for the direct predecessor case have already been updated above */
11200                     if (predBlock->bbJumpDest != block)
11201                     {
11202                         succBlock->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
11203                         break;
11204                     }
11205
11206                     /* Check if both side of the BBJ_COND now jump to the same block */
11207                     if (predBlock->bbNext == succBlock)
11208                     {
11209                         // Make sure we are replacing "block" with "succBlock" in predBlock->bbJumpDest.
11210                         noway_assert(predBlock->bbJumpDest == block);
11211                         predBlock->bbJumpDest = succBlock;
11212                         fgRemoveConditionalJump(predBlock);
11213                         break;
11214                     }
11215
11216                     /* Fall through for the jump case */
11217                     __fallthrough;
11218
11219                 case BBJ_CALLFINALLY:
11220                 case BBJ_ALWAYS:
11221                 case BBJ_EHCATCHRET:
11222                     noway_assert(predBlock->bbJumpDest == block);
11223                     predBlock->bbJumpDest = succBlock;
11224                     succBlock->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
11225                     break;
11226
11227                 case BBJ_SWITCH:
11228                     // Change any jumps from 'predBlock' (a BBJ_SWITCH) to 'block' to jump to 'succBlock'
11229                     //
11230                     // For the jump targets of 'predBlock' (a BBJ_SWITCH) that jump to 'block'
11231                     // remove the old predecessor at 'block' from 'predBlock'  and
11232                     // add the new predecessor at 'succBlock' from 'predBlock'
11233                     //
11234                     fgReplaceSwitchJumpTarget(predBlock, succBlock, block);
11235                     break;
11236             }
11237         }
11238     }
11239
11240     if (bPrev != nullptr)
11241     {
11242         switch (bPrev->bbJumpKind)
11243         {
11244             case BBJ_CALLFINALLY:
11245                 // If prev is a BBJ_CALLFINALLY it better be marked as RETLESS
11246                 noway_assert(bPrev->bbFlags & BBF_RETLESS_CALL);
11247                 break;
11248
11249             case BBJ_ALWAYS:
11250                 // Check for branch to next block. Just make sure the BBJ_ALWAYS block is not
11251                 // part of a BBJ_CALLFINALLY/BBJ_ALWAYS pair. We do this here and don't rely on fgUpdateFlowGraph
11252                 // because we can be called by ComputeDominators and it expects it to remove this jump to
11253                 // the next block. This is the safest fix. We should remove all this BBJ_CALLFINALLY/BBJ_ALWAYS
11254                 // pairing.
11255
11256                 if ((bPrev->bbJumpDest == bPrev->bbNext) &&
11257                     !fgInDifferentRegions(bPrev, bPrev->bbJumpDest)) // We don't remove a branch from Hot -> Cold
11258                 {
11259                     if ((bPrev == fgFirstBB) || !bPrev->bbPrev->isBBCallAlwaysPair())
11260                     {
11261                         // It's safe to change the jump type
11262                         bPrev->bbJumpKind = BBJ_NONE;
11263                         bPrev->bbFlags &= ~BBF_NEEDS_GCPOLL;
11264                     }
11265                 }
11266                 break;
11267
11268             case BBJ_COND:
11269                 /* Check for branch to next block */
11270                 if (bPrev->bbJumpDest == bPrev->bbNext)
11271                 {
11272                     fgRemoveConditionalJump(bPrev);
11273                 }
11274                 break;
11275
11276             default:
11277                 break;
11278         }
11279
11280         ehUpdateForDeletedBlock(block);
11281     }
11282 }
11283
11284 /*****************************************************************************
11285  *
11286  *  Function called to connect to block that previously had a fall through
11287  */
11288
11289 BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst)
11290 {
11291     BasicBlock* jmpBlk = nullptr;
11292
11293     /* If bSrc is non-NULL */
11294
11295     if (bSrc != nullptr)
11296     {
11297         /* If bSrc falls through to a block that is not bDst, we will insert a jump to bDst */
11298
11299         if (bSrc->bbFallsThrough() && (bSrc->bbNext != bDst))
11300         {
11301             switch (bSrc->bbJumpKind)
11302             {
11303
11304                 case BBJ_NONE:
11305                     bSrc->bbJumpKind = BBJ_ALWAYS;
11306                     bSrc->bbJumpDest = bDst;
11307                     bSrc->bbJumpDest->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
11308 #ifdef DEBUG
11309                     if (verbose)
11310                     {
11311                         printf("Block BB%02u ended with a BBJ_NONE, Changed to an unconditional jump to BB%02u\n",
11312                                bSrc->bbNum, bSrc->bbJumpDest->bbNum);
11313                     }
11314 #endif
11315                     break;
11316
11317                 case BBJ_CALLFINALLY:
11318                 case BBJ_COND:
11319
11320                     // Add a new block after bSrc which jumps to 'bDst'
11321                     jmpBlk = fgNewBBafter(BBJ_ALWAYS, bSrc, true);
11322
11323                     if (fgComputePredsDone)
11324                     {
11325                         fgAddRefPred(jmpBlk, bSrc, fgGetPredForBlock(bDst, bSrc));
11326                     }
11327
11328                     // When adding a new jmpBlk we will set the bbWeight and bbFlags
11329                     //
11330                     if (fgHaveValidEdgeWeights)
11331                     {
11332                         noway_assert(fgComputePredsDone);
11333
11334                         flowList* newEdge = fgGetPredForBlock(jmpBlk, bSrc);
11335
11336                         jmpBlk->bbWeight = (newEdge->flEdgeWeightMin + newEdge->flEdgeWeightMax) / 2;
11337                         if (bSrc->bbWeight == 0)
11338                         {
11339                             jmpBlk->bbWeight = 0;
11340                         }
11341
11342                         if (jmpBlk->bbWeight == 0)
11343                         {
11344                             jmpBlk->bbFlags |= BBF_RUN_RARELY;
11345                         }
11346
11347                         BasicBlock::weight_t weightDiff = (newEdge->flEdgeWeightMax - newEdge->flEdgeWeightMin);
11348                         BasicBlock::weight_t slop       = BasicBlock::GetSlopFraction(bSrc, bDst);
11349
11350                         //
11351                         // If the [min/max] values for our edge weight is within the slop factor
11352                         //  then we will set the BBF_PROF_WEIGHT flag for the block
11353                         //
11354                         if (weightDiff <= slop)
11355                         {
11356                             jmpBlk->bbFlags |= BBF_PROF_WEIGHT;
11357                         }
11358                     }
11359                     else
11360                     {
11361                         // We set the bbWeight to the smaller of bSrc->bbWeight or bDst->bbWeight
11362                         if (bSrc->bbWeight < bDst->bbWeight)
11363                         {
11364                             jmpBlk->bbWeight = bSrc->bbWeight;
11365                             jmpBlk->bbFlags |= (bSrc->bbFlags & BBF_RUN_RARELY);
11366                         }
11367                         else
11368                         {
11369                             jmpBlk->bbWeight = bDst->bbWeight;
11370                             jmpBlk->bbFlags |= (bDst->bbFlags & BBF_RUN_RARELY);
11371                         }
11372                     }
11373
11374                     jmpBlk->bbJumpDest = bDst;
11375                     jmpBlk->bbJumpDest->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
11376
11377                     if (fgComputePredsDone)
11378                     {
11379                         fgReplacePred(bDst, bSrc, jmpBlk);
11380                     }
11381                     else
11382                     {
11383                         jmpBlk->bbFlags |= BBF_IMPORTED;
11384                     }
11385
11386 #ifdef DEBUG
11387                     if (verbose)
11388                     {
11389                         printf("Added an unconditional jump to BB%02u after block BB%02u\n", jmpBlk->bbJumpDest->bbNum,
11390                                bSrc->bbNum);
11391                     }
11392 #endif // DEBUG
11393                     break;
11394
11395                 default:
11396                     noway_assert(!"Unexpected bbJumpKind");
11397                     break;
11398             }
11399         }
11400         else
11401         {
11402             // If bSrc is an unconditional branch to the next block
11403             // then change it to a BBJ_NONE block
11404             //
11405             if ((bSrc->bbJumpKind == BBJ_ALWAYS) && !(bSrc->bbFlags & BBF_KEEP_BBJ_ALWAYS) &&
11406                 (bSrc->bbJumpDest == bSrc->bbNext))
11407             {
11408                 bSrc->bbJumpKind = BBJ_NONE;
11409                 bSrc->bbFlags &= ~BBF_NEEDS_GCPOLL;
11410 #ifdef DEBUG
11411                 if (verbose)
11412                 {
11413                     printf("Changed an unconditional jump from BB%02u to the next block BB%02u into a BBJ_NONE block\n",
11414                            bSrc->bbNum, bSrc->bbNext->bbNum);
11415                 }
11416 #endif // DEBUG
11417             }
11418         }
11419     }
11420
11421     return jmpBlk;
11422 }
11423
11424 /*****************************************************************************
11425  Walk the flow graph, reassign block numbers to keep them in ascending order.
11426  Returns 'true' if any renumbering was actually done, OR if we change the
11427  maximum number of assigned basic blocks (this can happen if we do inlining,
11428  create a new, high-numbered block, then that block goes away. We go to
11429  renumber the blocks, none of them actually change number, but we shrink the
11430  maximum assigned block number. This affects the block set epoch).
11431 */
11432
11433 bool Compiler::fgRenumberBlocks()
11434 {
11435     // If we renumber the blocks the dominator information will be out-of-date
11436     if (fgDomsComputed)
11437     {
11438         noway_assert(!"Can't call Compiler::fgRenumberBlocks() when fgDomsComputed==true");
11439     }
11440
11441 #ifdef DEBUG
11442     if (verbose)
11443     {
11444         printf("\n*************** Before renumbering the basic blocks\n");
11445         fgDispBasicBlocks();
11446         fgDispHandlerTab();
11447     }
11448 #endif // DEBUG
11449
11450     bool        renumbered  = false;
11451     bool        newMaxBBNum = false;
11452     BasicBlock* block;
11453
11454     unsigned numStart = 1 + (compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : 0);
11455     unsigned num;
11456
11457     for (block = fgFirstBB, num = numStart; block != nullptr; block = block->bbNext, num++)
11458     {
11459         noway_assert((block->bbFlags & BBF_REMOVED) == 0);
11460
11461         if (block->bbNum != num)
11462         {
11463             renumbered = true;
11464 #ifdef DEBUG
11465             if (verbose)
11466             {
11467                 printf("Renumber BB%02u to BB%02u\n", block->bbNum, num);
11468             }
11469 #endif // DEBUG
11470             block->bbNum = num;
11471         }
11472
11473         if (block->bbNext == nullptr)
11474         {
11475             fgLastBB  = block;
11476             fgBBcount = num - numStart + 1;
11477             if (compIsForInlining())
11478             {
11479                 if (impInlineInfo->InlinerCompiler->fgBBNumMax != num)
11480                 {
11481                     impInlineInfo->InlinerCompiler->fgBBNumMax = num;
11482                     newMaxBBNum                                = true;
11483                 }
11484             }
11485             else
11486             {
11487                 if (fgBBNumMax != num)
11488                 {
11489                     fgBBNumMax  = num;
11490                     newMaxBBNum = true;
11491                 }
11492             }
11493         }
11494     }
11495
11496 #ifdef DEBUG
11497     if (verbose)
11498     {
11499         printf("\n*************** After renumbering the basic blocks\n");
11500         if (renumbered)
11501         {
11502             fgDispBasicBlocks();
11503             fgDispHandlerTab();
11504         }
11505         else
11506         {
11507             printf("=============== No blocks renumbered!\n");
11508         }
11509     }
11510 #endif // DEBUG
11511
11512     // Now update the BlockSet epoch, which depends on the block numbers.
11513     // If any blocks have been renumbered then create a new BlockSet epoch.
11514     // Even if we have not renumbered any blocks, we might still need to force
11515     // a new BlockSet epoch, for one of several reasons. If there are any new
11516     // blocks with higher numbers than the former maximum numbered block, then we
11517     // need a new epoch with a new size matching the new largest numbered block.
11518     // Also, if the number of blocks is different from the last time we set the
11519     // BlockSet epoch, then we need a new epoch. This wouldn't happen if we
11520     // renumbered blocks after every block addition/deletion, but it might be
11521     // the case that we can change the number of blocks, then set the BlockSet
11522     // epoch without renumbering, then change the number of blocks again, then
11523     // renumber.
11524     if (renumbered || newMaxBBNum)
11525     {
11526         NewBasicBlockEpoch();
11527
11528         // The key in the unique switch successor map is dependent on the block number, so invalidate that cache.
11529         InvalidateUniqueSwitchSuccMap();
11530     }
11531     else
11532     {
11533         EnsureBasicBlockEpoch();
11534     }
11535
11536     // Tell our caller if any blocks actually were renumbered.
11537     return renumbered || newMaxBBNum;
11538 }
11539
11540 /*****************************************************************************
11541  *
11542  *  Is the BasicBlock bJump a forward branch?
11543  *   Optionally bSrc can be supplied to indicate that
11544  *   bJump must be forward with respect to bSrc
11545  */
11546 bool Compiler::fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc /* = NULL */)
11547 {
11548     bool result = false;
11549
11550     if ((bJump->bbJumpKind == BBJ_COND) || (bJump->bbJumpKind == BBJ_ALWAYS))
11551     {
11552         BasicBlock* bDest = bJump->bbJumpDest;
11553         BasicBlock* bTemp = (bSrc == nullptr) ? bJump : bSrc;
11554
11555         while (true)
11556         {
11557             bTemp = bTemp->bbNext;
11558
11559             if (bTemp == nullptr)
11560             {
11561                 break;
11562             }
11563
11564             if (bTemp == bDest)
11565             {
11566                 result = true;
11567                 break;
11568             }
11569         }
11570     }
11571
11572     return result;
11573 }
11574
11575 /*****************************************************************************
11576  *
11577  *  Function called to expand the set of rarely run blocks
11578  */
11579
11580 bool Compiler::fgExpandRarelyRunBlocks()
11581 {
11582     bool result = false;
11583
11584 #ifdef DEBUG
11585     if (verbose)
11586     {
11587         printf("\n*************** In fgExpandRarelyRunBlocks()\n");
11588     }
11589
11590     const char* reason = nullptr;
11591 #endif
11592
11593     // We expand the number of rarely run blocks by observing
11594     // that a block that falls into or jumps to a rarely run block,
11595     // must itself be rarely run and when we have a conditional
11596     // jump in which both branches go to rarely run blocks then
11597     // the block must itself be rarely run
11598
11599     BasicBlock* block;
11600     BasicBlock* bPrev;
11601
11602     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
11603     {
11604         if (bPrev->isRunRarely())
11605         {
11606             continue;
11607         }
11608
11609         /* bPrev is known to be a normal block here */
11610         switch (bPrev->bbJumpKind)
11611         {
11612             case BBJ_ALWAYS:
11613
11614                 /* Is the jump target rarely run? */
11615                 if (bPrev->bbJumpDest->isRunRarely())
11616                 {
11617                     INDEBUG(reason = "Unconditional jump to a rarely run block";)
11618                     goto NEW_RARELY_RUN;
11619                 }
11620                 break;
11621
11622             case BBJ_CALLFINALLY:
11623
11624                 // Check for a BBJ_CALLFINALLY followed by a rarely run paired BBJ_ALWAYS
11625                 //
11626                 if (bPrev->isBBCallAlwaysPair())
11627                 {
11628                     /* Is the next block rarely run? */
11629                     if (block->isRunRarely())
11630                     {
11631                         INDEBUG(reason = "Call of finally followed by a rarely run block";)
11632                         goto NEW_RARELY_RUN;
11633                     }
11634                 }
11635                 break;
11636
11637             case BBJ_NONE:
11638
11639                 /* is fall through target rarely run? */
11640                 if (block->isRunRarely())
11641                 {
11642                     INDEBUG(reason = "Falling into a rarely run block";)
11643                     goto NEW_RARELY_RUN;
11644                 }
11645                 break;
11646
11647             case BBJ_COND:
11648
11649                 if (!block->isRunRarely())
11650                 {
11651                     continue;
11652                 }
11653
11654                 /* If both targets of the BBJ_COND are run rarely then don't reorder */
11655                 if (bPrev->bbJumpDest->isRunRarely())
11656                 {
11657                     /* bPrev should also be marked as run rarely */
11658                     if (!bPrev->isRunRarely())
11659                     {
11660                         INDEBUG(reason = "Both sides of a conditional jump are rarely run";)
11661
11662                     NEW_RARELY_RUN:
11663                         /* If the weight of the block was obtained from a profile run,
11664                            than it's more accurate than our static analysis */
11665                         if (bPrev->hasProfileWeight())
11666                         {
11667                             continue;
11668                         }
11669                         result = true;
11670
11671 #ifdef DEBUG
11672                         assert(reason != nullptr);
11673                         if (verbose)
11674                         {
11675                             printf("%s, marking BB%02u as rarely run\n", reason, bPrev->bbNum);
11676                         }
11677 #endif // DEBUG
11678
11679                         /* Must not have previously been marked */
11680                         noway_assert(!bPrev->isRunRarely());
11681
11682                         /* Mark bPrev as a new rarely run block */
11683                         bPrev->bbSetRunRarely();
11684
11685                         BasicBlock* bPrevPrev = nullptr;
11686                         BasicBlock* tmpbb;
11687
11688                         if ((bPrev->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)
11689                         {
11690                             // If we've got a BBJ_CALLFINALLY/BBJ_ALWAYS pair, treat the BBJ_CALLFINALLY as an
11691                             // additional predecessor for the BBJ_ALWAYS block
11692                             tmpbb = bPrev->bbPrev;
11693                             noway_assert(tmpbb != nullptr);
11694 #if FEATURE_EH_FUNCLETS
11695                             noway_assert(tmpbb->isBBCallAlwaysPair());
11696                             bPrevPrev = tmpbb;
11697 #else
11698                             if (tmpbb->bbJumpKind == BBJ_CALLFINALLY)
11699                             {
11700                                 bPrevPrev = tmpbb;
11701                             }
11702 #endif
11703                         }
11704
11705                         /* Now go back to it's earliest predecessor to see */
11706                         /* if it too should now be marked as rarely run    */
11707                         flowList* pred = bPrev->bbPreds;
11708
11709                         if ((pred != nullptr) || (bPrevPrev != nullptr))
11710                         {
11711                             // bPrevPrev will be set to the lexically
11712                             // earliest predecessor of bPrev.
11713
11714                             while (pred != nullptr)
11715                             {
11716                                 if (bPrevPrev == nullptr)
11717                                 {
11718                                     // Initially we select the first block in the bbPreds list
11719                                     bPrevPrev = pred->flBlock;
11720                                     continue;
11721                                 }
11722
11723                                 // Walk the flow graph lexically forward from pred->flBlock
11724                                 // if we find (block == bPrevPrev) then
11725                                 // pred->flBlock is an earlier predecessor.
11726                                 for (tmpbb = pred->flBlock; tmpbb != nullptr; tmpbb = tmpbb->bbNext)
11727                                 {
11728                                     if (tmpbb == bPrevPrev)
11729                                     {
11730                                         /* We found an ealier predecessor */
11731                                         bPrevPrev = pred->flBlock;
11732                                         break;
11733                                     }
11734                                     else if (tmpbb == bPrev)
11735                                     {
11736                                         // We have reached bPrev so stop walking
11737                                         // as this cannot be an earlier predecessor
11738                                         break;
11739                                     }
11740                                 }
11741
11742                                 // Onto the next predecessor
11743                                 pred = pred->flNext;
11744                             }
11745
11746                             // Walk the flow graph forward from bPrevPrev
11747                             // if we don't find (tmpbb == bPrev) then our candidate
11748                             // bPrevPrev is lexically after bPrev and we do not
11749                             // want to select it as our new block
11750
11751                             for (tmpbb = bPrevPrev; tmpbb != nullptr; tmpbb = tmpbb->bbNext)
11752                             {
11753                                 if (tmpbb == bPrev)
11754                                 {
11755                                     // Set up block back to the lexically
11756                                     // earliest predecessor of pPrev
11757
11758                                     block = bPrevPrev;
11759                                 }
11760                             }
11761                         }
11762                     }
11763                     break;
11764
11765                     default:
11766                         break;
11767                 }
11768         }
11769     }
11770
11771     // Now iterate over every block to see if we can prove that a block is rarely run
11772     // (i.e. when all predecessors to the block are rarely run)
11773     //
11774     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
11775     {
11776         // If block is not run rarely, then check to make sure that it has
11777         // at least one non-rarely run block.
11778
11779         if (!block->isRunRarely())
11780         {
11781             bool rare = true;
11782
11783             /* Make sure that block has at least one normal predecessor */
11784             for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
11785             {
11786                 /* Find the fall through predecessor, if any */
11787                 if (!pred->flBlock->isRunRarely())
11788                 {
11789                     rare = false;
11790                     break;
11791                 }
11792             }
11793
11794             if (rare)
11795             {
11796                 // If 'block' is the start of a handler or filter then we cannot make it
11797                 // rarely run because we may have an exceptional edge that
11798                 // branches here.
11799                 //
11800                 if (bbIsHandlerBeg(block))
11801                 {
11802                     rare = false;
11803                 }
11804             }
11805
11806             if (rare)
11807             {
11808                 block->bbSetRunRarely();
11809                 result = true;
11810
11811 #ifdef DEBUG
11812                 if (verbose)
11813                 {
11814                     printf("All branches to BB%02u are from rarely run blocks, marking as rarely run\n", block->bbNum);
11815                 }
11816 #endif // DEBUG
11817
11818                 // When marking a BBJ_CALLFINALLY as rarely run we also mark
11819                 // the BBJ_ALWAYS that comes after it as rarely run
11820                 //
11821                 if (block->isBBCallAlwaysPair())
11822                 {
11823                     BasicBlock* bNext = block->bbNext;
11824                     PREFIX_ASSUME(bNext != nullptr);
11825                     bNext->bbSetRunRarely();
11826 #ifdef DEBUG
11827                     if (verbose)
11828                     {
11829                         printf("Also marking the BBJ_ALWAYS at BB%02u as rarely run\n", bNext->bbNum);
11830                     }
11831 #endif // DEBUG
11832                 }
11833             }
11834         }
11835
11836         /* COMPACT blocks if possible */
11837         if (bPrev->bbJumpKind == BBJ_NONE)
11838         {
11839             if (fgCanCompactBlocks(bPrev, block))
11840             {
11841                 fgCompactBlocks(bPrev, block);
11842
11843                 block = bPrev;
11844                 continue;
11845             }
11846         }
11847         //
11848         // if bPrev->bbWeight is not based upon profile data we can adjust
11849         // the weights of bPrev and block
11850         //
11851         else if (bPrev->isBBCallAlwaysPair() &&          // we must have a BBJ_CALLFINALLY and BBK_ALWAYS pair
11852                  (bPrev->bbWeight != block->bbWeight) && // the weights are currently different
11853                  !bPrev->hasProfileWeight())             // and the BBJ_CALLFINALLY block is not using profiled
11854                                                          // weights
11855         {
11856             if (block->isRunRarely())
11857             {
11858                 bPrev->bbWeight =
11859                     block->bbWeight; // the BBJ_CALLFINALLY block now has the same weight as the BBJ_ALWAYS block
11860                 bPrev->bbFlags |= BBF_RUN_RARELY; // and is now rarely run
11861 #ifdef DEBUG
11862                 if (verbose)
11863                 {
11864                     printf("Marking the BBJ_CALLFINALLY block at BB%02u as rarely run because BB%02u is rarely run\n",
11865                            bPrev->bbNum, block->bbNum);
11866                 }
11867 #endif // DEBUG
11868             }
11869             else if (bPrev->isRunRarely())
11870             {
11871                 block->bbWeight =
11872                     bPrev->bbWeight; // the BBJ_ALWAYS block now has the same weight as the BBJ_CALLFINALLY block
11873                 block->bbFlags |= BBF_RUN_RARELY; // and is now rarely run
11874 #ifdef DEBUG
11875                 if (verbose)
11876                 {
11877                     printf("Marking the BBJ_ALWAYS block at BB%02u as rarely run because BB%02u is rarely run\n",
11878                            block->bbNum, bPrev->bbNum);
11879                 }
11880 #endif // DEBUG
11881             }
11882             else // Both blocks are hot, bPrev is known not to be using profiled weight
11883             {
11884                 bPrev->bbWeight =
11885                     block->bbWeight; // the BBJ_CALLFINALLY block now has the same weight as the BBJ_ALWAYS block
11886             }
11887             noway_assert(block->bbWeight == bPrev->bbWeight);
11888         }
11889     }
11890
11891     return result;
11892 }
11893
11894 /*****************************************************************************
11895  *
11896  *  Returns true if it is allowable (based upon the EH regions)
11897  *  to place block bAfter immediately after bBefore. It is allowable
11898  *  if the 'bBefore' and 'bAfter' blocks are in the exact same EH region.
11899  */
11900
11901 bool Compiler::fgEhAllowsMoveBlock(BasicBlock* bBefore, BasicBlock* bAfter)
11902 {
11903     return BasicBlock::sameEHRegion(bBefore, bAfter);
11904 }
11905
11906 /*****************************************************************************
11907  *
11908  *  Function called to move the range of blocks [bStart .. bEnd].
11909  *  The blocks are placed immediately after the insertAfterBlk.
11910  *  fgFirstFuncletBB is not updated; that is the responsibility of the caller, if necessary.
11911  */
11912
11913 void Compiler::fgMoveBlocksAfter(BasicBlock* bStart, BasicBlock* bEnd, BasicBlock* insertAfterBlk)
11914 {
11915     /* We have decided to insert the block(s) after 'insertAfterBlk' */
11916     CLANG_FORMAT_COMMENT_ANCHOR;
11917
11918 #ifdef DEBUG
11919     if (verbose)
11920     {
11921         printf("Relocated block%s [BB%02u..BB%02u] inserted after BB%02u%s\n", (bStart == bEnd) ? "" : "s",
11922                bStart->bbNum, bEnd->bbNum, insertAfterBlk->bbNum,
11923                (insertAfterBlk->bbNext == nullptr) ? " at the end of method" : "");
11924     }
11925 #endif // DEBUG
11926
11927     /* relink [bStart .. bEnd] into the flow graph */
11928
11929     bEnd->bbNext = insertAfterBlk->bbNext;
11930     if (insertAfterBlk->bbNext)
11931     {
11932         insertAfterBlk->bbNext->bbPrev = bEnd;
11933     }
11934     insertAfterBlk->setNext(bStart);
11935
11936     /* If insertAfterBlk was fgLastBB then update fgLastBB */
11937     if (insertAfterBlk == fgLastBB)
11938     {
11939         fgLastBB = bEnd;
11940         noway_assert(fgLastBB->bbNext == nullptr);
11941     }
11942 }
11943
11944 /*****************************************************************************
11945  *
11946  *  Function called to relocate a single range to the end of the method.
11947  *  Only an entire consecutive region can be moved and it will be kept together.
11948  *  Except for the first block, the range cannot have any blocks that jump into or out of the region.
11949  *  When successful we return the bLast block which is the last block that we relocated.
11950  *  When unsuccessful we return NULL.
11951
11952     =============================================================
11953     NOTE: This function can invalidate all pointers into the EH table, as well as change the size of the EH table!
11954     =============================================================
11955  */
11956
11957 BasicBlock* Compiler::fgRelocateEHRange(unsigned regionIndex, FG_RELOCATE_TYPE relocateType)
11958 {
11959     INDEBUG(const char* reason = "None";)
11960
11961     // Figure out the range of blocks we're going to move
11962
11963     unsigned    XTnum;
11964     EHblkDsc*   HBtab;
11965     BasicBlock* bStart  = nullptr;
11966     BasicBlock* bMiddle = nullptr;
11967     BasicBlock* bLast   = nullptr;
11968     BasicBlock* bPrev   = nullptr;
11969
11970 #if FEATURE_EH_FUNCLETS
11971     // We don't support moving try regions... yet?
11972     noway_assert(relocateType == FG_RELOCATE_HANDLER);
11973 #endif // FEATURE_EH_FUNCLETS
11974
11975     HBtab = ehGetDsc(regionIndex);
11976
11977     if (relocateType == FG_RELOCATE_TRY)
11978     {
11979         bStart = HBtab->ebdTryBeg;
11980         bLast  = HBtab->ebdTryLast;
11981     }
11982     else if (relocateType == FG_RELOCATE_HANDLER)
11983     {
11984         if (HBtab->HasFilter())
11985         {
11986             // The filter and handler funclets must be moved together, and remain contiguous.
11987             bStart  = HBtab->ebdFilter;
11988             bMiddle = HBtab->ebdHndBeg;
11989             bLast   = HBtab->ebdHndLast;
11990         }
11991         else
11992         {
11993             bStart = HBtab->ebdHndBeg;
11994             bLast  = HBtab->ebdHndLast;
11995         }
11996     }
11997
11998     // Our range must contain either all rarely run blocks or all non-rarely run blocks
11999     bool inTheRange = false;
12000     bool validRange = false;
12001
12002     BasicBlock* block;
12003
12004     noway_assert(bStart != nullptr && bLast != nullptr);
12005     if (bStart == fgFirstBB)
12006     {
12007         INDEBUG(reason = "can not relocate first block";)
12008         goto FAILURE;
12009     }
12010
12011 #if !FEATURE_EH_FUNCLETS
12012     // In the funclets case, we still need to set some information on the handler blocks
12013     if (bLast->bbNext == NULL)
12014     {
12015         INDEBUG(reason = "region is already at the end of the method";)
12016         goto FAILURE;
12017     }
12018 #endif // !FEATURE_EH_FUNCLETS
12019
12020     // Walk the block list for this purpose:
12021     // 1. Verify that all the blocks in the range are either all rarely run or not rarely run.
12022     // When creating funclets, we ignore the run rarely flag, as we need to be able to move any blocks
12023     // in the range.
12024     CLANG_FORMAT_COMMENT_ANCHOR;
12025
12026 #if !FEATURE_EH_FUNCLETS
12027     bool isRare;
12028     isRare = bStart->isRunRarely();
12029 #endif // !FEATURE_EH_FUNCLETS
12030     block = fgFirstBB;
12031     while (true)
12032     {
12033         if (block == bStart)
12034         {
12035             noway_assert(inTheRange == false);
12036             inTheRange = true;
12037         }
12038         else if (block == bLast->bbNext)
12039         {
12040             noway_assert(inTheRange == true);
12041             inTheRange = false;
12042             break; // we found the end, so we're done
12043         }
12044
12045         if (inTheRange)
12046         {
12047 #if !FEATURE_EH_FUNCLETS
12048             // Unless all blocks are (not) run rarely we must return false.
12049             if (isRare != block->isRunRarely())
12050             {
12051                 INDEBUG(reason = "this region contains both rarely run and non-rarely run blocks";)
12052                 goto FAILURE;
12053             }
12054 #endif // !FEATURE_EH_FUNCLETS
12055
12056             validRange = true;
12057         }
12058
12059         if (block == nullptr)
12060         {
12061             break;
12062         }
12063
12064         block = block->bbNext;
12065     }
12066     // Ensure that bStart .. bLast defined a valid range
12067     noway_assert((validRange == true) && (inTheRange == false));
12068
12069     bPrev = bStart->bbPrev;
12070     noway_assert(bPrev != nullptr); // Can't move a range that includes the first block of the function.
12071
12072     JITDUMP("Relocating %s range BB%02u..BB%02u (EH#%u) to end of BBlist\n",
12073             (relocateType == FG_RELOCATE_TRY) ? "try" : "handler", bStart->bbNum, bLast->bbNum, regionIndex);
12074
12075 #ifdef DEBUG
12076     if (verbose)
12077     {
12078         fgDispBasicBlocks();
12079         fgDispHandlerTab();
12080     }
12081
12082     if (!FEATURE_EH_FUNCLETS)
12083     {
12084         // This is really expensive, and quickly becomes O(n^n) with funclets
12085         // so only do it once after we've created them (see fgCreateFunclets)
12086         if (expensiveDebugCheckLevel >= 2)
12087         {
12088             fgDebugCheckBBlist();
12089         }
12090     }
12091 #endif // DEBUG
12092
12093 #if FEATURE_EH_FUNCLETS
12094
12095     bStart->bbFlags |= BBF_FUNCLET_BEG; // Mark the start block of the funclet
12096
12097     if (bMiddle != nullptr)
12098     {
12099         bMiddle->bbFlags |= BBF_FUNCLET_BEG; // Also mark the start block of a filter handler as a funclet
12100     }
12101
12102 #endif // FEATURE_EH_FUNCLETS
12103
12104     BasicBlock* bNext;
12105     bNext = bLast->bbNext;
12106
12107     /* Temporarily unlink [bStart .. bLast] from the flow graph */
12108     fgUnlinkRange(bStart, bLast);
12109
12110     BasicBlock* insertAfterBlk;
12111     insertAfterBlk = fgLastBB;
12112
12113 #if FEATURE_EH_FUNCLETS
12114
12115     // There are several cases we need to consider when moving an EH range.
12116     // If moving a range X, we must consider its relationship to every other EH
12117     // range A in the table. Note that each entry in the table represents both
12118     // a protected region and a handler region (possibly including a filter region
12119     // that must live before and adjacent to the handler region), so we must
12120     // consider try and handler regions independently. These are the cases:
12121     // 1. A is completely contained within X (where "completely contained" means
12122     //    that the 'begin' and 'last' parts of A are strictly between the 'begin'
12123     //    and 'end' parts of X, and aren't equal to either, for example, they don't
12124     //    share 'last' blocks). In this case, when we move X, A moves with it, and
12125     //    the EH table doesn't need to change.
12126     // 2. X is completely contained within A. In this case, X gets extracted from A,
12127     //    and the range of A shrinks, but because A is strictly within X, the EH
12128     //    table doesn't need to change.
12129     // 3. A and X have exactly the same range. In this case, A is moving with X and
12130     //    the EH table doesn't need to change.
12131     // 4. A and X share the 'last' block. There are two sub-cases:
12132     //    (a) A is a larger range than X (such that the beginning of A precedes the
12133     //        beginning of X): in this case, we are moving the tail of A. We set the
12134     //        'last' block of A to the the block preceding the beginning block of X.
12135     //    (b) A is a smaller range than X. Thus, we are moving the entirety of A along
12136     //        with X. In this case, nothing in the EH record for A needs to change.
12137     // 5. A and X share the 'beginning' block (but aren't the same range, as in #3).
12138     //    This can never happen here, because we are only moving handler ranges (we don't
12139     //    move try ranges), and handler regions cannot start at the beginning of a try
12140     //    range or handler range and be a subset.
12141     //
12142     // Note that A and X must properly nest for the table to be well-formed. For example,
12143     // the beginning of A can't be strictly within the range of X (that is, the beginning
12144     // of A isn't shared with the beginning of X) and the end of A outside the range.
12145
12146     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
12147     {
12148         if (XTnum != regionIndex) // we don't need to update our 'last' pointer
12149         {
12150             if (HBtab->ebdTryLast == bLast)
12151             {
12152                 // If we moved a set of blocks that were at the end of
12153                 // a different try region then we may need to update ebdTryLast
12154                 for (block = HBtab->ebdTryBeg; block != nullptr; block = block->bbNext)
12155                 {
12156                     if (block == bPrev)
12157                     {
12158                         // We were contained within it, so shrink its region by
12159                         // setting its 'last'
12160                         fgSetTryEnd(HBtab, bPrev);
12161                         break;
12162                     }
12163                     else if (block == HBtab->ebdTryLast->bbNext)
12164                     {
12165                         // bPrev does not come after the TryBeg, thus we are larger, and
12166                         // it is moving with us.
12167                         break;
12168                     }
12169                 }
12170             }
12171             if (HBtab->ebdHndLast == bLast)
12172             {
12173                 // If we moved a set of blocks that were at the end of
12174                 // a different handler region then we must update ebdHndLast
12175                 for (block = HBtab->ebdHndBeg; block != nullptr; block = block->bbNext)
12176                 {
12177                     if (block == bPrev)
12178                     {
12179                         fgSetHndEnd(HBtab, bPrev);
12180                         break;
12181                     }
12182                     else if (block == HBtab->ebdHndLast->bbNext)
12183                     {
12184                         // bPrev does not come after the HndBeg
12185                         break;
12186                     }
12187                 }
12188             }
12189         }
12190     } // end exception table iteration
12191
12192     // Insert the block(s) we are moving after fgLastBlock
12193     fgMoveBlocksAfter(bStart, bLast, insertAfterBlk);
12194
12195     if (fgFirstFuncletBB == nullptr) // The funclet region isn't set yet
12196     {
12197         fgFirstFuncletBB = bStart;
12198     }
12199     else
12200     {
12201         assert(fgFirstFuncletBB !=
12202                insertAfterBlk->bbNext); // We insert at the end, not at the beginning, of the funclet region.
12203     }
12204
12205     // These asserts assume we aren't moving try regions (which we might need to do). Only
12206     // try regions can have fall through into or out of the region.
12207
12208     noway_assert(!bPrev->bbFallsThrough()); // There can be no fall through into a filter or handler region
12209     noway_assert(!bLast->bbFallsThrough()); // There can be no fall through out of a handler region
12210
12211 #ifdef DEBUG
12212     if (verbose)
12213     {
12214         printf("Create funclets: moved region\n");
12215         fgDispHandlerTab();
12216     }
12217
12218     // We have to wait to do this until we've created all the additional regions
12219     // Because this relies on ebdEnclosingTryIndex and ebdEnclosingHndIndex
12220     if (!FEATURE_EH_FUNCLETS)
12221     {
12222         // This is really expensive, and quickly becomes O(n^n) with funclets
12223         // so only do it once after we've created them (see fgCreateFunclets)
12224         if (expensiveDebugCheckLevel >= 2)
12225         {
12226             fgDebugCheckBBlist();
12227         }
12228     }
12229 #endif // DEBUG
12230
12231 #else // FEATURE_EH_FUNCLETS
12232
12233     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
12234     {
12235         if (XTnum == regionIndex)
12236         {
12237             // Don't update our handler's Last info
12238             continue;
12239         }
12240
12241         if (HBtab->ebdTryLast == bLast)
12242         {
12243             // If we moved a set of blocks that were at the end of
12244             // a different try region then we may need to update ebdTryLast
12245             for (block = HBtab->ebdTryBeg; block != NULL; block = block->bbNext)
12246             {
12247                 if (block == bPrev)
12248                 {
12249                     fgSetTryEnd(HBtab, bPrev);
12250                     break;
12251                 }
12252                 else if (block == HBtab->ebdTryLast->bbNext)
12253                 {
12254                     // bPrev does not come after the TryBeg
12255                     break;
12256                 }
12257             }
12258         }
12259         if (HBtab->ebdHndLast == bLast)
12260         {
12261             // If we moved a set of blocks that were at the end of
12262             // a different handler region then we must update ebdHndLast
12263             for (block = HBtab->ebdHndBeg; block != NULL; block = block->bbNext)
12264             {
12265                 if (block == bPrev)
12266                 {
12267                     fgSetHndEnd(HBtab, bPrev);
12268                     break;
12269                 }
12270                 else if (block == HBtab->ebdHndLast->bbNext)
12271                 {
12272                     // bPrev does not come after the HndBeg
12273                     break;
12274                 }
12275             }
12276         }
12277     } // end exception table iteration
12278
12279     // We have decided to insert the block(s) after fgLastBlock
12280     fgMoveBlocksAfter(bStart, bLast, insertAfterBlk);
12281
12282     // If bPrev falls through, we will insert a jump to block
12283     fgConnectFallThrough(bPrev, bStart);
12284
12285     // If bLast falls through, we will insert a jump to bNext
12286     fgConnectFallThrough(bLast, bNext);
12287
12288 #endif // FEATURE_EH_FUNCLETS
12289
12290     goto DONE;
12291
12292 FAILURE:
12293
12294 #ifdef DEBUG
12295     if (verbose)
12296     {
12297         printf("*************** Failed fgRelocateEHRange(BB%02u..BB%02u) because %s\n", bStart->bbNum, bLast->bbNum,
12298                reason);
12299     }
12300 #endif // DEBUG
12301
12302     bLast = nullptr;
12303
12304 DONE:
12305
12306     return bLast;
12307 }
12308
12309 #if FEATURE_EH_FUNCLETS
12310
12311 #if defined(_TARGET_ARM_)
12312
12313 /*****************************************************************************
12314  * We just removed a BBJ_CALLFINALLY/BBJ_ALWAYS pair. If this was the only such pair
12315  * targeting the BBJ_ALWAYS target, then we need to clear the BBF_FINALLY_TARGET bit
12316  * so that target can also be removed. 'block' is the finally target. Since we just
12317  * removed the BBJ_ALWAYS, it better have the BBF_FINALLY_TARGET bit set.
12318  */
12319
12320 void Compiler::fgClearFinallyTargetBit(BasicBlock* block)
12321 {
12322     assert(fgComputePredsDone);
12323     assert((block->bbFlags & BBF_FINALLY_TARGET) != 0);
12324
12325     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
12326     {
12327         if (pred->flBlock->bbJumpKind == BBJ_ALWAYS && pred->flBlock->bbJumpDest == block)
12328         {
12329             BasicBlock* pPrev = pred->flBlock->bbPrev;
12330             if (pPrev != NULL)
12331             {
12332                 if (pPrev->bbJumpKind == BBJ_CALLFINALLY)
12333                 {
12334                     // We found a BBJ_CALLFINALLY / BBJ_ALWAYS that still points to this finally target
12335                     return;
12336                 }
12337             }
12338         }
12339     }
12340
12341     // Didn't find any BBJ_CALLFINALLY / BBJ_ALWAYS that still points here, so clear the bit
12342
12343     block->bbFlags &= ~BBF_FINALLY_TARGET;
12344 }
12345
12346 #endif // defined(_TARGET_ARM_)
12347
12348 /*****************************************************************************
12349  * Is this an intra-handler control flow edge?
12350  *
12351  * 'block' is the head block of a funclet/handler region, or .
12352  * 'predBlock' is a predecessor block of 'block' in the predecessor list.
12353  *
12354  * 'predBlock' can legally only be one of three things:
12355  * 1. in the same handler region (e.g., the source of a back-edge of a loop from
12356  *    'predBlock' to 'block'), including in nested regions within the handler,
12357  * 2. if 'block' begins a handler that is a filter-handler, 'predBlock' must be in the 'filter' region,
12358  * 3. for other handlers, 'predBlock' must be in the 'try' region corresponding to handler (or any
12359  *    region nested in the 'try' region).
12360  *
12361  * Note that on AMD64/ARM64, the BBJ_CALLFINALLY block that calls a finally handler is not
12362  * within the corresponding 'try' region: it is placed in the corresponding 'try' region's
12363  * parent (which might be the main function body). This is how it is represented to the VM
12364  * (with a special "cloned finally" EH table entry).
12365  *
12366  * Return 'true' for case #1, and 'false' otherwise.
12367  */
12368 bool Compiler::fgIsIntraHandlerPred(BasicBlock* predBlock, BasicBlock* block)
12369 {
12370     // Some simple preconditions (as stated above)
12371     assert(!fgFuncletsCreated);
12372     assert(fgGetPredForBlock(block, predBlock) != nullptr);
12373     assert(block->hasHndIndex());
12374
12375     EHblkDsc* xtab = ehGetDsc(block->getHndIndex());
12376
12377 #if FEATURE_EH_CALLFINALLY_THUNKS
12378     if (xtab->HasFinallyHandler())
12379     {
12380         assert((xtab->ebdHndBeg == block) || // The normal case
12381                ((xtab->ebdHndBeg->bbNext == block) &&
12382                 (xtab->ebdHndBeg->bbFlags & BBF_INTERNAL))); // After we've already inserted a header block, and we're
12383                                                              // trying to decide how to split up the predecessor edges.
12384         if (predBlock->bbJumpKind == BBJ_CALLFINALLY)
12385         {
12386             assert(predBlock->bbJumpDest == block);
12387
12388             // A BBJ_CALLFINALLY predecessor of the handler can only come from the corresponding try,
12389             // not from any EH clauses nested in this handler. However, we represent the BBJ_CALLFINALLY
12390             // as being in the 'try' region's parent EH region, which might be the main function body.
12391
12392             unsigned tryIndex = xtab->ebdEnclosingTryIndex;
12393             if (tryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
12394             {
12395                 assert(!predBlock->hasTryIndex());
12396             }
12397             else
12398             {
12399                 assert(predBlock->hasTryIndex());
12400                 assert(tryIndex == predBlock->getTryIndex());
12401                 assert(ehGetDsc(tryIndex)->InTryRegionBBRange(predBlock));
12402             }
12403             return false;
12404         }
12405     }
12406 #endif // FEATURE_EH_CALLFINALLY_THUNKS
12407
12408     assert(predBlock->hasHndIndex() || predBlock->hasTryIndex());
12409
12410     //   We could search the try region looking for predBlock by using bbInTryRegions
12411     // but that does a lexical search for the block, and then assumes funclets
12412     // have been created and does a lexical search of all funclets that were pulled
12413     // out of the parent try region.
12414     //   First, funclets haven't been created yet, and even if they had been, we shouldn't
12415     // have any funclet directly branching to another funclet (they have to return first).
12416     // So we can safely use CheckIsTryRegion instead of bbInTryRegions.
12417     //   Second, I believe the depth of any EH graph will on average be smaller than the
12418     // breadth of the blocks within a try body. Thus it is faster to get our answer by
12419     // looping outward over the region graph. However, I have added asserts, as a
12420     // precaution, to ensure both algorithms agree. The asserts also check that the only
12421     // way to reach the head of a funclet is from the corresponding try body or from
12422     // within the funclet (and *not* any nested funclets).
12423
12424     if (predBlock->hasTryIndex())
12425     {
12426         // Because the EH clauses are listed inside-out, any nested trys will be at a
12427         // lower index than the current try and if there's no enclosing try, tryIndex
12428         // will terminate at NO_ENCLOSING_INDEX
12429
12430         unsigned tryIndex = predBlock->getTryIndex();
12431         while (tryIndex < block->getHndIndex())
12432         {
12433             tryIndex = ehGetEnclosingTryIndex(tryIndex);
12434         }
12435         // tryIndex should enclose predBlock
12436         assert((tryIndex == EHblkDsc::NO_ENCLOSING_INDEX) || ehGetDsc(tryIndex)->InTryRegionBBRange(predBlock));
12437
12438         // At this point tryIndex is either block's handler's corresponding try body
12439         // or some outer try region that contains both predBlock & block or
12440         // NO_ENCLOSING_REGION (because there was no try body that encloses both).
12441         if (tryIndex == block->getHndIndex())
12442         {
12443             assert(xtab->InTryRegionBBRange(predBlock));
12444             assert(!xtab->InHndRegionBBRange(predBlock));
12445             return false;
12446         }
12447         // tryIndex should enclose block (and predBlock as previously asserted)
12448         assert((tryIndex == EHblkDsc::NO_ENCLOSING_INDEX) || ehGetDsc(tryIndex)->InTryRegionBBRange(block));
12449     }
12450     if (xtab->HasFilter())
12451     {
12452         // The block is a handler. Check if the pred block is from its filter. We only need to
12453         // check the end filter flag, as there is only a single filter for any handler, and we
12454         // already know predBlock is a predecessor of block.
12455         if (predBlock->bbJumpKind == BBJ_EHFILTERRET)
12456         {
12457             assert(!xtab->InHndRegionBBRange(predBlock));
12458             return false;
12459         }
12460     }
12461     // It is not in our try region (or filter), so it must be within this handler (or try bodies
12462     // within this handler)
12463     assert(!xtab->InTryRegionBBRange(predBlock));
12464     assert(xtab->InHndRegionBBRange(predBlock));
12465     return true;
12466 }
12467
12468 /*****************************************************************************
12469  * Does this block, first block of a handler region, have any predecessor edges
12470  * that are not from its corresponding try region?
12471  */
12472
12473 bool Compiler::fgAnyIntraHandlerPreds(BasicBlock* block)
12474 {
12475     assert(block->hasHndIndex());
12476     assert(fgFirstBlockOfHandler(block) == block); // this block is the first block of a handler
12477
12478     flowList* pred;
12479
12480     for (pred = block->bbPreds; pred; pred = pred->flNext)
12481     {
12482         BasicBlock* predBlock = pred->flBlock;
12483
12484         if (fgIsIntraHandlerPred(predBlock, block))
12485         {
12486             // We have a predecessor that is not from our try region
12487             return true;
12488         }
12489     }
12490
12491     return false;
12492 }
12493
12494 /*****************************************************************************
12495  * Introduce a new head block of the handler for the prolog to be put in, ahead
12496  * of the current handler head 'block'.
12497  * Note that this code has some similarities to fgCreateLoopPreHeader().
12498  */
12499
12500 void Compiler::fgInsertFuncletPrologBlock(BasicBlock* block)
12501 {
12502 #ifdef DEBUG
12503     if (verbose)
12504     {
12505         printf("\nCreating funclet prolog header for BB%02u\n", block->bbNum);
12506     }
12507 #endif
12508
12509     assert(block->hasHndIndex());
12510     assert(fgFirstBlockOfHandler(block) == block); // this block is the first block of a handler
12511
12512     /* Allocate a new basic block */
12513
12514     BasicBlock* newHead = bbNewBasicBlock(BBJ_NONE);
12515
12516     // In fgComputePreds() we set the BBF_JMP_TARGET and BBF_HAS_LABEL for all of the handler entry points
12517     //
12518     newHead->bbFlags |= (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL);
12519     newHead->inheritWeight(block);
12520     newHead->bbRefs = 0;
12521
12522     fgInsertBBbefore(block, newHead); // insert the new block in the block list
12523     fgExtendEHRegionBefore(block);    // Update the EH table to make the prolog block the first block in the block's EH
12524                                       // block.
12525
12526     // Distribute the pred list between newHead and block. Incoming edges coming from outside
12527     // the handler go to the prolog. Edges coming from with the handler are back-edges, and
12528     // go to the existing 'block'.
12529
12530     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
12531     {
12532         BasicBlock* predBlock = pred->flBlock;
12533         if (!fgIsIntraHandlerPred(predBlock, block))
12534         {
12535             // It's a jump from outside the handler; add it to the newHead preds list and remove
12536             // it from the block preds list.
12537
12538             switch (predBlock->bbJumpKind)
12539             {
12540                 case BBJ_CALLFINALLY:
12541                     noway_assert(predBlock->bbJumpDest == block);
12542                     predBlock->bbJumpDest = newHead;
12543                     fgRemoveRefPred(block, predBlock);
12544                     fgAddRefPred(newHead, predBlock);
12545                     break;
12546
12547                 default:
12548                     // The only way into the handler is via a BBJ_CALLFINALLY (to a finally handler), or
12549                     // via exception handling.
12550                     noway_assert(false);
12551                     break;
12552             }
12553         }
12554     }
12555
12556     assert(nullptr == fgGetPredForBlock(block, newHead));
12557     fgAddRefPred(block, newHead);
12558
12559     assert((newHead->bbFlags & (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL)) ==
12560            (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL));
12561 }
12562
12563 /*****************************************************************************
12564  *
12565  * Every funclet will have a prolog. That prolog will be inserted as the first instructions
12566  * in the first block of the funclet. If the prolog is also the head block of a loop, we
12567  * would end up with the prolog instructions being executed more than once.
12568  * Check for this by searching the predecessor list for loops, and create a new prolog header
12569  * block when needed. We detect a loop by looking for any predecessor that isn't in the
12570  * handler's try region, since the only way to get into a handler is via that try region.
12571  */
12572
12573 void Compiler::fgCreateFuncletPrologBlocks()
12574 {
12575     noway_assert(fgComputePredsDone);
12576     noway_assert(!fgDomsComputed); // this function doesn't maintain the dom sets
12577     assert(!fgFuncletsCreated);
12578
12579     bool      prologBlocksCreated = false;
12580     EHblkDsc* HBtabEnd;
12581     EHblkDsc* HBtab;
12582
12583     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
12584     {
12585         BasicBlock* head = HBtab->ebdHndBeg;
12586
12587         if (fgAnyIntraHandlerPreds(head))
12588         {
12589             // We need to create a new block in which to place the prolog, and split the existing
12590             // head block predecessor edges into those that should point to the prolog, and those
12591             // that shouldn't.
12592             //
12593             // It's arguable that we should just always do this, and not only when we "need to",
12594             // so there aren't two different code paths. However, it's unlikely to be necessary
12595             // for catch handlers because they have an incoming argument (the exception object)
12596             // that needs to get stored or saved, so back-arcs won't normally go to the head. It's
12597             // possible when writing in IL to generate a legal loop (e.g., push an Exception object
12598             // on the stack before jumping back to the catch head), but C# probably won't. This will
12599             // most commonly only be needed for finallys with a do/while loop at the top of the
12600             // finally.
12601             //
12602             // Note that we don't check filters. This might be a bug, but filters always have a filter
12603             // object live on entry, so it's at least unlikely (illegal?) that a loop edge targets the
12604             // filter head.
12605
12606             fgInsertFuncletPrologBlock(head);
12607             prologBlocksCreated = true;
12608         }
12609     }
12610
12611     if (prologBlocksCreated)
12612     {
12613         // If we've modified the graph, reset the 'modified' flag, since the dominators haven't
12614         // been computed.
12615         fgModified = false;
12616
12617 #if DEBUG
12618         if (verbose)
12619         {
12620             JITDUMP("\nAfter fgCreateFuncletPrologBlocks()");
12621             fgDispBasicBlocks();
12622             fgDispHandlerTab();
12623         }
12624
12625         fgVerifyHandlerTab();
12626         fgDebugCheckBBlist();
12627 #endif // DEBUG
12628     }
12629 }
12630
12631 /*****************************************************************************
12632  *
12633  *  Function to create funclets out of all EH catch/finally/fault blocks.
12634  *  We only move filter and handler blocks, not try blocks.
12635  */
12636
12637 void Compiler::fgCreateFunclets()
12638 {
12639     assert(!fgFuncletsCreated);
12640
12641 #ifdef DEBUG
12642     if (verbose)
12643     {
12644         printf("*************** In fgCreateFunclets()\n");
12645     }
12646 #endif
12647
12648     fgCreateFuncletPrologBlocks();
12649
12650     unsigned           XTnum;
12651     EHblkDsc*          HBtab;
12652     const unsigned int funcCnt = ehFuncletCount() + 1;
12653
12654     if (!FitsIn<unsigned short>(funcCnt))
12655     {
12656         IMPL_LIMITATION("Too many funclets");
12657     }
12658
12659     FuncInfoDsc* funcInfo = new (this, CMK_BasicBlock) FuncInfoDsc[funcCnt];
12660
12661     unsigned short funcIdx;
12662
12663     // Setup the root FuncInfoDsc and prepare to start associating
12664     // FuncInfoDsc's with their corresponding EH region
12665     memset((void*)funcInfo, 0, funcCnt * sizeof(FuncInfoDsc));
12666     assert(funcInfo[0].funKind == FUNC_ROOT);
12667     funcIdx = 1;
12668
12669     // Because we iterate from the top to the bottom of the compHndBBtab array, we are iterating
12670     // from most nested (innermost) to least nested (outermost) EH region. It would be reasonable
12671     // to iterate in the opposite order, but the order of funclets shouldn't matter.
12672     //
12673     // We move every handler region to the end of the function: each handler will become a funclet.
12674     //
12675     // Note that fgRelocateEHRange() can add new entries to the EH table. However, they will always
12676     // be added *after* the current index, so our iteration here is not invalidated.
12677     // It *can* invalidate the compHndBBtab pointer itself, though, if it gets reallocated!
12678
12679     for (XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
12680     {
12681         HBtab = ehGetDsc(XTnum); // must re-compute this every loop, since fgRelocateEHRange changes the table
12682         if (HBtab->HasFilter())
12683         {
12684             assert(funcIdx < funcCnt);
12685             funcInfo[funcIdx].funKind    = FUNC_FILTER;
12686             funcInfo[funcIdx].funEHIndex = (unsigned short)XTnum;
12687             funcIdx++;
12688         }
12689         assert(funcIdx < funcCnt);
12690         funcInfo[funcIdx].funKind    = FUNC_HANDLER;
12691         funcInfo[funcIdx].funEHIndex = (unsigned short)XTnum;
12692         HBtab->ebdFuncIndex          = funcIdx;
12693         funcIdx++;
12694         fgRelocateEHRange(XTnum, FG_RELOCATE_HANDLER);
12695     }
12696
12697     // We better have populated all of them by now
12698     assert(funcIdx == funcCnt);
12699
12700     // Publish
12701     compCurrFuncIdx   = 0;
12702     compFuncInfos     = funcInfo;
12703     compFuncInfoCount = (unsigned short)funcCnt;
12704
12705     fgFuncletsCreated = true;
12706
12707 #if DEBUG
12708     if (verbose)
12709     {
12710         JITDUMP("\nAfter fgCreateFunclets()");
12711         fgDispBasicBlocks();
12712         fgDispHandlerTab();
12713     }
12714
12715     fgVerifyHandlerTab();
12716     fgDebugCheckBBlist();
12717 #endif // DEBUG
12718 }
12719
12720 #else // !FEATURE_EH_FUNCLETS
12721
12722 /*****************************************************************************
12723  *
12724  *  Function called to relocate any and all EH regions.
12725  *  Only entire consecutive EH regions will be moved and they will be kept together.
12726  *  Except for the first block, the range can not have any blocks that jump into or out of the region.
12727  */
12728
12729 bool Compiler::fgRelocateEHRegions()
12730 {
12731     bool result = false; // Our return value
12732
12733 #ifdef DEBUG
12734     if (verbose)
12735         printf("*************** In fgRelocateEHRegions()\n");
12736 #endif
12737
12738     if (fgCanRelocateEHRegions)
12739     {
12740         unsigned  XTnum;
12741         EHblkDsc* HBtab;
12742
12743         for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
12744         {
12745             // Nested EH regions cannot be moved.
12746             // Also we don't want to relocate an EH region that has a filter
12747             if ((HBtab->ebdHandlerNestingLevel == 0) && !HBtab->HasFilter())
12748             {
12749                 bool movedTry = false;
12750 #if DEBUG
12751                 bool movedHnd = false;
12752 #endif // DEBUG
12753
12754                 // Only try to move the outermost try region
12755                 if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
12756                 {
12757                     // Move the entire try region if it can be moved
12758                     if (HBtab->ebdTryBeg->isRunRarely())
12759                     {
12760                         BasicBlock* bTryLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_TRY);
12761                         if (bTryLastBB != NULL)
12762                         {
12763                             result   = true;
12764                             movedTry = true;
12765                         }
12766                     }
12767 #if DEBUG
12768                     if (verbose && movedTry)
12769                     {
12770                         printf("\nAfter relocating an EH try region");
12771                         fgDispBasicBlocks();
12772                         fgDispHandlerTab();
12773
12774                         // Make sure that the predecessor lists are accurate
12775                         if (expensiveDebugCheckLevel >= 2)
12776                         {
12777                             fgDebugCheckBBlist();
12778                         }
12779                     }
12780 #endif // DEBUG
12781                 }
12782
12783                 // Currently it is not good to move the rarely run handler regions to the end of the method
12784                 // because fgDetermineFirstColdBlock() must put the start of any handler region in the hot
12785                 // section.
12786                 CLANG_FORMAT_COMMENT_ANCHOR;
12787
12788 #if 0
12789                 // Now try to move the entire handler region if it can be moved.
12790                 // Don't try to move a finally handler unless we already moved the try region.
12791                 if (HBtab->ebdHndBeg->isRunRarely() &&
12792                     !HBtab->ebdHndBeg->hasTryIndex() &&
12793                     (movedTry || !HBtab->HasFinallyHandler()))
12794                 {
12795                     BasicBlock* bHndLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_HANDLER);
12796                     if (bHndLastBB != NULL)
12797                     {
12798                         result   = true;
12799                         movedHnd = true;
12800                     }
12801                 }
12802 #endif // 0
12803
12804 #if DEBUG
12805                 if (verbose && movedHnd)
12806                 {
12807                     printf("\nAfter relocating an EH handler region");
12808                     fgDispBasicBlocks();
12809                     fgDispHandlerTab();
12810
12811                     // Make sure that the predecessor lists are accurate
12812                     if (expensiveDebugCheckLevel >= 2)
12813                     {
12814                         fgDebugCheckBBlist();
12815                     }
12816                 }
12817 #endif // DEBUG
12818             }
12819         }
12820     }
12821
12822 #if DEBUG
12823     fgVerifyHandlerTab();
12824
12825     if (verbose && result)
12826     {
12827         printf("\nAfter fgRelocateEHRegions()");
12828         fgDispBasicBlocks();
12829         fgDispHandlerTab();
12830         // Make sure that the predecessor lists are accurate
12831         fgDebugCheckBBlist();
12832     }
12833 #endif // DEBUG
12834
12835     return result;
12836 }
12837
12838 #endif // !FEATURE_EH_FUNCLETS
12839
12840 bool flowList::setEdgeWeightMinChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop)
12841 {
12842     bool result = false;
12843     if ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin))
12844     {
12845         flEdgeWeightMin = newWeight;
12846         result          = true;
12847     }
12848     else if (slop > 0)
12849     {
12850         // We allow for a small amount of inaccuracy in block weight counts.
12851         if (flEdgeWeightMax < newWeight)
12852         {
12853             // We have already determined that this edge's weight
12854             // is less than newWeight, so we just allow for the slop
12855             if (newWeight <= (flEdgeWeightMax + slop))
12856             {
12857                 result = true;
12858
12859                 if (flEdgeWeightMax != 0)
12860                 {
12861                     // We will raise flEdgeWeightMin and Max towards newWeight
12862                     flEdgeWeightMin = flEdgeWeightMax;
12863                     flEdgeWeightMax = newWeight;
12864                 }
12865
12866                 if (wbUsedSlop != nullptr)
12867                 {
12868                     *wbUsedSlop = true;
12869                 }
12870             }
12871         }
12872         else
12873         {
12874             assert(flEdgeWeightMin > newWeight);
12875
12876             // We have already determined that this edge's weight
12877             // is more than newWeight, so we just allow for the slop
12878             if ((newWeight + slop) >= flEdgeWeightMin)
12879             {
12880                 result = true;
12881
12882                 assert(flEdgeWeightMax != 0);
12883
12884                 // We will lower flEdgeWeightMin towards newWeight
12885                 flEdgeWeightMin = newWeight;
12886
12887                 if (wbUsedSlop != nullptr)
12888                 {
12889                     *wbUsedSlop = true;
12890                 }
12891             }
12892         }
12893
12894         // If we are returning true then we should have adjusted the range so that
12895         // the newWeight is in new range [Min..Max] or fgEdjeWeightMax is zero.
12896         // Also we should have set wbUsedSlop to true.
12897         if (result == true)
12898         {
12899             assert((flEdgeWeightMax == 0) || ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin)));
12900
12901             if (wbUsedSlop != nullptr)
12902             {
12903                 assert(*wbUsedSlop == true);
12904             }
12905         }
12906     }
12907
12908 #if DEBUG
12909     if (result == false)
12910     {
12911         result = false; // break here
12912     }
12913 #endif // DEBUG
12914
12915     return result;
12916 }
12917
12918 bool flowList::setEdgeWeightMaxChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop)
12919 {
12920     bool result = false;
12921     if ((newWeight >= flEdgeWeightMin) && (newWeight <= flEdgeWeightMax))
12922     {
12923         flEdgeWeightMax = newWeight;
12924         result          = true;
12925     }
12926     else if (slop > 0)
12927     {
12928         // We allow for a small amount of inaccuracy in block weight counts.
12929         if (flEdgeWeightMax < newWeight)
12930         {
12931             // We have already determined that this edge's weight
12932             // is less than newWeight, so we just allow for the slop
12933             if (newWeight <= (flEdgeWeightMax + slop))
12934             {
12935                 result = true;
12936
12937                 if (flEdgeWeightMax != 0)
12938                 {
12939                     // We will allow this to raise flEdgeWeightMax towards newWeight
12940                     flEdgeWeightMax = newWeight;
12941                 }
12942
12943                 if (wbUsedSlop != nullptr)
12944                 {
12945                     *wbUsedSlop = true;
12946                 }
12947             }
12948         }
12949         else
12950         {
12951             assert(flEdgeWeightMin > newWeight);
12952
12953             // We have already determined that this edge's weight
12954             // is more than newWeight, so we just allow for the slop
12955             if ((newWeight + slop) >= flEdgeWeightMin)
12956             {
12957                 result = true;
12958
12959                 assert(flEdgeWeightMax != 0);
12960
12961                 // We will allow this to lower flEdgeWeightMin and Max towards newWeight
12962                 flEdgeWeightMax = flEdgeWeightMin;
12963                 flEdgeWeightMin = newWeight;
12964
12965                 if (wbUsedSlop != nullptr)
12966                 {
12967                     *wbUsedSlop = true;
12968                 }
12969             }
12970         }
12971
12972         // If we are returning true then we should have adjusted the range so that
12973         // the newWeight is in new range [Min..Max] or fgEdjeWeightMax is zero
12974         // Also we should have set wbUsedSlop to true, unless it is NULL
12975         if (result == true)
12976         {
12977             assert((flEdgeWeightMax == 0) || ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin)));
12978
12979             assert((wbUsedSlop == nullptr) || (*wbUsedSlop == true));
12980         }
12981     }
12982
12983 #if DEBUG
12984     if (result == false)
12985     {
12986         result = false; // break here
12987     }
12988 #endif // DEBUG
12989
12990     return result;
12991 }
12992
12993 #ifdef DEBUG
12994 void Compiler::fgPrintEdgeWeights()
12995 {
12996     BasicBlock* bSrc;
12997     BasicBlock* bDst;
12998     flowList*   edge;
12999
13000     // Print out all of the edge weights
13001     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13002     {
13003         if (bDst->bbPreds != nullptr)
13004         {
13005             printf("    Edge weights into BB%02u :", bDst->bbNum);
13006             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13007             {
13008                 bSrc = edge->flBlock;
13009                 // This is the control flow edge (bSrc -> bDst)
13010
13011                 printf("BB%02u ", bSrc->bbNum);
13012
13013                 if (edge->flEdgeWeightMin < BB_MAX_WEIGHT)
13014                 {
13015                     printf("(%u", edge->flEdgeWeightMin);
13016                 }
13017                 else
13018                 {
13019                     printf("(MAX");
13020                 }
13021                 if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
13022                 {
13023                     if (edge->flEdgeWeightMax < BB_MAX_WEIGHT)
13024                     {
13025                         printf("..%u", edge->flEdgeWeightMax);
13026                     }
13027                     else
13028                     {
13029                         printf("..MAX");
13030                     }
13031                 }
13032                 printf(")");
13033                 if (edge->flNext != nullptr)
13034                 {
13035                     printf(", ");
13036                 }
13037             }
13038             printf("\n");
13039         }
13040     }
13041 }
13042 #endif // DEBUG
13043
13044 // return true if there is a possibility that the method has a loop (a backedge is present)
13045 bool Compiler::fgMightHaveLoop()
13046 {
13047     // Don't use a BlockSet for this temporary bitset of blocks: we don't want to have to call EnsureBasicBlockEpoch()
13048     // and potentially change the block epoch.
13049
13050     BitVecTraits blockVecTraits(fgBBNumMax + 1, this);
13051     BitVec       blocksSeen(BitVecOps::MakeEmpty(&blockVecTraits));
13052
13053     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
13054     {
13055         BitVecOps::AddElemD(&blockVecTraits, blocksSeen, block->bbNum);
13056
13057         for (BasicBlock* succ : block->GetAllSuccs(this))
13058         {
13059             if (BitVecOps::IsMember(&blockVecTraits, blocksSeen, succ->bbNum))
13060             {
13061                 return true;
13062             }
13063         }
13064     }
13065     return false;
13066 }
13067
13068 void Compiler::fgComputeEdgeWeights()
13069 {
13070 #ifdef DEBUG
13071     if (verbose)
13072     {
13073         printf("*************** In fgComputeEdgeWeights()\n");
13074     }
13075 #endif // DEBUG
13076
13077     if (fgIsUsingProfileWeights() == false)
13078     {
13079 #ifdef DEBUG
13080         if (verbose)
13081         {
13082             printf("fgComputeEdgeWeights() we do not have any profile data so we are not using the edge weights\n");
13083         }
13084 #endif // DEBUG
13085         fgHaveValidEdgeWeights = false;
13086         fgCalledCount          = BB_UNITY_WEIGHT;
13087     }
13088
13089 #if DEBUG
13090     if (verbose)
13091     {
13092         fgDispBasicBlocks();
13093         printf("\n");
13094     }
13095 #endif // DEBUG
13096
13097     BasicBlock* bSrc;
13098     BasicBlock* bDst;
13099     flowList*   edge;
13100     unsigned    iterations               = 0;
13101     unsigned    goodEdgeCountCurrent     = 0;
13102     unsigned    goodEdgeCountPrevious    = 0;
13103     bool        inconsistentProfileData  = false;
13104     bool        hasIncompleteEdgeWeights = false;
13105     unsigned    numEdges                 = 0;
13106     bool        usedSlop                 = false;
13107     bool        changed;
13108     bool        modified;
13109
13110     BasicBlock::weight_t returnWeight;
13111     BasicBlock::weight_t slop;
13112
13113     // If we have any blocks that did not have profile derived weight
13114     // we will try to fix their weight up here
13115     //
13116     modified = false;
13117     do // while (changed)
13118     {
13119         changed      = false;
13120         returnWeight = 0;
13121         iterations++;
13122
13123         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13124         {
13125             if (!bDst->hasProfileWeight() && (bDst->bbPreds != nullptr))
13126             {
13127                 BasicBlock* bOnlyNext;
13128
13129                 // This block does not have a profile derived weight
13130                 //
13131                 BasicBlock::weight_t newWeight = BB_MAX_WEIGHT;
13132
13133                 if (bDst->countOfInEdges() == 1)
13134                 {
13135                     // Only one block flows into bDst
13136                     bSrc = bDst->bbPreds->flBlock;
13137
13138                     // Does this block flow into only one other block
13139                     if (bSrc->bbJumpKind == BBJ_NONE)
13140                     {
13141                         bOnlyNext = bSrc->bbNext;
13142                     }
13143                     else if (bSrc->bbJumpKind == BBJ_ALWAYS)
13144                     {
13145                         bOnlyNext = bSrc->bbJumpDest;
13146                     }
13147                     else
13148                     {
13149                         bOnlyNext = nullptr;
13150                     }
13151
13152                     if ((bOnlyNext == bDst) && bSrc->hasProfileWeight())
13153                     {
13154                         // We know the exact weight of bDst
13155                         newWeight = bSrc->bbWeight;
13156                     }
13157                 }
13158
13159                 // Does this block flow into only one other block
13160                 if (bDst->bbJumpKind == BBJ_NONE)
13161                 {
13162                     bOnlyNext = bDst->bbNext;
13163                 }
13164                 else if (bDst->bbJumpKind == BBJ_ALWAYS)
13165                 {
13166                     bOnlyNext = bDst->bbJumpDest;
13167                 }
13168                 else
13169                 {
13170                     bOnlyNext = nullptr;
13171                 }
13172
13173                 if ((bOnlyNext != nullptr) && (bOnlyNext->bbPreds != nullptr))
13174                 {
13175                     // Does only one block flow into bOnlyNext
13176                     if (bOnlyNext->countOfInEdges() == 1)
13177                     {
13178                         noway_assert(bOnlyNext->bbPreds->flBlock == bDst);
13179
13180                         // We know the exact weight of bDst
13181                         newWeight = bOnlyNext->bbWeight;
13182                     }
13183                 }
13184
13185                 if ((newWeight != BB_MAX_WEIGHT) && (bDst->bbWeight != newWeight))
13186                 {
13187                     changed        = true;
13188                     modified       = true;
13189                     bDst->bbWeight = newWeight;
13190                     if (newWeight == 0)
13191                     {
13192                         bDst->bbFlags |= BBF_RUN_RARELY;
13193                     }
13194                     else
13195                     {
13196                         bDst->bbFlags &= ~BBF_RUN_RARELY;
13197                     }
13198                 }
13199             }
13200
13201             // Sum up the weights of all of the return blocks and throw blocks
13202             // This is used when we have a back-edge into block 1
13203             //
13204             if (bDst->hasProfileWeight() && ((bDst->bbJumpKind == BBJ_RETURN) || (bDst->bbJumpKind == BBJ_THROW)))
13205             {
13206                 returnWeight += bDst->bbWeight;
13207             }
13208         }
13209     }
13210     // Generally when we synthesize profile estimates we do it in a way where this algorithm will converge
13211     // but downstream opts that remove conditional branches may create a situation where this is not the case.
13212     // For instance a loop that becomes unreachable creates a sort of 'ring oscillator' (See test b539509)
13213     while (changed && iterations < 10);
13214
13215 #if DEBUG
13216     if (verbose && modified)
13217     {
13218         printf("fgComputeEdgeWeights() adjusted the weight of some blocks\n");
13219         fgDispBasicBlocks();
13220         printf("\n");
13221     }
13222 #endif
13223
13224     // When we are not using profile data we have already setup fgCalledCount
13225     // only set it here if we are using profile data
13226     //
13227     if (fgIsUsingProfileWeights())
13228     {
13229         BasicBlock* firstILBlock = fgFirstBB; // The first block for IL code (i.e. for the IL code at offset 0)
13230
13231         // Do we have an internal block as our first Block?
13232         if (firstILBlock->bbFlags & BBF_INTERNAL)
13233         {
13234             // Skip past any/all BBF_INTERNAL blocks that may have been added before the first real IL block.
13235             //
13236             while (firstILBlock->bbFlags & BBF_INTERNAL)
13237             {
13238                 firstILBlock = firstILBlock->bbNext;
13239             }
13240             // The 'firstILBlock' is now expected to have a profile-derived weight
13241             assert(firstILBlock->hasProfileWeight());
13242         }
13243
13244         // If the first block only has one ref then we use it's weight for fgCalledCount.
13245         // Otherwise we have backedge's into the first block, so instead we use the sum
13246         // of the return block weights for fgCalledCount.
13247         //
13248         // If the profile data has a 0 for the returnWeight
13249         // (i.e. the function never returns because it always throws)
13250         // then just use the first block weight rather than 0.
13251         //
13252         if ((firstILBlock->countOfInEdges() == 1) || (returnWeight == 0))
13253         {
13254             assert(firstILBlock->hasProfileWeight()); // This should always be a profile-derived weight
13255             fgCalledCount = firstILBlock->bbWeight;
13256         }
13257         else
13258         {
13259             fgCalledCount = returnWeight;
13260         }
13261
13262         // If we allocated a scratch block as the first BB then we need
13263         // to set its profile-derived weight to be fgCalledCount
13264         if (fgFirstBBisScratch())
13265         {
13266             fgFirstBB->setBBProfileWeight(fgCalledCount);
13267             if (fgFirstBB->bbWeight == 0)
13268             {
13269                 fgFirstBB->bbFlags |= BBF_RUN_RARELY;
13270             }
13271         }
13272
13273 #if DEBUG
13274         if (verbose)
13275         {
13276             printf("We are using the Profile Weights and fgCalledCount is %d.\n", fgCalledCount);
13277         }
13278 #endif
13279     }
13280
13281     // Now we will compute the initial flEdgeWeightMin and flEdgeWeightMax values
13282     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13283     {
13284         BasicBlock::weight_t bDstWeight = bDst->bbWeight;
13285
13286         // We subtract out the called count so that bDstWeight is
13287         // the sum of all edges that go into this block from this method.
13288         //
13289         if (bDst == fgFirstBB)
13290         {
13291             bDstWeight -= fgCalledCount;
13292         }
13293
13294         for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13295         {
13296             bool assignOK = true;
13297
13298             bSrc = edge->flBlock;
13299             // We are processing the control flow edge (bSrc -> bDst)
13300
13301             numEdges++;
13302
13303             //
13304             // If the bSrc or bDst blocks do not have exact profile weights
13305             // then we must reset any values that they currently have
13306             //
13307
13308             if (!bSrc->hasProfileWeight() || !bDst->hasProfileWeight())
13309             {
13310                 edge->flEdgeWeightMin = BB_ZERO_WEIGHT;
13311                 edge->flEdgeWeightMax = BB_MAX_WEIGHT;
13312             }
13313
13314             slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
13315             switch (bSrc->bbJumpKind)
13316             {
13317                 case BBJ_ALWAYS:
13318                 case BBJ_EHCATCHRET:
13319                 case BBJ_NONE:
13320                 case BBJ_CALLFINALLY:
13321                     // We know the exact edge weight
13322                     assignOK &= edge->setEdgeWeightMinChecked(bSrc->bbWeight, slop, &usedSlop);
13323                     assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, slop, &usedSlop);
13324                     break;
13325
13326                 case BBJ_COND:
13327                 case BBJ_SWITCH:
13328                 case BBJ_EHFINALLYRET:
13329                 case BBJ_EHFILTERRET:
13330                     if (edge->flEdgeWeightMax > bSrc->bbWeight)
13331                     {
13332                         // The maximum edge weight to block can't be greater than the weight of bSrc
13333                         assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, slop, &usedSlop);
13334                     }
13335                     break;
13336
13337                 default:
13338                     // We should never have an edge that starts from one of these jump kinds
13339                     noway_assert(!"Unexpected bbJumpKind");
13340                     break;
13341             }
13342
13343             // The maximum edge weight to block can't be greater than the weight of bDst
13344             if (edge->flEdgeWeightMax > bDstWeight)
13345             {
13346                 assignOK &= edge->setEdgeWeightMaxChecked(bDstWeight, slop, &usedSlop);
13347             }
13348
13349             if (!assignOK)
13350             {
13351                 // Here we have inconsistent profile data
13352                 inconsistentProfileData = true;
13353                 // No point in continuing
13354                 goto EARLY_EXIT;
13355             }
13356         }
13357     }
13358
13359     fgEdgeCount = numEdges;
13360
13361     iterations = 0;
13362
13363     do
13364     {
13365         iterations++;
13366         goodEdgeCountPrevious    = goodEdgeCountCurrent;
13367         goodEdgeCountCurrent     = 0;
13368         hasIncompleteEdgeWeights = false;
13369
13370         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13371         {
13372             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13373             {
13374                 bool assignOK = true;
13375
13376                 // We are processing the control flow edge (bSrc -> bDst)
13377                 bSrc = edge->flBlock;
13378
13379                 slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
13380                 if (bSrc->bbJumpKind == BBJ_COND)
13381                 {
13382                     int       diff;
13383                     flowList* otherEdge;
13384                     if (bSrc->bbNext == bDst)
13385                     {
13386                         otherEdge = fgGetPredForBlock(bSrc->bbJumpDest, bSrc);
13387                     }
13388                     else
13389                     {
13390                         otherEdge = fgGetPredForBlock(bSrc->bbNext, bSrc);
13391                     }
13392                     noway_assert(edge->flEdgeWeightMin <= edge->flEdgeWeightMax);
13393                     noway_assert(otherEdge->flEdgeWeightMin <= otherEdge->flEdgeWeightMax);
13394
13395                     // Adjust edge->flEdgeWeightMin up or adjust otherEdge->flEdgeWeightMax down
13396                     diff = ((int)bSrc->bbWeight) - ((int)edge->flEdgeWeightMin + (int)otherEdge->flEdgeWeightMax);
13397                     if (diff > 0)
13398                     {
13399                         assignOK &= edge->setEdgeWeightMinChecked(edge->flEdgeWeightMin + diff, slop, &usedSlop);
13400                     }
13401                     else if (diff < 0)
13402                     {
13403                         assignOK &=
13404                             otherEdge->setEdgeWeightMaxChecked(otherEdge->flEdgeWeightMax + diff, slop, &usedSlop);
13405                     }
13406
13407                     // Adjust otherEdge->flEdgeWeightMin up or adjust edge->flEdgeWeightMax down
13408                     diff = ((int)bSrc->bbWeight) - ((int)otherEdge->flEdgeWeightMin + (int)edge->flEdgeWeightMax);
13409                     if (diff > 0)
13410                     {
13411                         assignOK &=
13412                             otherEdge->setEdgeWeightMinChecked(otherEdge->flEdgeWeightMin + diff, slop, &usedSlop);
13413                     }
13414                     else if (diff < 0)
13415                     {
13416                         assignOK &= edge->setEdgeWeightMaxChecked(edge->flEdgeWeightMax + diff, slop, &usedSlop);
13417                     }
13418
13419                     if (!assignOK)
13420                     {
13421                         // Here we have inconsistent profile data
13422                         inconsistentProfileData = true;
13423                         // No point in continuing
13424                         goto EARLY_EXIT;
13425                     }
13426 #ifdef DEBUG
13427                     // Now edge->flEdgeWeightMin and otherEdge->flEdgeWeightMax) should add up to bSrc->bbWeight
13428                     diff = ((int)bSrc->bbWeight) - ((int)edge->flEdgeWeightMin + (int)otherEdge->flEdgeWeightMax);
13429                     noway_assert((-((int)slop) <= diff) && (diff <= ((int)slop)));
13430
13431                     // Now otherEdge->flEdgeWeightMin and edge->flEdgeWeightMax) should add up to bSrc->bbWeight
13432                     diff = ((int)bSrc->bbWeight) - ((int)otherEdge->flEdgeWeightMin + (int)edge->flEdgeWeightMax);
13433                     noway_assert((-((int)slop) <= diff) && (diff <= ((int)slop)));
13434 #endif // DEBUG
13435                 }
13436             }
13437         }
13438
13439         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13440         {
13441             BasicBlock::weight_t bDstWeight = bDst->bbWeight;
13442
13443             if (bDstWeight == BB_MAX_WEIGHT)
13444             {
13445                 inconsistentProfileData = true;
13446                 // No point in continuing
13447                 goto EARLY_EXIT;
13448             }
13449             else
13450             {
13451                 // We subtract out the called count so that bDstWeight is
13452                 // the sum of all edges that go into this block from this method.
13453                 //
13454                 if (bDst == fgFirstBB)
13455                 {
13456                     bDstWeight -= fgCalledCount;
13457                 }
13458
13459                 UINT64 minEdgeWeightSum = 0;
13460                 UINT64 maxEdgeWeightSum = 0;
13461
13462                 // Calculate the sums of the minimum and maximum edge weights
13463                 for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13464                 {
13465                     // We are processing the control flow edge (bSrc -> bDst)
13466                     bSrc = edge->flBlock;
13467
13468                     maxEdgeWeightSum += edge->flEdgeWeightMax;
13469                     minEdgeWeightSum += edge->flEdgeWeightMin;
13470                 }
13471
13472                 // maxEdgeWeightSum is the sum of all flEdgeWeightMax values into bDst
13473                 // minEdgeWeightSum is the sum of all flEdgeWeightMin values into bDst
13474
13475                 for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13476                 {
13477                     bool assignOK = true;
13478
13479                     // We are processing the control flow edge (bSrc -> bDst)
13480                     bSrc = edge->flBlock;
13481                     slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
13482
13483                     // otherMaxEdgesWeightSum is the sum of all of the other edges flEdgeWeightMax values
13484                     // This can be used to compute a lower bound for our minimum edge weight
13485                     noway_assert(maxEdgeWeightSum >= edge->flEdgeWeightMax);
13486                     UINT64 otherMaxEdgesWeightSum = maxEdgeWeightSum - edge->flEdgeWeightMax;
13487
13488                     // otherMinEdgesWeightSum is the sum of all of the other edges flEdgeWeightMin values
13489                     // This can be used to compute an upper bound for our maximum edge weight
13490                     noway_assert(minEdgeWeightSum >= edge->flEdgeWeightMin);
13491                     UINT64 otherMinEdgesWeightSum = minEdgeWeightSum - edge->flEdgeWeightMin;
13492
13493                     if (bDstWeight >= otherMaxEdgesWeightSum)
13494                     {
13495                         // minWeightCalc is our minWeight when every other path to bDst takes it's flEdgeWeightMax value
13496                         BasicBlock::weight_t minWeightCalc =
13497                             (BasicBlock::weight_t)(bDstWeight - otherMaxEdgesWeightSum);
13498                         if (minWeightCalc > edge->flEdgeWeightMin)
13499                         {
13500                             assignOK &= edge->setEdgeWeightMinChecked(minWeightCalc, slop, &usedSlop);
13501                         }
13502                     }
13503
13504                     if (bDstWeight >= otherMinEdgesWeightSum)
13505                     {
13506                         // maxWeightCalc is our maxWeight when every other path to bDst takes it's flEdgeWeightMin value
13507                         BasicBlock::weight_t maxWeightCalc =
13508                             (BasicBlock::weight_t)(bDstWeight - otherMinEdgesWeightSum);
13509                         if (maxWeightCalc < edge->flEdgeWeightMax)
13510                         {
13511                             assignOK &= edge->setEdgeWeightMaxChecked(maxWeightCalc, slop, &usedSlop);
13512                         }
13513                     }
13514
13515                     if (!assignOK)
13516                     {
13517                         // Here we have inconsistent profile data
13518                         inconsistentProfileData = true;
13519                         // No point in continuing
13520                         goto EARLY_EXIT;
13521                     }
13522
13523                     // When flEdgeWeightMin equals flEdgeWeightMax we have a "good" edge weight
13524                     if (edge->flEdgeWeightMin == edge->flEdgeWeightMax)
13525                     {
13526                         // Count how many "good" edge weights we have
13527                         // Each time through we should have more "good" weights
13528                         // We exit the while loop when no longer find any new "good" edges
13529                         goodEdgeCountCurrent++;
13530                     }
13531                     else
13532                     {
13533                         // Remember that we have seen at least one "Bad" edge weight
13534                         // so that we will repeat the while loop again
13535                         hasIncompleteEdgeWeights = true;
13536                     }
13537                 }
13538             }
13539         }
13540
13541         if (inconsistentProfileData)
13542         {
13543             hasIncompleteEdgeWeights = true;
13544             break;
13545         }
13546
13547         if (numEdges == goodEdgeCountCurrent)
13548         {
13549             noway_assert(hasIncompleteEdgeWeights == false);
13550             break;
13551         }
13552
13553     } while (hasIncompleteEdgeWeights && (goodEdgeCountCurrent > goodEdgeCountPrevious) && (iterations < 8));
13554
13555 EARLY_EXIT:;
13556
13557 #ifdef DEBUG
13558     if (verbose)
13559     {
13560         if (inconsistentProfileData)
13561         {
13562             printf("fgComputeEdgeWeights() found inconsistent profile data, not using the edge weights\n");
13563         }
13564         else
13565         {
13566             if (hasIncompleteEdgeWeights)
13567             {
13568                 printf("fgComputeEdgeWeights() was able to compute exact edge weights for %3d of the %3d edges, using "
13569                        "%d passes.\n",
13570                        goodEdgeCountCurrent, numEdges, iterations);
13571             }
13572             else
13573             {
13574                 printf("fgComputeEdgeWeights() was able to compute exact edge weights for all of the %3d edges, using "
13575                        "%d passes.\n",
13576                        numEdges, iterations);
13577             }
13578
13579             fgPrintEdgeWeights();
13580         }
13581     }
13582 #endif // DEBUG
13583
13584     fgSlopUsedInEdgeWeights  = usedSlop;
13585     fgRangeUsedInEdgeWeights = false;
13586
13587     // See if any edge weight are expressed in [min..max] form
13588
13589     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13590     {
13591         if (bDst->bbPreds != nullptr)
13592         {
13593             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13594             {
13595                 bSrc = edge->flBlock;
13596                 // This is the control flow edge (bSrc -> bDst)
13597
13598                 if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
13599                 {
13600                     fgRangeUsedInEdgeWeights = true;
13601                     break;
13602                 }
13603             }
13604             if (fgRangeUsedInEdgeWeights)
13605             {
13606                 break;
13607             }
13608         }
13609     }
13610
13611     fgHaveValidEdgeWeights = !inconsistentProfileData;
13612     fgEdgeWeightsComputed  = true;
13613 }
13614
13615 // fgOptimizeBranchToEmptyUnconditional:
13616 //    optimize a jump to an empty block which ends in an unconditional branch.
13617 //  Args:
13618 //      block: source block
13619 //      bDest: destination
13620 //  Returns: true if we changed the code
13621 //
13622 bool Compiler::fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBlock* bDest)
13623 {
13624     bool optimizeJump = true;
13625
13626     assert(bDest->isEmpty());
13627     assert(bDest->bbJumpKind == BBJ_ALWAYS);
13628
13629     // We do not optimize jumps between two different try regions.
13630     // However jumping to a block that is not in any try region is OK
13631     //
13632     if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
13633     {
13634         optimizeJump = false;
13635     }
13636
13637     // Don't optimize a jump to a removed block
13638     if (bDest->bbJumpDest->bbFlags & BBF_REMOVED)
13639     {
13640         optimizeJump = false;
13641     }
13642
13643     // Don't optimize a jump to a cloned finally
13644     if (bDest->bbFlags & BBF_CLONED_FINALLY_BEGIN)
13645     {
13646         optimizeJump = false;
13647     }
13648
13649 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13650     // Don't optimize a jump to a finally target. For BB1->BB2->BB3, where
13651     // BB2 is a finally target, if we changed BB1 to jump directly to BB3,
13652     // it would skip the finally target. BB1 might be a BBJ_ALWAYS block part
13653     // of a BBJ_CALLFINALLY/BBJ_ALWAYS pair, so changing the finally target
13654     // would change the unwind behavior.
13655     if (bDest->bbFlags & BBF_FINALLY_TARGET)
13656     {
13657         optimizeJump = false;
13658     }
13659 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13660
13661     // Must optimize jump if bDest has been removed
13662     //
13663     if (bDest->bbFlags & BBF_REMOVED)
13664     {
13665         optimizeJump = true;
13666     }
13667
13668     // If we are optimizing using real profile weights
13669     // then don't optimize a conditional jump to an unconditional jump
13670     // until after we have computed the edge weights
13671     //
13672     if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed)
13673     {
13674         fgNeedsUpdateFlowGraph = true;
13675         optimizeJump           = false;
13676     }
13677
13678     if (optimizeJump)
13679     {
13680 #ifdef DEBUG
13681         if (verbose)
13682         {
13683             printf("\nOptimizing a jump to an unconditional jump (BB%02u -> BB%02u -> BB%02u)\n", block->bbNum,
13684                    bDest->bbNum, bDest->bbJumpDest->bbNum);
13685         }
13686 #endif // DEBUG
13687
13688         //
13689         // When we optimize a branch to branch we need to update the profile weight
13690         // of bDest by subtracting out the block/edge weight of the path that is being optimized.
13691         //
13692         if (fgHaveValidEdgeWeights && bDest->hasProfileWeight())
13693         {
13694             flowList* edge1 = fgGetPredForBlock(bDest, block);
13695             noway_assert(edge1 != nullptr);
13696
13697             BasicBlock::weight_t edgeWeight;
13698
13699             if (edge1->flEdgeWeightMin != edge1->flEdgeWeightMax)
13700             {
13701                 //
13702                 // We only have an estimate for the edge weight
13703                 //
13704                 edgeWeight = (edge1->flEdgeWeightMin + edge1->flEdgeWeightMax) / 2;
13705                 //
13706                 //  Clear the profile weight flag
13707                 //
13708                 bDest->bbFlags &= ~BBF_PROF_WEIGHT;
13709             }
13710             else
13711             {
13712                 //
13713                 // We only have the exact edge weight
13714                 //
13715                 edgeWeight = edge1->flEdgeWeightMin;
13716             }
13717
13718             //
13719             // Update the bDest->bbWeight
13720             //
13721             if (bDest->bbWeight > edgeWeight)
13722             {
13723                 bDest->bbWeight -= edgeWeight;
13724             }
13725             else
13726             {
13727                 bDest->bbWeight = BB_ZERO_WEIGHT;
13728                 bDest->bbFlags |= BBF_RUN_RARELY; // Set the RarelyRun flag
13729             }
13730
13731             flowList* edge2 = fgGetPredForBlock(bDest->bbJumpDest, bDest);
13732
13733             if (edge2 != nullptr)
13734             {
13735                 //
13736                 // Update the edge2 min/max weights
13737                 //
13738                 if (edge2->flEdgeWeightMin > edge1->flEdgeWeightMin)
13739                 {
13740                     edge2->flEdgeWeightMin -= edge1->flEdgeWeightMin;
13741                 }
13742                 else
13743                 {
13744                     edge2->flEdgeWeightMin = BB_ZERO_WEIGHT;
13745                 }
13746
13747                 if (edge2->flEdgeWeightMax > edge1->flEdgeWeightMin)
13748                 {
13749                     edge2->flEdgeWeightMax -= edge1->flEdgeWeightMin;
13750                 }
13751                 else
13752                 {
13753                     edge2->flEdgeWeightMax = BB_ZERO_WEIGHT;
13754                 }
13755             }
13756         }
13757
13758         // Optimize the JUMP to empty unconditional JUMP to go to the new target
13759         block->bbJumpDest = bDest->bbJumpDest;
13760
13761         fgAddRefPred(bDest->bbJumpDest, block, fgRemoveRefPred(bDest, block));
13762
13763         return true;
13764     }
13765     return false;
13766 }
13767
13768 // fgOptimizeEmptyBlock:
13769 //   Does flow optimization of an empty block (can remove it in some cases)
13770 //
13771 //  Args:
13772 //      block: an empty block
13773 //  Returns: true if we changed the code
13774
13775 bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block)
13776 {
13777     assert(block->isEmpty());
13778
13779     BasicBlock* bPrev = block->bbPrev;
13780
13781     switch (block->bbJumpKind)
13782     {
13783         case BBJ_COND:
13784         case BBJ_SWITCH:
13785         case BBJ_THROW:
13786
13787             /* can never happen */
13788             noway_assert(!"Conditional, switch, or throw block with empty body!");
13789             break;
13790
13791         case BBJ_CALLFINALLY:
13792         case BBJ_RETURN:
13793         case BBJ_EHCATCHRET:
13794         case BBJ_EHFINALLYRET:
13795         case BBJ_EHFILTERRET:
13796
13797             /* leave them as is */
13798             /* some compilers generate multiple returns and put all of them at the end -
13799              * to solve that we need the predecessor list */
13800
13801             break;
13802
13803         case BBJ_ALWAYS:
13804
13805             // A GOTO cannot be to the next block since that
13806             // should have been fixed by the  optimization above
13807             // An exception is made for a jump from Hot to Cold
13808             noway_assert(block->bbJumpDest != block->bbNext || ((bPrev != nullptr) && bPrev->isBBCallAlwaysPair()) ||
13809                          fgInDifferentRegions(block, block->bbNext));
13810
13811             /* Cannot remove the first BB */
13812             if (!bPrev)
13813             {
13814                 break;
13815             }
13816
13817             /* Do not remove a block that jumps to itself - used for while (true){} */
13818             if (block->bbJumpDest == block)
13819             {
13820                 break;
13821             }
13822
13823             /* Empty GOTO can be removed iff bPrev is BBJ_NONE */
13824             if (bPrev->bbJumpKind != BBJ_NONE)
13825             {
13826                 break;
13827             }
13828
13829             // can't allow fall through into cold code
13830             if (block->bbNext == fgFirstColdBlock)
13831             {
13832                 break;
13833             }
13834
13835             /* Can fall through since this is similar with removing
13836              * a BBJ_NONE block, only the successor is different */
13837
13838             __fallthrough;
13839
13840         case BBJ_NONE:
13841
13842             /* special case if this is the first BB */
13843             if (!bPrev)
13844             {
13845                 assert(block == fgFirstBB);
13846             }
13847             else
13848             {
13849                 /* If this block follows a BBJ_CALLFINALLY do not remove it
13850                  * (because we don't know who may jump to it) */
13851                 if (bPrev->bbJumpKind == BBJ_CALLFINALLY)
13852                 {
13853                     break;
13854                 }
13855             }
13856
13857 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13858             /* Don't remove finally targets */
13859             if (block->bbFlags & BBF_FINALLY_TARGET)
13860                 break;
13861 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13862
13863 #if FEATURE_EH_FUNCLETS
13864             /* Don't remove an empty block that is in a different EH region
13865              * from its successor block, if the block is the target of a
13866              * catch return. It is required that the return address of a
13867              * catch be in the correct EH region, for re-raise of thread
13868              * abort exceptions to work. Insert a NOP in the empty block
13869              * to ensure we generate code for the block, if we keep it.
13870              */
13871             {
13872                 BasicBlock* succBlock;
13873
13874                 if (block->bbJumpKind == BBJ_ALWAYS)
13875                 {
13876                     succBlock = block->bbJumpDest;
13877                 }
13878                 else
13879                 {
13880                     succBlock = block->bbNext;
13881                 }
13882
13883                 if ((succBlock != nullptr) && !BasicBlock::sameEHRegion(block, succBlock))
13884                 {
13885                     // The empty block and the block that follows it are in different
13886                     // EH regions. Is this a case where they can't be merged?
13887
13888                     bool okToMerge = true; // assume it's ok
13889                     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
13890                     {
13891                         if (pred->flBlock->bbJumpKind == BBJ_EHCATCHRET)
13892                         {
13893                             assert(pred->flBlock->bbJumpDest == block);
13894                             okToMerge = false; // we can't get rid of the empty block
13895                             break;
13896                         }
13897                     }
13898
13899                     if (!okToMerge)
13900                     {
13901                         // Insert a NOP in the empty block to ensure we generate code
13902                         // for the catchret target in the right EH region.
13903                         GenTree* nop = new (this, GT_NO_OP) GenTree(GT_NO_OP, TYP_VOID);
13904
13905                         if (block->IsLIR())
13906                         {
13907                             LIR::AsRange(block).InsertAtEnd(nop);
13908 #ifndef LEGACY_BACKEND
13909                             LIR::ReadOnlyRange range(nop, nop);
13910                             m_pLowering->LowerRange(block, range);
13911 #endif
13912                         }
13913                         else
13914                         {
13915                             GenTree* nopStmt = fgInsertStmtAtEnd(block, nop);
13916                             fgSetStmtSeq(nopStmt);
13917                             gtSetStmtInfo(nopStmt);
13918                         }
13919
13920 #ifdef DEBUG
13921                         if (verbose)
13922                         {
13923                             printf("\nKeeping empty block BB%02u - it is the target of a catch return\n", block->bbNum);
13924                         }
13925 #endif // DEBUG
13926
13927                         break; // go to the next block
13928                     }
13929                 }
13930             }
13931 #endif // FEATURE_EH_FUNCLETS
13932
13933             if (!ehCanDeleteEmptyBlock(block))
13934             {
13935                 // We're not allowed to remove this block due to reasons related to the EH table.
13936                 break;
13937             }
13938
13939             /* special case if this is the last BB */
13940             if (block == fgLastBB)
13941             {
13942                 if (!bPrev)
13943                 {
13944                     break;
13945                 }
13946                 fgLastBB = bPrev;
13947             }
13948
13949             // When using profile weights, fgComputeEdgeWeights expects the first non-internal block to have profile
13950             // weight.
13951             // Make sure we don't break that invariant.
13952             if (fgIsUsingProfileWeights() && block->hasProfileWeight() && (block->bbFlags & BBF_INTERNAL) == 0)
13953             {
13954                 BasicBlock* bNext = block->bbNext;
13955
13956                 // Check if the next block can't maintain the invariant.
13957                 if ((bNext == nullptr) || ((bNext->bbFlags & BBF_INTERNAL) != 0) || !bNext->hasProfileWeight())
13958                 {
13959                     // Check if the current block is the first non-internal block.
13960                     BasicBlock* curBB = bPrev;
13961                     while ((curBB != nullptr) && (curBB->bbFlags & BBF_INTERNAL) != 0)
13962                     {
13963                         curBB = curBB->bbPrev;
13964                     }
13965                     if (curBB == nullptr)
13966                     {
13967                         // This block is the first non-internal block and it has profile weight.
13968                         // Don't delete it.
13969                         break;
13970                     }
13971                 }
13972             }
13973
13974             /* Remove the block */
13975             compCurBB = block;
13976             fgRemoveBlock(block, false);
13977             return true;
13978
13979         default:
13980             noway_assert(!"Unexpected bbJumpKind");
13981             break;
13982     }
13983     return false;
13984 }
13985
13986 // fgOptimizeSwitchBranches:
13987 //   Does flow optimization for a switch - bypasses jumps to empty unconditional branches,
13988 //      and transforms degenerate switch cases like those with 1 or 2 targets
13989 //
13990 //  Args:
13991 //      block: BasicBlock that contains the switch
13992 //  Returns: true if we changed the code
13993 //
13994 bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block)
13995 {
13996     assert(block->bbJumpKind == BBJ_SWITCH);
13997
13998     unsigned     jmpCnt = block->bbJumpSwt->bbsCount;
13999     BasicBlock** jmpTab = block->bbJumpSwt->bbsDstTab;
14000     BasicBlock*  bNewDest; // the new jump target for the current switch case
14001     BasicBlock*  bDest;
14002     bool         returnvalue = false;
14003
14004     do
14005     {
14006     REPEAT_SWITCH:;
14007         bDest    = *jmpTab;
14008         bNewDest = bDest;
14009
14010         // Do we have a JUMP to an empty unconditional JUMP block?
14011         if (bDest->isEmpty() && (bDest->bbJumpKind == BBJ_ALWAYS) &&
14012             (bDest != bDest->bbJumpDest)) // special case for self jumps
14013         {
14014             bool optimizeJump = true;
14015
14016             // We do not optimize jumps between two different try regions.
14017             // However jumping to a block that is not in any try region is OK
14018             //
14019             if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
14020             {
14021                 optimizeJump = false;
14022             }
14023
14024             // If we are optimize using real profile weights
14025             // then don't optimize a switch jump to an unconditional jump
14026             // until after we have computed the edge weights
14027             //
14028             if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed)
14029             {
14030                 fgNeedsUpdateFlowGraph = true;
14031                 optimizeJump           = false;
14032             }
14033
14034             if (optimizeJump)
14035             {
14036                 bNewDest = bDest->bbJumpDest;
14037 #ifdef DEBUG
14038                 if (verbose)
14039                 {
14040                     printf("\nOptimizing a switch jump to an empty block with an unconditional jump (BB%02u -> BB%02u "
14041                            "-> BB%02u)\n",
14042                            block->bbNum, bDest->bbNum, bNewDest->bbNum);
14043                 }
14044 #endif // DEBUG
14045             }
14046         }
14047
14048         if (bNewDest != bDest)
14049         {
14050             //
14051             // When we optimize a branch to branch we need to update the profile weight
14052             // of bDest by subtracting out the block/edge weight of the path that is being optimized.
14053             //
14054             if (fgIsUsingProfileWeights() && bDest->hasProfileWeight())
14055             {
14056                 if (fgHaveValidEdgeWeights)
14057                 {
14058                     flowList*            edge                = fgGetPredForBlock(bDest, block);
14059                     BasicBlock::weight_t branchThroughWeight = edge->flEdgeWeightMin;
14060
14061                     if (bDest->bbWeight > branchThroughWeight)
14062                     {
14063                         bDest->bbWeight -= branchThroughWeight;
14064                     }
14065                     else
14066                     {
14067                         bDest->bbWeight = BB_ZERO_WEIGHT;
14068                         bDest->bbFlags |= BBF_RUN_RARELY;
14069                     }
14070                 }
14071             }
14072
14073             // Update the switch jump table
14074             *jmpTab = bNewDest;
14075
14076             // Maintain, if necessary, the set of unique targets of "block."
14077             UpdateSwitchTableTarget(block, bDest, bNewDest);
14078
14079             fgAddRefPred(bNewDest, block, fgRemoveRefPred(bDest, block));
14080
14081             // we optimized a Switch label - goto REPEAT_SWITCH to follow this new jump
14082             returnvalue = true;
14083
14084             goto REPEAT_SWITCH;
14085         }
14086     } while (++jmpTab, --jmpCnt);
14087
14088     GenTreeStmt* switchStmt = nullptr;
14089     LIR::Range*  blockRange = nullptr;
14090
14091     GenTree* switchTree;
14092     if (block->IsLIR())
14093     {
14094         blockRange = &LIR::AsRange(block);
14095         switchTree = blockRange->LastNode();
14096
14097         assert(switchTree->OperGet() == GT_SWITCH_TABLE);
14098     }
14099     else
14100     {
14101         switchStmt = block->lastStmt();
14102         switchTree = switchStmt->gtStmtExpr;
14103
14104         assert(switchTree->OperGet() == GT_SWITCH);
14105     }
14106
14107     noway_assert(switchTree->gtType == TYP_VOID);
14108
14109     // At this point all of the case jump targets have been updated such
14110     // that none of them go to block that is an empty unconditional block
14111     //
14112     jmpTab = block->bbJumpSwt->bbsDstTab;
14113     jmpCnt = block->bbJumpSwt->bbsCount;
14114     // Now check for two trivial switch jumps.
14115     //
14116     if (block->NumSucc(this) == 1)
14117     {
14118         // Use BBJ_ALWAYS for a switch with only a default clause, or with only one unique successor.
14119         BasicBlock* uniqueSucc = jmpTab[0];
14120
14121 #ifdef DEBUG
14122         if (verbose)
14123         {
14124             printf("\nRemoving a switch jump with a single target (BB%02u)\n", block->bbNum);
14125             printf("BEFORE:\n");
14126         }
14127 #endif // DEBUG
14128
14129         if (block->IsLIR())
14130         {
14131             bool               isClosed;
14132             unsigned           sideEffects;
14133             LIR::ReadOnlyRange switchTreeRange = blockRange->GetTreeRange(switchTree, &isClosed, &sideEffects);
14134
14135             // The switch tree should form a contiguous, side-effect free range by construction. See
14136             // Lowering::LowerSwitch for details.
14137             assert(isClosed);
14138             assert((sideEffects & GTF_ALL_EFFECT) == 0);
14139
14140             blockRange->Delete(this, block, std::move(switchTreeRange));
14141         }
14142         else
14143         {
14144             /* check for SIDE_EFFECTS */
14145             if (switchTree->gtFlags & GTF_SIDE_EFFECT)
14146             {
14147                 /* Extract the side effects from the conditional */
14148                 GenTree* sideEffList = nullptr;
14149
14150                 gtExtractSideEffList(switchTree, &sideEffList);
14151
14152                 if (sideEffList == nullptr)
14153                 {
14154                     goto NO_SWITCH_SIDE_EFFECT;
14155                 }
14156
14157                 noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
14158
14159 #ifdef DEBUG
14160                 if (verbose)
14161                 {
14162                     printf("\nSwitch expression has side effects! Extracting side effects...\n");
14163                     gtDispTree(switchTree);
14164                     printf("\n");
14165                     gtDispTree(sideEffList);
14166                     printf("\n");
14167                 }
14168 #endif // DEBUG
14169
14170                 /* Replace the conditional statement with the list of side effects */
14171                 noway_assert(sideEffList->gtOper != GT_STMT);
14172                 noway_assert(sideEffList->gtOper != GT_SWITCH);
14173
14174                 switchStmt->gtStmtExpr = sideEffList;
14175
14176                 if (fgStmtListThreaded)
14177                 {
14178                     /* Update the lclvar ref counts */
14179                     compCurBB = block;
14180                     fgUpdateRefCntForExtract(switchTree, sideEffList);
14181
14182                     /* Update ordering, costs, FP levels, etc. */
14183                     gtSetStmtInfo(switchStmt);
14184
14185                     /* Re-link the nodes for this statement */
14186                     fgSetStmtSeq(switchStmt);
14187                 }
14188             }
14189             else
14190             {
14191
14192             NO_SWITCH_SIDE_EFFECT:
14193
14194                 /* conditional has NO side effect - remove it */
14195                 fgRemoveStmt(block, switchStmt);
14196             }
14197         }
14198
14199         // Change the switch jump into a BBJ_ALWAYS
14200         block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0];
14201         block->bbJumpKind = BBJ_ALWAYS;
14202         if (jmpCnt > 1)
14203         {
14204             for (unsigned i = 1; i < jmpCnt; ++i)
14205             {
14206                 (void)fgRemoveRefPred(jmpTab[i], block);
14207             }
14208         }
14209
14210         return true;
14211     }
14212     else if (block->bbJumpSwt->bbsCount == 2 && block->bbJumpSwt->bbsDstTab[1] == block->bbNext)
14213     {
14214         /* Use a BBJ_COND(switchVal==0) for a switch with only one
14215            significant clause besides the default clause, if the
14216            default clause is bbNext */
14217         GenTree* switchVal = switchTree->gtOp.gtOp1;
14218         noway_assert(genActualTypeIsIntOrI(switchVal->TypeGet()));
14219
14220 #ifndef LEGACY_BACKEND
14221         // If we are in LIR, remove the jump table from the block.
14222         if (block->IsLIR())
14223         {
14224             GenTree* jumpTable = switchTree->gtOp.gtOp2;
14225             assert(jumpTable->OperGet() == GT_JMPTABLE);
14226             blockRange->Remove(jumpTable);
14227         }
14228 #endif
14229
14230         // Change the GT_SWITCH(switchVal) into GT_JTRUE(GT_EQ(switchVal==0)).
14231         // Also mark the node as GTF_DONT_CSE as further down JIT is not capable of handling it.
14232         // For example CSE could determine that the expression rooted at GT_EQ is a candidate cse and
14233         // replace it with a COMMA node.  In such a case we will end up with GT_JTRUE node pointing to
14234         // a COMMA node which results in noway asserts in fgMorphSmpOp(), optAssertionGen() and rpPredictTreeRegUse().
14235         // For the same reason fgMorphSmpOp() marks GT_JTRUE nodes with RELOP children as GTF_DONT_CSE.
14236         CLANG_FORMAT_COMMENT_ANCHOR;
14237
14238 #ifdef DEBUG
14239         if (verbose)
14240         {
14241             printf("\nConverting a switch (BB%02u) with only one significant clause besides a default target to a "
14242                    "conditional branch\n",
14243                    block->bbNum);
14244         }
14245 #endif // DEBUG
14246
14247         switchTree->ChangeOper(GT_JTRUE);
14248         GenTree* zeroConstNode = gtNewZeroConNode(genActualType(switchVal->TypeGet()));
14249         GenTree* condNode      = gtNewOperNode(GT_EQ, TYP_INT, switchVal, zeroConstNode);
14250         switchTree->gtOp.gtOp1 = condNode;
14251         switchTree->gtOp.gtOp1->gtFlags |= (GTF_RELOP_JMP_USED | GTF_DONT_CSE);
14252
14253         if (block->IsLIR())
14254         {
14255             blockRange->InsertAfter(switchVal, zeroConstNode, condNode);
14256 #ifndef LEGACY_BACKEND
14257             LIR::ReadOnlyRange range(zeroConstNode, switchTree);
14258             m_pLowering->LowerRange(block, range);
14259 #endif // !LEGACY_BACKEND
14260         }
14261         else
14262         {
14263             // Re-link the nodes for this statement.
14264             fgSetStmtSeq(switchStmt);
14265         }
14266
14267         block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0];
14268         block->bbJumpKind = BBJ_COND;
14269
14270         return true;
14271     }
14272     return returnvalue;
14273 }
14274
14275 // fgBlockEndFavorsTailDuplication:
14276 //     Heuristic function that returns true if this block ends in a statement that looks favorable
14277 //     for tail-duplicating its successor (such as assigning a constant to a local).
14278 //  Args:
14279 //      block: BasicBlock we are considering duplicating the successor of
14280 //  Returns:
14281 //      true if it seems like a good idea
14282 //
14283 bool Compiler::fgBlockEndFavorsTailDuplication(BasicBlock* block)
14284 {
14285     if (block->isRunRarely())
14286     {
14287         return false;
14288     }
14289
14290     if (!block->lastStmt())
14291     {
14292         return false;
14293     }
14294     else
14295     {
14296         // Tail duplication tends to pay off when the last statement
14297         // is an assignment of a constant, arraylength, or a relop.
14298         // This is because these statements produce information about values
14299         // that would otherwise be lost at the upcoming merge point.
14300
14301         GenTreeStmt* lastStmt = block->lastStmt();
14302         GenTree*     tree     = lastStmt->gtStmtExpr;
14303         if (tree->gtOper != GT_ASG)
14304         {
14305             return false;
14306         }
14307
14308         if (tree->OperIsBlkOp())
14309         {
14310             return false;
14311         }
14312
14313         GenTree* op2 = tree->gtOp.gtOp2;
14314         if (op2->gtOper != GT_ARR_LENGTH && !op2->OperIsConst() && ((op2->OperKind() & GTK_RELOP) == 0))
14315         {
14316             return false;
14317         }
14318     }
14319     return true;
14320 }
14321
14322 // fgBlockIsGoodTailDuplicationCandidate:
14323 //     Heuristic function that examines a block (presumably one that is a merge point) to determine
14324 //     if it should be duplicated.
14325 // args:
14326 //     target - the tail block (candidate for duplication)
14327 // returns:
14328 //     true if this block seems like a good candidate for duplication
14329 //
14330 bool Compiler::fgBlockIsGoodTailDuplicationCandidate(BasicBlock* target)
14331 {
14332     GenTreeStmt* stmt = target->FirstNonPhiDef();
14333
14334     // Here we are looking for blocks with a single statement feeding a conditional branch.
14335     // These blocks are small, and when duplicated onto the tail of blocks that end in
14336     // assignments, there is a high probability of the branch completely going away.
14337
14338     // This is by no means the only kind of tail that it is beneficial to duplicate,
14339     // just the only one we recognize for now.
14340
14341     if (stmt != target->lastStmt())
14342     {
14343         return false;
14344     }
14345
14346     if (target->bbJumpKind != BBJ_COND)
14347     {
14348         return false;
14349     }
14350
14351     GenTree* tree = stmt->gtStmtExpr;
14352
14353     if (tree->gtOper != GT_JTRUE)
14354     {
14355         return false;
14356     }
14357
14358     // must be some kind of relational operator
14359     GenTree* cond = tree->gtOp.gtOp1;
14360     if (!(cond->OperKind() & GTK_RELOP))
14361     {
14362         return false;
14363     }
14364
14365     // op1 must be some combinations of casts of local or constant
14366     GenTree* op1 = cond->gtOp.gtOp1;
14367     while (op1->gtOper == GT_CAST)
14368     {
14369         op1 = op1->gtOp.gtOp1;
14370     }
14371     if (!op1->IsLocal() && !op1->OperIsConst())
14372     {
14373         return false;
14374     }
14375
14376     // op2 must be some combinations of casts of local or constant
14377     GenTree* op2 = cond->gtOp.gtOp2;
14378     while (op2->gtOper == GT_CAST)
14379     {
14380         op2 = op2->gtOp.gtOp1;
14381     }
14382     if (!op2->IsLocal() && !op2->OperIsConst())
14383     {
14384         return false;
14385     }
14386
14387     return true;
14388 }
14389
14390 // fgOptimizeUncondBranchToSimpleCond:
14391 //    For a block which has an unconditional branch, look to see if its target block
14392 //    is a good candidate for tail duplication, and if so do that duplication.
14393 //
14394 // Args:
14395 //    block  - block with uncond branch
14396 //    target - block which is target of first block
14397 //
14398 // returns: true if changes were made
14399
14400 bool Compiler::fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* target)
14401 {
14402     assert(block->bbJumpKind == BBJ_ALWAYS);
14403     assert(block->bbJumpDest == target);
14404
14405     // TODO-Review: OK if they are in the same region?
14406     if (compHndBBtabCount > 0)
14407     {
14408         return false;
14409     }
14410
14411     if (!fgBlockIsGoodTailDuplicationCandidate(target))
14412     {
14413         return false;
14414     }
14415
14416     if (!fgBlockEndFavorsTailDuplication(block))
14417     {
14418         return false;
14419     }
14420
14421     // NOTE: we do not currently hit this assert because this function is only called when
14422     // `fgUpdateFlowGraph` has been called with `doTailDuplication` set to true, and the
14423     // backend always calls `fgUpdateFlowGraph` with `doTailDuplication` set to false.
14424     assert(!block->IsLIR());
14425
14426     GenTreeStmt* stmt = target->FirstNonPhiDef();
14427     assert(stmt == target->lastStmt());
14428
14429     // Duplicate the target block at the end of this block
14430
14431     GenTree* cloned = gtCloneExpr(stmt->gtStmtExpr);
14432     noway_assert(cloned);
14433     GenTree* jmpStmt = gtNewStmt(cloned);
14434
14435     block->bbJumpKind = BBJ_COND;
14436     block->bbJumpDest = target->bbJumpDest;
14437     fgAddRefPred(block->bbJumpDest, block);
14438     fgRemoveRefPred(target, block);
14439
14440     // add an unconditional block after this block to jump to the target block's fallthrough block
14441
14442     BasicBlock* next = fgNewBBafter(BBJ_ALWAYS, block, true);
14443
14444     // The new block 'next' will inherit its weight from 'block'
14445     next->inheritWeight(block);
14446     next->bbJumpDest = target->bbNext;
14447     target->bbNext->bbFlags |= BBF_JMP_TARGET;
14448     fgAddRefPred(next, block);
14449     fgAddRefPred(next->bbJumpDest, next);
14450
14451 #ifdef DEBUG
14452     if (verbose)
14453     {
14454         printf("fgOptimizeUncondBranchToSimpleCond(from BB%02u to cond BB%02u), created new uncond BB%02u\n",
14455                block->bbNum, target->bbNum, next->bbNum);
14456     }
14457 #endif // DEBUG
14458
14459     if (fgStmtListThreaded)
14460     {
14461         gtSetStmtInfo(jmpStmt);
14462     }
14463
14464     fgInsertStmtAtEnd(block, jmpStmt);
14465
14466     return true;
14467 }
14468
14469 // fgOptimizeBranchToNext:
14470 //    Optimize a block which has a branch to the following block
14471 // Args:
14472 //    block - block with a branch
14473 //    bNext - block which is both next and the target of the first block
14474 //    bPrev - block which is prior to the first block
14475 //
14476 // returns: true if changes were made
14477 //
14478 bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev)
14479 {
14480     assert(block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS);
14481     assert(block->bbJumpDest == bNext);
14482     assert(block->bbNext == bNext);
14483     assert(block->bbPrev == bPrev);
14484
14485     if (block->bbJumpKind == BBJ_ALWAYS)
14486     {
14487         // We can't remove it if it is a branch from hot => cold
14488         if (!fgInDifferentRegions(block, bNext))
14489         {
14490             // We can't remove if it is marked as BBF_KEEP_BBJ_ALWAYS
14491             if (!(block->bbFlags & BBF_KEEP_BBJ_ALWAYS))
14492             {
14493                 // We can't remove if the BBJ_ALWAYS is part of a BBJ_CALLFINALLY pair
14494                 if ((bPrev == nullptr) || !bPrev->isBBCallAlwaysPair())
14495                 {
14496                     /* the unconditional jump is to the next BB  */
14497                     block->bbJumpKind = BBJ_NONE;
14498                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
14499 #ifdef DEBUG
14500                     if (verbose)
14501                     {
14502                         printf("\nRemoving unconditional jump to next block (BB%02u -> BB%02u) (converted BB%02u to "
14503                                "fall-through)\n",
14504                                block->bbNum, bNext->bbNum, block->bbNum);
14505                     }
14506 #endif // DEBUG
14507                     return true;
14508                 }
14509             }
14510         }
14511     }
14512     else
14513     {
14514         /* remove the conditional statement at the end of block */
14515         noway_assert(block->bbJumpKind == BBJ_COND);
14516         noway_assert(block->bbTreeList);
14517
14518 #ifdef DEBUG
14519         if (verbose)
14520         {
14521             printf("\nRemoving conditional jump to next block (BB%02u -> BB%02u)\n", block->bbNum, bNext->bbNum);
14522         }
14523 #endif // DEBUG
14524
14525         if (block->IsLIR())
14526         {
14527             LIR::Range& blockRange = LIR::AsRange(block);
14528             GenTree*    jmp        = blockRange.LastNode();
14529             assert(jmp->OperIsConditionalJump());
14530             if (jmp->OperGet() == GT_JTRUE)
14531             {
14532                 jmp->gtOp.gtOp1->gtFlags &= ~GTF_SET_FLAGS;
14533             }
14534
14535             bool               isClosed;
14536             unsigned           sideEffects;
14537             LIR::ReadOnlyRange jmpRange = blockRange.GetTreeRange(jmp, &isClosed, &sideEffects);
14538
14539             // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable
14540             //            diffs compared to the existing backend.
14541             if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0))
14542             {
14543                 // If the jump and its operands form a contiguous, side-effect-free range,
14544                 // remove them.
14545                 blockRange.Delete(this, block, std::move(jmpRange));
14546             }
14547             else
14548             {
14549                 // Otherwise, just remove the jump node itself.
14550                 blockRange.Remove(jmp, true);
14551             }
14552         }
14553         else
14554         {
14555             GenTreeStmt* cond = block->lastStmt();
14556             noway_assert(cond->gtStmtExpr->gtOper == GT_JTRUE);
14557
14558             /* check for SIDE_EFFECTS */
14559             if (cond->gtStmtExpr->gtFlags & GTF_SIDE_EFFECT)
14560             {
14561                 /* Extract the side effects from the conditional */
14562                 GenTree* sideEffList = nullptr;
14563
14564                 gtExtractSideEffList(cond->gtStmtExpr, &sideEffList);
14565
14566                 if (sideEffList == nullptr)
14567                 {
14568                     compCurBB = block;
14569                     fgRemoveStmt(block, cond);
14570                 }
14571                 else
14572                 {
14573                     noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
14574 #ifdef DEBUG
14575                     if (verbose)
14576                     {
14577                         printf("\nConditional has side effects! Extracting side effects...\n");
14578                         gtDispTree(cond);
14579                         printf("\n");
14580                         gtDispTree(sideEffList);
14581                         printf("\n");
14582                     }
14583 #endif // DEBUG
14584
14585                     /* Replace the conditional statement with the list of side effects */
14586                     noway_assert(sideEffList->gtOper != GT_STMT);
14587                     noway_assert(sideEffList->gtOper != GT_JTRUE);
14588
14589                     cond->gtStmtExpr = sideEffList;
14590
14591                     if (fgStmtListThreaded)
14592                     {
14593                         /* Update the lclvar ref counts */
14594                         compCurBB = block;
14595                         fgUpdateRefCntForExtract(cond->gtStmtExpr, sideEffList);
14596
14597                         /* Update ordering, costs, FP levels, etc. */
14598                         gtSetStmtInfo(cond);
14599
14600                         /* Re-link the nodes for this statement */
14601                         fgSetStmtSeq(cond);
14602                     }
14603                 }
14604             }
14605             else
14606             {
14607                 compCurBB = block;
14608                 /* conditional has NO side effect - remove it */
14609                 fgRemoveStmt(block, cond);
14610             }
14611         }
14612
14613         /* Conditional is gone - simply fall into the next block */
14614
14615         block->bbJumpKind = BBJ_NONE;
14616         block->bbFlags &= ~BBF_NEEDS_GCPOLL;
14617
14618         /* Update bbRefs and bbNum - Conditional predecessors to the same
14619          * block are counted twice so we have to remove one of them */
14620
14621         noway_assert(bNext->countOfInEdges() > 1);
14622         fgRemoveRefPred(bNext, block);
14623
14624         return true;
14625     }
14626     return false;
14627 }
14628
14629 /*****************************************************************************
14630  *
14631  *  Function called to optimize an unconditional branch that branches
14632  *  to a conditional branch.
14633  *  Currently we require that the conditional branch jump back to the
14634  *  block that follows the unconditional branch.
14635  *
14636  *  We can improve the code execution and layout by concatenating a copy
14637  *  of the conditional branch block at the end of the conditional branch
14638  *  and reversing the sense of the branch.
14639  *
14640  *  This is only done when the amount of code to be copied is smaller than
14641  *  our calculated threshold in maxDupCostSz.
14642  *
14643  */
14644
14645 bool Compiler::fgOptimizeBranch(BasicBlock* bJump)
14646 {
14647     if (opts.MinOpts())
14648     {
14649         return false;
14650     }
14651
14652     if (bJump->bbJumpKind != BBJ_ALWAYS)
14653     {
14654         return false;
14655     }
14656
14657     if (bJump->bbFlags & BBF_KEEP_BBJ_ALWAYS)
14658     {
14659         return false;
14660     }
14661
14662     // Don't hoist a conditional branch into the scratch block; we'd prefer it stay
14663     // either BBJ_NONE or BBJ_ALWAYS.
14664     if (fgBBisScratch(bJump))
14665     {
14666         return false;
14667     }
14668
14669     BasicBlock* bDest = bJump->bbJumpDest;
14670
14671     if (bDest->bbJumpKind != BBJ_COND)
14672     {
14673         return false;
14674     }
14675
14676     if (bDest->bbJumpDest != bJump->bbNext)
14677     {
14678         return false;
14679     }
14680
14681     // 'bJump' must be in the same try region as the condition, since we're going to insert
14682     // a duplicated condition in 'bJump', and the condition might include exception throwing code.
14683     if (!BasicBlock::sameTryRegion(bJump, bDest))
14684     {
14685         return false;
14686     }
14687
14688     // do not jump into another try region
14689     BasicBlock* bDestNext = bDest->bbNext;
14690     if (bDestNext->hasTryIndex() && !BasicBlock::sameTryRegion(bJump, bDestNext))
14691     {
14692         return false;
14693     }
14694
14695     // This function is only called by fgReorderBlocks, which we do not run in the backend.
14696     // If we wanted to run block reordering in the backend, we would need to be able to
14697     // calculate cost information for LIR on a per-node basis in order for this function
14698     // to work.
14699     assert(!bJump->IsLIR());
14700     assert(!bDest->IsLIR());
14701
14702     GenTreeStmt* stmt;
14703     unsigned     estDupCostSz = 0;
14704     for (stmt = bDest->firstStmt(); stmt; stmt = stmt->gtNextStmt)
14705     {
14706         GenTree* expr = stmt->gtStmtExpr;
14707
14708         /* We call gtPrepareCost to measure the cost of duplicating this tree */
14709         gtPrepareCost(expr);
14710
14711         estDupCostSz += expr->gtCostSz;
14712     }
14713
14714     bool                 allProfileWeightsAreValid = false;
14715     BasicBlock::weight_t weightJump                = bJump->bbWeight;
14716     BasicBlock::weight_t weightDest                = bDest->bbWeight;
14717     BasicBlock::weight_t weightNext                = bJump->bbNext->bbWeight;
14718     bool                 rareJump                  = bJump->isRunRarely();
14719     bool                 rareDest                  = bDest->isRunRarely();
14720     bool                 rareNext                  = bJump->bbNext->isRunRarely();
14721
14722     // If we have profile data then we calculate the number of time
14723     // the loop will iterate into loopIterations
14724     if (fgIsUsingProfileWeights())
14725     {
14726         // Only rely upon the profile weight when all three of these blocks
14727         // have either good profile weights or are rarelyRun
14728         //
14729         if ((bJump->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)) &&
14730             (bDest->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)) &&
14731             (bJump->bbNext->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)))
14732         {
14733             allProfileWeightsAreValid = true;
14734
14735             if ((weightJump * 100) < weightDest)
14736             {
14737                 rareJump = true;
14738             }
14739
14740             if ((weightNext * 100) < weightDest)
14741             {
14742                 rareNext = true;
14743             }
14744
14745             if (((weightDest * 100) < weightJump) && ((weightDest * 100) < weightNext))
14746             {
14747                 rareDest = true;
14748             }
14749         }
14750     }
14751
14752     unsigned maxDupCostSz = 6;
14753
14754     //
14755     // Branches between the hot and rarely run regions
14756     // should be minimized.  So we allow a larger size
14757     //
14758     if (rareDest != rareJump)
14759     {
14760         maxDupCostSz += 6;
14761     }
14762
14763     if (rareDest != rareNext)
14764     {
14765         maxDupCostSz += 6;
14766     }
14767
14768     //
14769     // We we are ngen-ing:
14770     // If the uncondional branch is a rarely run block then
14771     // we are willing to have more code expansion since we
14772     // won't be running code from this page
14773     //
14774     if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
14775     {
14776         if (rareJump)
14777         {
14778             maxDupCostSz *= 2;
14779         }
14780     }
14781
14782     // If the compare has too high cost then we don't want to dup
14783
14784     bool costIsTooHigh = (estDupCostSz > maxDupCostSz);
14785
14786 #ifdef DEBUG
14787     if (verbose)
14788     {
14789         printf("\nDuplication of the conditional block BB%02u (always branch from BB%02u) %s, because the cost of "
14790                "duplication (%i) is %s than %i,"
14791                " validProfileWeights = %s\n",
14792                bDest->bbNum, bJump->bbNum, costIsTooHigh ? "not done" : "performed", estDupCostSz,
14793                costIsTooHigh ? "greater" : "less or equal", maxDupCostSz, allProfileWeightsAreValid ? "true" : "false");
14794     }
14795 #endif // DEBUG
14796
14797     if (costIsTooHigh)
14798     {
14799         return false;
14800     }
14801
14802     /* Looks good - duplicate the conditional block */
14803
14804     GenTree* newStmtList     = nullptr; // new stmt list to be added to bJump
14805     GenTree* newStmtLast     = nullptr;
14806     bool     cloneExprFailed = false;
14807
14808     /* Visit all the statements in bDest */
14809
14810     for (GenTree* curStmt = bDest->bbTreeList; curStmt; curStmt = curStmt->gtNext)
14811     {
14812         /* Clone/substitute the expression */
14813
14814         stmt = gtCloneExpr(curStmt)->AsStmt();
14815
14816         // cloneExpr doesn't handle everything
14817
14818         if (stmt == nullptr)
14819         {
14820             cloneExprFailed = true;
14821             break;
14822         }
14823
14824         /* Append the expression to our list */
14825
14826         if (newStmtList != nullptr)
14827         {
14828             newStmtLast->gtNext = stmt;
14829         }
14830         else
14831         {
14832             newStmtList = stmt;
14833         }
14834
14835         stmt->gtPrev = newStmtLast;
14836         newStmtLast  = stmt;
14837     }
14838
14839     if (cloneExprFailed)
14840     {
14841         return false;
14842     }
14843
14844     noway_assert(newStmtLast != nullptr);
14845     noway_assert(stmt != nullptr);
14846     noway_assert(stmt->gtOper == GT_STMT);
14847
14848     if ((newStmtLast == nullptr) || (stmt == nullptr) || (stmt->gtOper != GT_STMT))
14849     {
14850         return false;
14851     }
14852
14853     /* Get to the condition node from the statement tree */
14854
14855     GenTree* condTree = stmt->gtStmtExpr;
14856     noway_assert(condTree->gtOper == GT_JTRUE);
14857
14858     if (condTree->gtOper != GT_JTRUE)
14859     {
14860         return false;
14861     }
14862
14863     //
14864     // Set condTree to the operand to the GT_JTRUE
14865     //
14866     condTree = condTree->gtOp.gtOp1;
14867
14868     //
14869     // This condTree has to be a RelOp comparison
14870     //
14871     if (condTree->OperIsCompare() == false)
14872     {
14873         return false;
14874     }
14875
14876     // Bump up the ref-counts of any variables in 'stmt'
14877     fgUpdateRefCntForClone(bJump, stmt->gtStmtExpr);
14878
14879     //
14880     // Find the last statement in the bJump block
14881     //
14882     GenTreeStmt* lastStmt = nullptr;
14883     for (stmt = bJump->firstStmt(); stmt; stmt = stmt->gtNextStmt)
14884     {
14885         lastStmt = stmt;
14886     }
14887     stmt = bJump->firstStmt();
14888
14889     /* Join the two linked lists */
14890     newStmtLast->gtNext = nullptr;
14891
14892     if (lastStmt != nullptr)
14893     {
14894         stmt->gtPrev        = newStmtLast;
14895         lastStmt->gtNext    = newStmtList;
14896         newStmtList->gtPrev = lastStmt;
14897     }
14898     else
14899     {
14900         bJump->bbTreeList   = newStmtList;
14901         newStmtList->gtPrev = newStmtLast;
14902     }
14903
14904     //
14905     // Reverse the sense of the compare
14906     //
14907     gtReverseCond(condTree);
14908
14909     // We need to update the following flags of the bJump block if they were set in the bDest block
14910     bJump->bbFlags |=
14911         (bDest->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_VTABREF));
14912
14913     bJump->bbJumpKind = BBJ_COND;
14914     bJump->bbJumpDest = bDest->bbNext;
14915
14916     /* Mark the jump dest block as being a jump target */
14917     bJump->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
14918
14919     /* Update bbRefs and bbPreds */
14920
14921     // bJump now falls through into the next block
14922     //
14923     fgAddRefPred(bJump->bbNext, bJump);
14924
14925     // bJump no longer jumps to bDest
14926     //
14927     fgRemoveRefPred(bDest, bJump);
14928
14929     // bJump now jumps to bDest->bbNext
14930     //
14931     fgAddRefPred(bDest->bbNext, bJump);
14932
14933     if (weightJump > 0)
14934     {
14935         if (allProfileWeightsAreValid)
14936         {
14937             if (weightDest > weightJump)
14938             {
14939                 bDest->bbWeight = (weightDest - weightJump);
14940             }
14941             else if (!bDest->isRunRarely())
14942             {
14943                 bDest->bbWeight = BB_UNITY_WEIGHT;
14944             }
14945         }
14946         else
14947         {
14948             BasicBlock::weight_t newWeightDest    = 0;
14949             BasicBlock::weight_t unloopWeightDest = 0;
14950
14951             if (weightDest > weightJump)
14952             {
14953                 newWeightDest = (weightDest - weightJump);
14954             }
14955             if (weightDest >= (BB_LOOP_WEIGHT * BB_UNITY_WEIGHT) / 2)
14956             {
14957                 newWeightDest = (weightDest * 2) / (BB_LOOP_WEIGHT * BB_UNITY_WEIGHT);
14958             }
14959             if ((newWeightDest > 0) || (unloopWeightDest > 0))
14960             {
14961                 bDest->bbWeight = Max(newWeightDest, unloopWeightDest);
14962             }
14963         }
14964     }
14965
14966 #if DEBUG
14967     if (verbose)
14968     {
14969         // Dump out the newStmtList that we created
14970         printf("\nfgOptimizeBranch added these statements(s) at the end of BB%02u:\n", bJump->bbNum);
14971         for (stmt = newStmtList->AsStmt(); stmt; stmt = stmt->gtNextStmt)
14972         {
14973             gtDispTree(stmt);
14974         }
14975         printf("\nfgOptimizeBranch changed block BB%02u from BBJ_ALWAYS to BBJ_COND.\n", bJump->bbNum);
14976
14977         printf("\nAfter this change in fgOptimizeBranch the BB graph is:");
14978         fgDispBasicBlocks(verboseTrees);
14979         printf("\n");
14980     }
14981 #endif // DEBUG
14982
14983     return true;
14984 }
14985
14986 /*****************************************************************************
14987  *
14988  *  Function called to optimize switch statements
14989  */
14990
14991 bool Compiler::fgOptimizeSwitchJumps()
14992 {
14993     bool result = false; // Our return value
14994
14995 #if 0
14996     // TODO-CQ: Add switch jump optimizations?
14997     if (!fgHasSwitch)
14998         return false;
14999
15000     if (!fgHaveValidEdgeWeights)
15001         return false;
15002
15003     for (BasicBlock* bSrc = fgFirstBB; bSrc != NULL; bSrc = bSrc->bbNext)
15004     {
15005         if (bSrc->bbJumpKind == BBJ_SWITCH)
15006         {
15007             unsigned        jumpCnt; jumpCnt = bSrc->bbJumpSwt->bbsCount;
15008             BasicBlock**    jumpTab; jumpTab = bSrc->bbJumpSwt->bbsDstTab;
15009
15010             do
15011             {
15012                 BasicBlock*   bDst       = *jumpTab;
15013                 flowList*     edgeToDst  = fgGetPredForBlock(bDst, bSrc);
15014                 double        outRatio   = (double) edgeToDst->flEdgeWeightMin  / (double) bSrc->bbWeight;
15015
15016                 if (outRatio >= 0.60)
15017                 {
15018                     // straighten switch here...
15019                 }
15020             }
15021             while (++jumpTab, --jumpCnt);
15022         }
15023     }
15024 #endif
15025
15026     return result;
15027 }
15028
15029 #ifdef _PREFAST_
15030 #pragma warning(push)
15031 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
15032 #endif
15033 /*****************************************************************************
15034  *
15035  *  Function called to reorder the flowgraph of BasicBlocks such that any
15036  *  rarely run blocks are placed at the end of the block list.
15037  *  If we have profile information we also use that information to reverse
15038  *  all conditional jumps that would benefit.
15039  */
15040
15041 void Compiler::fgReorderBlocks()
15042 {
15043     noway_assert(opts.compDbgCode == false);
15044
15045 #if FEATURE_EH_FUNCLETS
15046     assert(fgFuncletsCreated);
15047 #endif // FEATURE_EH_FUNCLETS
15048
15049     // We can't relocate anything if we only have one block
15050     if (fgFirstBB->bbNext == nullptr)
15051     {
15052         return;
15053     }
15054
15055     bool newRarelyRun      = false;
15056     bool movedBlocks       = false;
15057     bool optimizedSwitches = false;
15058
15059     // First let us expand the set of run rarely blocks
15060     newRarelyRun |= fgExpandRarelyRunBlocks();
15061
15062 #if !FEATURE_EH_FUNCLETS
15063     movedBlocks |= fgRelocateEHRegions();
15064 #endif // !FEATURE_EH_FUNCLETS
15065
15066     //
15067     // If we are using profile weights we can change some
15068     // switch jumps into conditional test and jump
15069     //
15070     if (fgIsUsingProfileWeights())
15071     {
15072         //
15073         // Note that this is currently not yet implemented
15074         //
15075         optimizedSwitches = fgOptimizeSwitchJumps();
15076         if (optimizedSwitches)
15077         {
15078             fgUpdateFlowGraph();
15079         }
15080     }
15081
15082 #ifdef DEBUG
15083     if (verbose)
15084     {
15085         printf("*************** In fgReorderBlocks()\n");
15086
15087         printf("\nInitial BasicBlocks");
15088         fgDispBasicBlocks(verboseTrees);
15089         printf("\n");
15090     }
15091 #endif // DEBUG
15092
15093     BasicBlock* bNext;
15094     BasicBlock* bPrev;
15095     BasicBlock* block;
15096     unsigned    XTnum;
15097     EHblkDsc*   HBtab;
15098
15099     // Iterate over every block, remembering our previous block in bPrev
15100     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
15101     {
15102         //
15103         // Consider relocating the rarely run blocks such that they are at the end of the method.
15104         // We also consider reversing conditional branches so that they become a not taken forwards branch.
15105         //
15106
15107         // If block is marked with a BBF_KEEP_BBJ_ALWAYS flag then we don't move the block
15108         if ((block->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)
15109         {
15110             continue;
15111         }
15112
15113         // Finally and handlers blocks are to be kept contiguous.
15114         // TODO-CQ: Allow reordering within the handler region
15115         if (block->hasHndIndex() == true)
15116         {
15117             continue;
15118         }
15119
15120         bool        reorderBlock   = true; // This is set to false if we decide not to reorder 'block'
15121         bool        isRare         = block->isRunRarely();
15122         BasicBlock* bDest          = nullptr;
15123         bool        forwardBranch  = false;
15124         bool        backwardBranch = false;
15125
15126         // Setup bDest
15127         if ((bPrev->bbJumpKind == BBJ_COND) || (bPrev->bbJumpKind == BBJ_ALWAYS))
15128         {
15129             bDest          = bPrev->bbJumpDest;
15130             forwardBranch  = fgIsForwardBranch(bPrev);
15131             backwardBranch = !forwardBranch;
15132         }
15133
15134         // We will look for bPrev as a non rarely run block followed by block as a rarely run block
15135         //
15136         if (bPrev->isRunRarely())
15137         {
15138             reorderBlock = false;
15139         }
15140
15141         // If the weights of the bPrev, block and bDest were all obtained from a profile run
15142         // then we can use them to decide if it is useful to reverse this conditional branch
15143
15144         BasicBlock::weight_t profHotWeight = -1;
15145
15146         if (bPrev->hasProfileWeight() && block->hasProfileWeight() && ((bDest == nullptr) || bDest->hasProfileWeight()))
15147         {
15148             //
15149             // All blocks have profile information
15150             //
15151             if (forwardBranch)
15152             {
15153                 if (bPrev->bbJumpKind == BBJ_ALWAYS)
15154                 {
15155                     // We can pull up the blocks that the unconditional jump branches to
15156                     // if the weight of bDest is greater or equal to the weight of block
15157                     // also the weight of bDest can't be zero.
15158                     //
15159                     if ((bDest->bbWeight < block->bbWeight) || (bDest->bbWeight == 0))
15160                     {
15161                         reorderBlock = false;
15162                     }
15163                     else
15164                     {
15165                         //
15166                         // If this remains true then we will try to pull up bDest to succeed bPrev
15167                         //
15168                         bool moveDestUp = true;
15169
15170                         if (fgHaveValidEdgeWeights)
15171                         {
15172                             //
15173                             // The edge bPrev -> bDest must have a higher minimum weight
15174                             // than every other edge into bDest
15175                             //
15176                             flowList* edgeFromPrev = fgGetPredForBlock(bDest, bPrev);
15177                             noway_assert(edgeFromPrev != nullptr);
15178
15179                             // Examine all of the other edges into bDest
15180                             for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext)
15181                             {
15182                                 if (edge != edgeFromPrev)
15183                                 {
15184                                     if (edge->flEdgeWeightMax >= edgeFromPrev->flEdgeWeightMin)
15185                                     {
15186                                         moveDestUp = false;
15187                                         break;
15188                                     }
15189                                 }
15190                             }
15191                         }
15192                         else
15193                         {
15194                             //
15195                             // The block bPrev must have a higher weight
15196                             // than every other block that goes into bDest
15197                             //
15198
15199                             // Examine all of the other edges into bDest
15200                             for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext)
15201                             {
15202                                 BasicBlock* bTemp = edge->flBlock;
15203
15204                                 if ((bTemp != bPrev) && (bTemp->bbWeight >= bPrev->bbWeight))
15205                                 {
15206                                     moveDestUp = false;
15207                                     break;
15208                                 }
15209                             }
15210                         }
15211
15212                         // Are we still good to move bDest up to bPrev?
15213                         if (moveDestUp)
15214                         {
15215                             //
15216                             // We will consider all blocks that have less weight than profHotWeight to be
15217                             // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest
15218                             //
15219                             profHotWeight = bDest->bbWeight - 1;
15220                         }
15221                         else
15222                         {
15223                             if (block->isRunRarely())
15224                             {
15225                                 // We will move any rarely run blocks blocks
15226                                 profHotWeight = 0;
15227                             }
15228                             else
15229                             {
15230                                 // We will move all blocks that have a weight less or equal to our fall through block
15231                                 profHotWeight = block->bbWeight + 1;
15232                             }
15233                             // But we won't try to connect with bDest
15234                             bDest = nullptr;
15235                         }
15236                     }
15237                 }
15238                 else // (bPrev->bbJumpKind == BBJ_COND)
15239                 {
15240                     noway_assert(bPrev->bbJumpKind == BBJ_COND);
15241                     //
15242                     // We will reverse branch if the taken-jump to bDest ratio (i.e. 'takenRatio')
15243                     // is more than 51%
15244                     //
15245                     // We will setup profHotWeight to be maximum bbWeight that a block
15246                     // could have for us not to want to reverse the conditional branch
15247                     //
15248                     // We will consider all blocks that have less weight than profHotWeight to be
15249                     // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest
15250                     //
15251                     if (fgHaveValidEdgeWeights)
15252                     {
15253                         // We have valid edge weights, however even with valid edge weights
15254                         // we may have a minimum and maximum range for each edges value
15255                         //
15256                         // We will check that the min weight of the bPrev to bDest edge
15257                         //  is more than twice the max weight of the bPrev to block edge.
15258                         //
15259                         //                  bPrev -->   [BB04, weight 31]
15260                         //                                     |         \
15261                         //          edgeToBlock -------------> O          \
15262                         //          [min=8,max=10]             V           \
15263                         //                  block -->   [BB05, weight 10]   \
15264                         //                                                   \
15265                         //          edgeToDest ----------------------------> O
15266                         //          [min=21,max=23]                          |
15267                         //                                                   V
15268                         //                  bDest --------------->   [BB08, weight 21]
15269                         //
15270                         flowList* edgeToDest  = fgGetPredForBlock(bDest, bPrev);
15271                         flowList* edgeToBlock = fgGetPredForBlock(block, bPrev);
15272                         noway_assert(edgeToDest != nullptr);
15273                         noway_assert(edgeToBlock != nullptr);
15274                         //
15275                         // Calculate the taken ratio
15276                         //   A takenRation of 0.10 means taken 10% of the time, not taken 90% of the time
15277                         //   A takenRation of 0.50 means taken 50% of the time, not taken 50% of the time
15278                         //   A takenRation of 0.90 means taken 90% of the time, not taken 10% of the time
15279                         //
15280                         double takenCount =
15281                             ((double)edgeToDest->flEdgeWeightMin + (double)edgeToDest->flEdgeWeightMax) / 2.0;
15282                         double notTakenCount =
15283                             ((double)edgeToBlock->flEdgeWeightMin + (double)edgeToBlock->flEdgeWeightMax) / 2.0;
15284                         double totalCount = takenCount + notTakenCount;
15285                         double takenRatio = takenCount / totalCount;
15286
15287                         // If the takenRatio is greater or equal to 51% then we will reverse the branch
15288                         if (takenRatio < 0.51)
15289                         {
15290                             reorderBlock = false;
15291                         }
15292                         else
15293                         {
15294                             // set profHotWeight
15295                             profHotWeight = (edgeToBlock->flEdgeWeightMin + edgeToBlock->flEdgeWeightMax) / 2 - 1;
15296                         }
15297                     }
15298                     else
15299                     {
15300                         // We don't have valid edge weight so we will be more conservative
15301                         // We could have bPrev, block or bDest as part of a loop and thus have extra weight
15302                         //
15303                         // We will do two checks:
15304                         //   1. Check that the weight of bDest is at least two times more than block
15305                         //   2. Check that the weight of bPrev is at least three times more than block
15306                         //
15307                         //                  bPrev -->   [BB04, weight 31]
15308                         //                                     |         \
15309                         //                                     V          \
15310                         //                  block -->   [BB05, weight 10]  \
15311                         //                                                  \
15312                         //                                                  |
15313                         //                                                  V
15314                         //                  bDest --------------->   [BB08, weight 21]
15315                         //
15316                         //  For this case weightDest is calculated as (21+1)/2  or 11
15317                         //            and weightPrev is calculated as (31+2)/3  also 11
15318                         //
15319                         //  Generally both weightDest and weightPrev should calculate
15320                         //  the same value unless bPrev or bDest are part of a loop
15321                         //
15322                         BasicBlock::weight_t weightDest =
15323                             bDest->isMaxBBWeight() ? bDest->bbWeight : (bDest->bbWeight + 1) / 2;
15324                         BasicBlock::weight_t weightPrev =
15325                             bPrev->isMaxBBWeight() ? bPrev->bbWeight : (bPrev->bbWeight + 2) / 3;
15326
15327                         // select the lower of weightDest and weightPrev
15328                         profHotWeight = (weightDest < weightPrev) ? weightDest : weightPrev;
15329
15330                         // if the weight of block is greater (or equal) to profHotWeight then we don't reverse the cond
15331                         if (block->bbWeight >= profHotWeight)
15332                         {
15333                             reorderBlock = false;
15334                         }
15335                     }
15336                 }
15337             }
15338             else // not a forwardBranch
15339             {
15340                 if (bPrev->bbFallsThrough())
15341                 {
15342                     goto CHECK_FOR_RARE;
15343                 }
15344
15345                 // Here we should pull up the highest weight block remaining
15346                 // and place it here since bPrev does not fall through.
15347
15348                 BasicBlock::weight_t highestWeight           = 0;
15349                 BasicBlock*          candidateBlock          = nullptr;
15350                 BasicBlock*          lastNonFallThroughBlock = bPrev;
15351                 BasicBlock*          bTmp                    = bPrev->bbNext;
15352
15353                 while (bTmp != nullptr)
15354                 {
15355                     // Don't try to split a Call/Always pair
15356                     //
15357                     if (bTmp->isBBCallAlwaysPair())
15358                     {
15359                         // Move bTmp forward
15360                         bTmp = bTmp->bbNext;
15361                     }
15362
15363                     //
15364                     // Check for loop exit condition
15365                     //
15366                     if (bTmp == nullptr)
15367                     {
15368                         break;
15369                     }
15370
15371                     //
15372                     // if its weight is the highest one we've seen and
15373                     //  the EH regions allow for us to place bTmp after bPrev
15374                     //
15375                     if ((bTmp->bbWeight > highestWeight) && fgEhAllowsMoveBlock(bPrev, bTmp))
15376                     {
15377                         // When we have a current candidateBlock that is a conditional (or unconditional) jump
15378                         // to bTmp (which is a higher weighted block) then it is better to keep out current
15379                         // candidateBlock and have it fall into bTmp
15380                         //
15381                         if ((candidateBlock == nullptr) ||
15382                             ((candidateBlock->bbJumpKind != BBJ_COND) && (candidateBlock->bbJumpKind != BBJ_ALWAYS)) ||
15383                             (candidateBlock->bbJumpDest != bTmp))
15384                         {
15385                             // otherwise we have a new candidateBlock
15386                             //
15387                             highestWeight  = bTmp->bbWeight;
15388                             candidateBlock = lastNonFallThroughBlock->bbNext;
15389                         }
15390                     }
15391
15392                     if ((bTmp->bbFallsThrough() == false) || (bTmp->bbWeight == 0))
15393                     {
15394                         lastNonFallThroughBlock = bTmp;
15395                     }
15396
15397                     bTmp = bTmp->bbNext;
15398                 }
15399
15400                 // If we didn't find a suitable block then skip this
15401                 if (highestWeight == 0)
15402                 {
15403                     reorderBlock = false;
15404                 }
15405                 else
15406                 {
15407                     noway_assert(candidateBlock != nullptr);
15408
15409                     // If the candidateBlock is the same a block then skip this
15410                     if (candidateBlock == block)
15411                     {
15412                         reorderBlock = false;
15413                     }
15414                     else
15415                     {
15416                         // Set bDest to the block that we want to come after bPrev
15417                         bDest = candidateBlock;
15418
15419                         // set profHotWeight
15420                         profHotWeight = highestWeight - 1;
15421                     }
15422                 }
15423             }
15424         }
15425         else // we don't have good profile info (or we are falling through)
15426         {
15427
15428         CHECK_FOR_RARE:;
15429
15430             /* We only want to reorder when we have a rarely run   */
15431             /* block right after a normal block,                   */
15432             /* (bPrev is known to be a normal block at this point) */
15433             if (!isRare)
15434             {
15435                 if ((bDest == block->bbNext) && (block->bbJumpKind == BBJ_RETURN) && (bPrev->bbJumpKind == BBJ_ALWAYS))
15436                 {
15437                     // This is a common case with expressions like "return Expr1 && Expr2" -- move the return
15438                     // to establish fall-through.
15439                 }
15440                 else
15441                 {
15442                     reorderBlock = false;
15443                 }
15444             }
15445             else
15446             {
15447                 /* If the jump target bDest is also a rarely run block then we don't want to do the reversal */
15448                 if (bDest && bDest->isRunRarely())
15449                 {
15450                     reorderBlock = false; /* Both block and bDest are rarely run */
15451                 }
15452                 else
15453                 {
15454                     // We will move any rarely run blocks blocks
15455                     profHotWeight = 0;
15456                 }
15457             }
15458         }
15459
15460         if (reorderBlock == false)
15461         {
15462             //
15463             // Check for an unconditional branch to a conditional branch
15464             // which also branches back to our next block
15465             //
15466             if (fgOptimizeBranch(bPrev))
15467             {
15468                 noway_assert(bPrev->bbJumpKind == BBJ_COND);
15469             }
15470             continue;
15471         }
15472
15473         //  Now we need to determine which blocks should be moved
15474         //
15475         //  We consider one of two choices:
15476         //
15477         //  1. Moving the fall-through blocks (or rarely run blocks) down to
15478         //     later in the method and hopefully connecting the jump dest block
15479         //     so that it becomes the fall through block
15480         //
15481         //  And when bDest in not NULL, we also consider:
15482         //
15483         //  2. Moving the bDest block (or blocks) up to bPrev
15484         //     so that it could be used as a fall through block
15485         //
15486         //  We will prefer option #1 if we are able to connect the jump dest
15487         //  block as the fall though block otherwise will we try to use option #2
15488         //
15489
15490         //
15491         //  Consider option #1: relocating blocks starting at 'block'
15492         //    to later in flowgraph
15493         //
15494         // We set bStart to the first block that will be relocated
15495         // and bEnd to the last block that will be relocated
15496
15497         BasicBlock* bStart   = block;
15498         BasicBlock* bEnd     = bStart;
15499         bNext                = bEnd->bbNext;
15500         bool connected_bDest = false;
15501
15502         if ((backwardBranch && !isRare) ||
15503             ((block->bbFlags & BBF_DONT_REMOVE) != 0)) // Don't choose option #1 when block is the start of a try region
15504         {
15505             bStart = nullptr;
15506             bEnd   = nullptr;
15507         }
15508         else
15509         {
15510             while (true)
15511             {
15512                 // Don't try to split a Call/Always pair
15513                 //
15514                 if (bEnd->isBBCallAlwaysPair())
15515                 {
15516                     // Move bEnd and bNext forward
15517                     bEnd  = bNext;
15518                     bNext = bNext->bbNext;
15519                 }
15520
15521                 //
15522                 // Check for loop exit condition
15523                 //
15524                 if (bNext == nullptr)
15525                 {
15526                     break;
15527                 }
15528
15529 #if FEATURE_EH_FUNCLETS
15530                 // Check if we've reached the funclets region, at the end of the function
15531                 if (fgFirstFuncletBB == bEnd->bbNext)
15532                 {
15533                     break;
15534                 }
15535 #endif // FEATURE_EH_FUNCLETS
15536
15537                 if (bNext == bDest)
15538                 {
15539                     connected_bDest = true;
15540                     break;
15541                 }
15542
15543                 // All the blocks must have the same try index
15544                 // and must not have the BBF_DONT_REMOVE flag set
15545
15546                 if (!BasicBlock::sameTryRegion(bStart, bNext) || ((bNext->bbFlags & BBF_DONT_REMOVE) != 0))
15547                 {
15548                     // exit the loop, bEnd is now set to the
15549                     // last block that we want to relocate
15550                     break;
15551                 }
15552
15553                 // If we are relocating rarely run blocks..
15554                 if (isRare)
15555                 {
15556                     // ... then all blocks must be rarely run
15557                     if (!bNext->isRunRarely())
15558                     {
15559                         // exit the loop, bEnd is now set to the
15560                         // last block that we want to relocate
15561                         break;
15562                     }
15563                 }
15564                 else
15565                 {
15566                     // If we are moving blocks that are hot then all
15567                     // of the blocks moved must be less than profHotWeight */
15568                     if (bNext->bbWeight >= profHotWeight)
15569                     {
15570                         // exit the loop, bEnd is now set to the
15571                         // last block that we would relocate
15572                         break;
15573                     }
15574                 }
15575
15576                 // Move bEnd and bNext forward
15577                 bEnd  = bNext;
15578                 bNext = bNext->bbNext;
15579             }
15580
15581             // Set connected_bDest to true if moving blocks [bStart .. bEnd]
15582             //  connects with the the jump dest of bPrev (i.e bDest) and
15583             // thus allows bPrev fall through instead of jump.
15584             if (bNext == bDest)
15585             {
15586                 connected_bDest = true;
15587             }
15588         }
15589
15590         //  Now consider option #2: Moving the jump dest block (or blocks)
15591         //    up to bPrev
15592         //
15593         // The variables bStart2, bEnd2 and bPrev2 are used for option #2
15594         //
15595         // We will setup bStart2 to the first block that will be relocated
15596         // and bEnd2 to the last block that will be relocated
15597         // and bPrev2 to be the lexical pred of bDest
15598         //
15599         // If after this calculation bStart2 is NULL we cannot use option #2,
15600         // otherwise bStart2, bEnd2 and bPrev2 are all non-NULL and we will use option #2
15601
15602         BasicBlock* bStart2 = nullptr;
15603         BasicBlock* bEnd2   = nullptr;
15604         BasicBlock* bPrev2  = nullptr;
15605
15606         // If option #1 didn't connect bDest and bDest isn't NULL
15607         if ((connected_bDest == false) && (bDest != nullptr) &&
15608             //  The jump target cannot be moved if it has the BBF_DONT_REMOVE flag set
15609             ((bDest->bbFlags & BBF_DONT_REMOVE) == 0))
15610         {
15611             // We will consider option #2: relocating blocks starting at 'bDest' to succeed bPrev
15612             //
15613             // setup bPrev2 to be the lexical pred of bDest
15614
15615             bPrev2 = block;
15616             while (bPrev2 != nullptr)
15617             {
15618                 if (bPrev2->bbNext == bDest)
15619                 {
15620                     break;
15621                 }
15622
15623                 bPrev2 = bPrev2->bbNext;
15624             }
15625
15626             if ((bPrev2 != nullptr) && fgEhAllowsMoveBlock(bPrev, bDest))
15627             {
15628                 // We have decided that relocating bDest to be after bPrev is best
15629                 // Set bStart2 to the first block that will be relocated
15630                 // and bEnd2 to the last block that will be relocated
15631                 //
15632                 // Assigning to bStart2 selects option #2
15633                 //
15634                 bStart2 = bDest;
15635                 bEnd2   = bStart2;
15636                 bNext   = bEnd2->bbNext;
15637
15638                 while (true)
15639                 {
15640                     // Don't try to split a Call/Always pair
15641                     //
15642                     if (bEnd2->isBBCallAlwaysPair())
15643                     {
15644                         noway_assert(bNext->bbJumpKind == BBJ_ALWAYS);
15645                         // Move bEnd2 and bNext forward
15646                         bEnd2 = bNext;
15647                         bNext = bNext->bbNext;
15648                     }
15649
15650                     // Check for the Loop exit conditions
15651
15652                     if (bNext == nullptr)
15653                     {
15654                         break;
15655                     }
15656
15657                     if (bEnd2->bbFallsThrough() == false)
15658                     {
15659                         break;
15660                     }
15661
15662                     // If we are relocating rarely run blocks..
15663                     // All the blocks must have the same try index,
15664                     // and must not have the BBF_DONT_REMOVE flag set
15665
15666                     if (!BasicBlock::sameTryRegion(bStart2, bNext) || ((bNext->bbFlags & BBF_DONT_REMOVE) != 0))
15667                     {
15668                         // exit the loop, bEnd2 is now set to the
15669                         // last block that we want to relocate
15670                         break;
15671                     }
15672
15673                     if (isRare)
15674                     {
15675                         /* ... then all blocks must not be rarely run */
15676                         if (bNext->isRunRarely())
15677                         {
15678                             // exit the loop, bEnd2 is now set to the
15679                             // last block that we want to relocate
15680                             break;
15681                         }
15682                     }
15683                     else
15684                     {
15685                         // If we are relocating hot blocks
15686                         // all blocks moved must be greater than profHotWeight
15687                         if (bNext->bbWeight <= profHotWeight)
15688                         {
15689                             // exit the loop, bEnd2 is now set to the
15690                             // last block that we want to relocate
15691                             break;
15692                         }
15693                     }
15694
15695                     // Move bEnd2 and bNext forward
15696                     bEnd2 = bNext;
15697                     bNext = bNext->bbNext;
15698                 }
15699             }
15700         }
15701
15702         // If we are using option #1 then ...
15703         if (bStart2 == nullptr)
15704         {
15705             // Don't use option #1 for a backwards branch
15706             if (bStart == nullptr)
15707             {
15708                 continue;
15709             }
15710
15711             // .... Don't move a set of blocks that are already at the end of the main method
15712             if (bEnd == fgLastBBInMainFunction())
15713             {
15714                 continue;
15715             }
15716         }
15717
15718 #ifdef DEBUG
15719         if (verbose)
15720         {
15721             if (bDest != nullptr)
15722             {
15723                 if (bPrev->bbJumpKind == BBJ_COND)
15724                 {
15725                     printf("Decided to reverse conditional branch at block BB%02u branch to BB%02u ", bPrev->bbNum,
15726                            bDest->bbNum);
15727                 }
15728                 else if (bPrev->bbJumpKind == BBJ_ALWAYS)
15729                 {
15730                     printf("Decided to straighten unconditional branch at block BB%02u branch to BB%02u ", bPrev->bbNum,
15731                            bDest->bbNum);
15732                 }
15733                 else
15734                 {
15735                     printf("Decided to place hot code after BB%02u, placed BB%02u after this block ", bPrev->bbNum,
15736                            bDest->bbNum);
15737                 }
15738
15739                 if (profHotWeight > 0)
15740                 {
15741                     printf("because of IBC profile data\n");
15742                 }
15743                 else
15744                 {
15745                     if (bPrev->bbFallsThrough())
15746                     {
15747                         printf("since it falls into a rarely run block\n");
15748                     }
15749                     else
15750                     {
15751                         printf("since it is succeeded by a rarely run block\n");
15752                     }
15753                 }
15754             }
15755             else
15756             {
15757                 printf("Decided to relocate block(s) after block BB%02u since they are %s block(s)\n", bPrev->bbNum,
15758                        block->isRunRarely() ? "rarely run" : "uncommonly run");
15759             }
15760         }
15761 #endif // DEBUG
15762
15763         // We will set insertAfterBlk to the block the precedes our insertion range
15764         // We will set bStartPrev to be the block that precedes the set of blocks that we are moving
15765         BasicBlock* insertAfterBlk;
15766         BasicBlock* bStartPrev;
15767
15768         if (bStart2 != nullptr)
15769         {
15770             // Option #2: relocating blocks starting at 'bDest' to follow bPrev
15771
15772             // Update bStart and bEnd so that we can use these two for all later operations
15773             bStart = bStart2;
15774             bEnd   = bEnd2;
15775
15776             // Set bStartPrev to be the block that comes before bStart
15777             bStartPrev = bPrev2;
15778
15779             // We will move [bStart..bEnd] to immediately after bPrev
15780             insertAfterBlk = bPrev;
15781         }
15782         else
15783         {
15784             // option #1: Moving the fall-through blocks (or rarely run blocks) down to later in the method
15785
15786             // Set bStartPrev to be the block that come before bStart
15787             bStartPrev = bPrev;
15788
15789             // We will move [bStart..bEnd] but we will pick the insert location later
15790             insertAfterBlk = nullptr;
15791         }
15792
15793         // We are going to move [bStart..bEnd] so they can't be NULL
15794         noway_assert(bStart != nullptr);
15795         noway_assert(bEnd != nullptr);
15796
15797         // bEnd can't be a BBJ_CALLFINALLY unless it is a RETLESS call
15798         noway_assert((bEnd->bbJumpKind != BBJ_CALLFINALLY) || (bEnd->bbFlags & BBF_RETLESS_CALL));
15799
15800         // bStartPrev must be set to the block that precedes bStart
15801         noway_assert(bStartPrev->bbNext == bStart);
15802
15803         // Since we will be unlinking [bStart..bEnd],
15804         // we need to compute and remember if bStart is in each of
15805         // the try and handler regions
15806         //
15807         bool* fStartIsInTry = nullptr;
15808         bool* fStartIsInHnd = nullptr;
15809
15810         if (compHndBBtabCount > 0)
15811         {
15812             fStartIsInTry = new (this, CMK_Unknown) bool[compHndBBtabCount];
15813             fStartIsInHnd = new (this, CMK_Unknown) bool[compHndBBtabCount];
15814
15815             for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
15816             {
15817                 fStartIsInTry[XTnum] = HBtab->InTryRegionBBRange(bStart);
15818                 fStartIsInHnd[XTnum] = HBtab->InHndRegionBBRange(bStart);
15819             }
15820         }
15821
15822         /* Temporarily unlink [bStart..bEnd] from the flow graph */
15823         fgUnlinkRange(bStart, bEnd);
15824
15825         if (insertAfterBlk == nullptr)
15826         {
15827             // Find new location for the unlinked block(s)
15828             // Set insertAfterBlk to the block which will precede the insertion point
15829
15830             if (!bStart->hasTryIndex() && isRare)
15831             {
15832                 // We'll just insert the blocks at the end of the method. If the method
15833                 // has funclets, we will insert at the end of the main method but before
15834                 // any of the funclets. Note that we create funclets before we call
15835                 // fgReorderBlocks().
15836
15837                 insertAfterBlk = fgLastBBInMainFunction();
15838                 noway_assert(insertAfterBlk != bPrev);
15839             }
15840             else
15841             {
15842                 BasicBlock* startBlk;
15843                 BasicBlock* lastBlk;
15844                 EHblkDsc*   ehDsc = ehInitTryBlockRange(bStart, &startBlk, &lastBlk);
15845
15846                 BasicBlock* endBlk;
15847
15848                 /* Setup startBlk and endBlk as the range to search */
15849
15850                 if (ehDsc != nullptr)
15851                 {
15852                     endBlk = lastBlk->bbNext;
15853
15854                     /*
15855                        Multiple (nested) try regions might start from the same BB.
15856                        For example,
15857
15858                        try3   try2   try1
15859                        |---   |---   |---   BB01
15860                        |      |      |      BB02
15861                        |      |      |---   BB03
15862                        |      |             BB04
15863                        |      |------------ BB05
15864                        |                    BB06
15865                        |------------------- BB07
15866
15867                        Now if we want to insert in try2 region, we will start with startBlk=BB01.
15868                        The following loop will allow us to start from startBlk==BB04.
15869                     */
15870                     while (!BasicBlock::sameTryRegion(startBlk, bStart) && (startBlk != endBlk))
15871                     {
15872                         startBlk = startBlk->bbNext;
15873                     }
15874
15875                     // startBlk cannot equal endBlk as it must come before endBlk
15876                     if (startBlk == endBlk)
15877                     {
15878                         goto CANNOT_MOVE;
15879                     }
15880
15881                     // we also can't start searching the try region at bStart
15882                     if (startBlk == bStart)
15883                     {
15884                         // if bEnd is the last block in the method or
15885                         // or if bEnd->bbNext is in a different try region
15886                         // then we cannot move the blocks
15887                         //
15888                         if ((bEnd->bbNext == nullptr) || !BasicBlock::sameTryRegion(startBlk, bEnd->bbNext))
15889                         {
15890                             goto CANNOT_MOVE;
15891                         }
15892
15893                         startBlk = bEnd->bbNext;
15894
15895                         // Check that the new startBlk still comes before endBlk
15896
15897                         // startBlk cannot equal endBlk as it must come before endBlk
15898                         if (startBlk == endBlk)
15899                         {
15900                             goto CANNOT_MOVE;
15901                         }
15902
15903                         BasicBlock* tmpBlk = startBlk;
15904                         while ((tmpBlk != endBlk) && (tmpBlk != nullptr))
15905                         {
15906                             tmpBlk = tmpBlk->bbNext;
15907                         }
15908
15909                         // when tmpBlk is NULL that means startBlk is after endBlk
15910                         // so there is no way to move bStart..bEnd within the try region
15911                         if (tmpBlk == nullptr)
15912                         {
15913                             goto CANNOT_MOVE;
15914                         }
15915                     }
15916                 }
15917                 else
15918                 {
15919                     noway_assert(isRare == false);
15920
15921                     /* We'll search through the entire main method */
15922                     startBlk = fgFirstBB;
15923                     endBlk   = fgEndBBAfterMainFunction();
15924                 }
15925
15926                 // Calculate nearBlk and jumpBlk and then call fgFindInsertPoint()
15927                 // to find our insertion block
15928                 //
15929                 {
15930                     // If the set of blocks that we are moving ends with a BBJ_ALWAYS to
15931                     // another [rarely run] block that comes after bPrev (forward branch)
15932                     // then we can set up nearBlk to eliminate this jump sometimes
15933                     //
15934                     BasicBlock* nearBlk = nullptr;
15935                     BasicBlock* jumpBlk = nullptr;
15936
15937                     if ((bEnd->bbJumpKind == BBJ_ALWAYS) && (!isRare || bEnd->bbJumpDest->isRunRarely()) &&
15938                         fgIsForwardBranch(bEnd, bPrev))
15939                     {
15940                         // Set nearBlk to be the block in [startBlk..endBlk]
15941                         // such that nearBlk->bbNext == bEnd->JumpDest
15942                         // if no such block exists then set nearBlk to NULL
15943                         nearBlk = startBlk;
15944                         jumpBlk = bEnd;
15945                         do
15946                         {
15947                             // We do not want to set nearBlk to bPrev
15948                             // since then we will not move [bStart..bEnd]
15949                             //
15950                             if (nearBlk != bPrev)
15951                             {
15952                                 // Check if nearBlk satisfies our requirement
15953                                 if (nearBlk->bbNext == bEnd->bbJumpDest)
15954                                 {
15955                                     break;
15956                                 }
15957                             }
15958
15959                             // Did we reach the endBlk?
15960                             if (nearBlk == endBlk)
15961                             {
15962                                 nearBlk = nullptr;
15963                                 break;
15964                             }
15965
15966                             // advance nearBlk to the next block
15967                             nearBlk = nearBlk->bbNext;
15968
15969                         } while (nearBlk != nullptr);
15970                     }
15971
15972                     // if nearBlk is NULL then we set nearBlk to be the
15973                     // first block that we want to insert after.
15974                     if (nearBlk == nullptr)
15975                     {
15976                         if (bDest != nullptr)
15977                         {
15978                             // we want to insert after bDest
15979                             nearBlk = bDest;
15980                         }
15981                         else
15982                         {
15983                             // we want to insert after bPrev
15984                             nearBlk = bPrev;
15985                         }
15986                     }
15987
15988                     /* Set insertAfterBlk to the block which we will insert after. */
15989
15990                     insertAfterBlk =
15991                         fgFindInsertPoint(bStart->bbTryIndex,
15992                                           true, // Insert in the try region.
15993                                           startBlk, endBlk, nearBlk, jumpBlk, bStart->bbWeight == BB_ZERO_WEIGHT);
15994                 }
15995
15996                 /* See if insertAfterBlk is the same as where we started, */
15997                 /*  or if we could not find any insertion point     */
15998
15999                 if ((insertAfterBlk == bPrev) || (insertAfterBlk == nullptr))
16000                 {
16001                 CANNOT_MOVE:;
16002                     /* We couldn't move the blocks, so put everything back */
16003                     /* relink [bStart .. bEnd] into the flow graph */
16004
16005                     bPrev->setNext(bStart);
16006                     if (bEnd->bbNext)
16007                     {
16008                         bEnd->bbNext->bbPrev = bEnd;
16009                     }
16010 #ifdef DEBUG
16011                     if (verbose)
16012                     {
16013                         if (bStart != bEnd)
16014                         {
16015                             printf("Could not relocate blocks (BB%02u .. BB%02u)\n", bStart->bbNum, bEnd->bbNum);
16016                         }
16017                         else
16018                         {
16019                             printf("Could not relocate block BB%02u\n", bStart->bbNum);
16020                         }
16021                     }
16022 #endif // DEBUG
16023                     continue;
16024                 }
16025             }
16026         }
16027
16028         noway_assert(insertAfterBlk != nullptr);
16029         noway_assert(bStartPrev != nullptr);
16030         noway_assert(bStartPrev != insertAfterBlk);
16031
16032 #ifdef DEBUG
16033         movedBlocks = true;
16034
16035         if (verbose)
16036         {
16037             const char* msg;
16038             if (bStart2 != nullptr)
16039             {
16040                 msg = "hot";
16041             }
16042             else
16043             {
16044                 if (isRare)
16045                 {
16046                     msg = "rarely run";
16047                 }
16048                 else
16049                 {
16050                     msg = "uncommon";
16051                 }
16052             }
16053
16054             printf("Relocated %s ", msg);
16055             if (bStart != bEnd)
16056             {
16057                 printf("blocks (BB%02u .. BB%02u)", bStart->bbNum, bEnd->bbNum);
16058             }
16059             else
16060             {
16061                 printf("block BB%02u", bStart->bbNum);
16062             }
16063
16064             if (bPrev->bbJumpKind == BBJ_COND)
16065             {
16066                 printf(" by reversing conditional jump at BB%02u\n", bPrev->bbNum);
16067             }
16068             else
16069             {
16070                 printf("\n", bPrev->bbNum);
16071             }
16072         }
16073 #endif // DEBUG
16074
16075         if (bPrev->bbJumpKind == BBJ_COND)
16076         {
16077             /* Reverse the bPrev jump condition */
16078             GenTree* condTest = bPrev->lastStmt();
16079
16080             condTest = condTest->gtStmt.gtStmtExpr;
16081             noway_assert(condTest->gtOper == GT_JTRUE);
16082
16083             condTest->gtOp.gtOp1 = gtReverseCond(condTest->gtOp.gtOp1);
16084
16085             if (bStart2 == nullptr)
16086             {
16087                 /* Set the new jump dest for bPrev to the rarely run or uncommon block(s) */
16088                 bPrev->bbJumpDest = bStart;
16089                 bStart->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
16090             }
16091             else
16092             {
16093                 noway_assert(insertAfterBlk == bPrev);
16094                 noway_assert(insertAfterBlk->bbNext == block);
16095
16096                 /* Set the new jump dest for bPrev to the rarely run or uncommon block(s) */
16097                 bPrev->bbJumpDest = block;
16098                 block->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
16099             }
16100         }
16101
16102         // If we are moving blocks that are at the end of a try or handler
16103         // we will need to shorten ebdTryLast or ebdHndLast
16104         //
16105         ehUpdateLastBlocks(bEnd, bStartPrev);
16106
16107         // If we are moving blocks into the end of a try region or handler region
16108         // we will need to extend ebdTryLast or ebdHndLast so the blocks that we
16109         // are moving are part of this try or handler region.
16110         //
16111         for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
16112         {
16113             // Are we moving blocks to the end of a try region?
16114             if (HBtab->ebdTryLast == insertAfterBlk)
16115             {
16116                 if (fStartIsInTry[XTnum])
16117                 {
16118                     // bStart..bEnd is in the try, so extend the try region
16119                     fgSetTryEnd(HBtab, bEnd);
16120                 }
16121             }
16122
16123             // Are we moving blocks to the end of a handler region?
16124             if (HBtab->ebdHndLast == insertAfterBlk)
16125             {
16126                 if (fStartIsInHnd[XTnum])
16127                 {
16128                     // bStart..bEnd is in the handler, so extend the handler region
16129                     fgSetHndEnd(HBtab, bEnd);
16130                 }
16131             }
16132         }
16133
16134         /* We have decided to insert the block(s) after 'insertAfterBlk' */
16135         fgMoveBlocksAfter(bStart, bEnd, insertAfterBlk);
16136
16137         if (bDest)
16138         {
16139             /* We may need to insert an unconditional branch after bPrev to bDest */
16140             fgConnectFallThrough(bPrev, bDest);
16141         }
16142         else
16143         {
16144             /* If bPrev falls through, we must insert a jump to block */
16145             fgConnectFallThrough(bPrev, block);
16146         }
16147
16148         BasicBlock* bSkip = bEnd->bbNext;
16149
16150         /* If bEnd falls through, we must insert a jump to bNext */
16151         fgConnectFallThrough(bEnd, bNext);
16152
16153         if (bStart2 == nullptr)
16154         {
16155             /* If insertAfterBlk falls through, we are forced to     */
16156             /* add a jump around the block(s) we just inserted */
16157             fgConnectFallThrough(insertAfterBlk, bSkip);
16158         }
16159         else
16160         {
16161             /* We may need to insert an unconditional branch after bPrev2 to bStart */
16162             fgConnectFallThrough(bPrev2, bStart);
16163         }
16164
16165 #if DEBUG
16166         if (verbose)
16167         {
16168             printf("\nAfter this change in fgReorderBlocks the BB graph is:");
16169             fgDispBasicBlocks(verboseTrees);
16170             printf("\n");
16171         }
16172         fgVerifyHandlerTab();
16173
16174         // Make sure that the predecessor lists are accurate
16175         if (expensiveDebugCheckLevel >= 2)
16176         {
16177             fgDebugCheckBBlist();
16178         }
16179 #endif // DEBUG
16180
16181         // Set our iteration point 'block' to be the new bPrev->bbNext
16182         //  It will be used as the next bPrev
16183         block = bPrev->bbNext;
16184
16185     } // end of for loop(bPrev,block)
16186
16187     bool changed = movedBlocks || newRarelyRun || optimizedSwitches;
16188
16189     if (changed)
16190     {
16191         fgNeedsUpdateFlowGraph = true;
16192 #if DEBUG
16193         // Make sure that the predecessor lists are accurate
16194         if (expensiveDebugCheckLevel >= 2)
16195         {
16196             fgDebugCheckBBlist();
16197         }
16198 #endif // DEBUG
16199     }
16200 }
16201 #ifdef _PREFAST_
16202 #pragma warning(pop)
16203 #endif
16204
16205 /*-------------------------------------------------------------------------
16206  *
16207  * Walk the basic blocks list to determine the first block to place in the
16208  * cold section.  This would be the first of a series of rarely executed blocks
16209  * such that no succeeding blocks are in a try region or an exception handler
16210  * or are rarely executed.
16211  */
16212
16213 void Compiler::fgDetermineFirstColdBlock()
16214 {
16215 #ifdef DEBUG
16216     if (verbose)
16217     {
16218         printf("\n*************** In fgDetermineFirstColdBlock()\n");
16219     }
16220 #endif // DEBUG
16221
16222     // Since we may need to create a new transistion block
16223     // we assert that it is OK to create new blocks.
16224     //
16225     assert(fgSafeBasicBlockCreation);
16226
16227     fgFirstColdBlock = nullptr;
16228
16229 #if FEATURE_STACK_FP_X87
16230     if (compMayHaveTransitionBlocks)
16231     {
16232         opts.compProcedureSplitting = false;
16233
16234         // See comment above declaration of compMayHaveTransitionBlocks for comments on this
16235         JITDUMP("Turning off procedure splitting for this method, as it may end up having FP transition blocks\n");
16236     }
16237 #endif // FEATURE_STACK_FP_X87
16238
16239     if (!opts.compProcedureSplitting)
16240     {
16241         JITDUMP("No procedure splitting will be done for this method\n");
16242         return;
16243     }
16244
16245 #ifdef DEBUG
16246     if ((compHndBBtabCount > 0) && !opts.compProcedureSplittingEH)
16247     {
16248         JITDUMP("No procedure splitting will be done for this method with EH (by request)\n");
16249         return;
16250     }
16251 #endif // DEBUG
16252
16253 #if FEATURE_EH_FUNCLETS
16254     // TODO-CQ: handle hot/cold splitting in functions with EH (including synchronized methods
16255     // that create EH in methods without explicit EH clauses).
16256
16257     if (compHndBBtabCount > 0)
16258     {
16259         JITDUMP("No procedure splitting will be done for this method with EH (implementation limitation)\n");
16260         return;
16261     }
16262 #endif // FEATURE_EH_FUNCLETS
16263
16264     BasicBlock* firstColdBlock       = nullptr;
16265     BasicBlock* prevToFirstColdBlock = nullptr;
16266     BasicBlock* block;
16267     BasicBlock* lblk;
16268
16269     for (lblk = nullptr, block = fgFirstBB; block != nullptr; lblk = block, block = block->bbNext)
16270     {
16271         bool blockMustBeInHotSection = false;
16272
16273 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
16274         if (bbIsHandlerBeg(block))
16275         {
16276             blockMustBeInHotSection = true;
16277         }
16278 #endif // HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
16279
16280         // Do we have a candidate for the first cold block?
16281         if (firstColdBlock != nullptr)
16282         {
16283             // We have a candidate for first cold block
16284
16285             // Is this a hot block?
16286             if (blockMustBeInHotSection || (block->isRunRarely() == false))
16287             {
16288                 // We have to restart the search for the first cold block
16289                 firstColdBlock       = nullptr;
16290                 prevToFirstColdBlock = nullptr;
16291             }
16292         }
16293         else // (firstColdBlock == NULL)
16294         {
16295             // We don't have a candidate for first cold block
16296
16297             // Is this a cold block?
16298             if (!blockMustBeInHotSection && (block->isRunRarely() == true))
16299             {
16300                 //
16301                 // If the last block that was hot was a BBJ_COND
16302                 // then we will have to add an unconditional jump
16303                 // so the code size for block needs be large
16304                 // enough to make it worth our while
16305                 //
16306                 if ((lblk == nullptr) || (lblk->bbJumpKind != BBJ_COND) || (fgGetCodeEstimate(block) >= 8))
16307                 {
16308                     // This block is now a candidate for first cold block
16309                     // Also remember the predecessor to this block
16310                     firstColdBlock       = block;
16311                     prevToFirstColdBlock = lblk;
16312                 }
16313             }
16314         }
16315     }
16316
16317     if (firstColdBlock == fgFirstBB)
16318     {
16319         // If the first block is Cold then we can't move any blocks
16320         // into the cold section
16321
16322         firstColdBlock = nullptr;
16323     }
16324
16325     if (firstColdBlock != nullptr)
16326     {
16327         noway_assert(prevToFirstColdBlock != nullptr);
16328
16329         if (prevToFirstColdBlock == nullptr)
16330         {
16331             return; // To keep Prefast happy
16332         }
16333
16334         // If we only have one cold block
16335         // then it may not be worth it to move it
16336         // into the Cold section as a jump to the
16337         // Cold section is 5 bytes in size.
16338         //
16339         if (firstColdBlock->bbNext == nullptr)
16340         {
16341             // If the size of the cold block is 7 or less
16342             // then we will keep it in the Hot section.
16343             //
16344             if (fgGetCodeEstimate(firstColdBlock) < 8)
16345             {
16346                 firstColdBlock = nullptr;
16347                 goto EXIT;
16348             }
16349         }
16350
16351         // When the last Hot block fall through into the Cold section
16352         // we may need to add a jump
16353         //
16354         if (prevToFirstColdBlock->bbFallsThrough())
16355         {
16356             switch (prevToFirstColdBlock->bbJumpKind)
16357             {
16358                 default:
16359                     noway_assert(!"Unhandled jumpkind in fgDetermineFirstColdBlock()");
16360
16361                 case BBJ_CALLFINALLY:
16362                     // A BBJ_CALLFINALLY that falls through is always followed
16363                     // by an empty BBJ_ALWAYS.
16364                     //
16365                     assert(prevToFirstColdBlock->isBBCallAlwaysPair());
16366                     firstColdBlock =
16367                         firstColdBlock->bbNext; // Note that this assignment could make firstColdBlock == nullptr
16368                     break;
16369
16370                 case BBJ_COND:
16371                     //
16372                     // This is a slightly more complicated case, because we will
16373                     // probably need to insert a block to jump to the cold section.
16374                     //
16375                     if (firstColdBlock->isEmpty() && (firstColdBlock->bbJumpKind == BBJ_ALWAYS))
16376                     {
16377                         // We can just use this block as the transitionBlock
16378                         firstColdBlock = firstColdBlock->bbNext;
16379                         // Note that this assignment could make firstColdBlock == NULL
16380                     }
16381                     else
16382                     {
16383                         BasicBlock* transitionBlock = fgNewBBafter(BBJ_ALWAYS, prevToFirstColdBlock, true);
16384                         transitionBlock->bbJumpDest = firstColdBlock;
16385                         transitionBlock->inheritWeight(firstColdBlock);
16386
16387                         noway_assert(fgComputePredsDone);
16388
16389                         // Update the predecessor list for firstColdBlock
16390                         fgReplacePred(firstColdBlock, prevToFirstColdBlock, transitionBlock);
16391
16392                         // Add prevToFirstColdBlock as a predecessor for transitionBlock
16393                         fgAddRefPred(transitionBlock, prevToFirstColdBlock);
16394                     }
16395                     break;
16396
16397                 case BBJ_NONE:
16398                     // If the block preceding the first cold block is BBJ_NONE,
16399                     // convert it to BBJ_ALWAYS to force an explicit jump.
16400
16401                     prevToFirstColdBlock->bbJumpDest = firstColdBlock;
16402                     prevToFirstColdBlock->bbJumpKind = BBJ_ALWAYS;
16403                     break;
16404             }
16405         }
16406     }
16407
16408     if (firstColdBlock != nullptr)
16409     {
16410         firstColdBlock->bbFlags |= BBF_JMP_TARGET;
16411
16412         for (block = firstColdBlock; block; block = block->bbNext)
16413         {
16414             block->bbFlags |= BBF_COLD;
16415         }
16416     }
16417
16418 EXIT:;
16419
16420 #ifdef DEBUG
16421     if (verbose)
16422     {
16423         if (firstColdBlock)
16424         {
16425             printf("fgFirstColdBlock is BB%02u.\n", firstColdBlock->bbNum);
16426         }
16427         else
16428         {
16429             printf("fgFirstColdBlock is NULL.\n");
16430         }
16431
16432         fgDispBasicBlocks();
16433     }
16434
16435     fgVerifyHandlerTab();
16436 #endif // DEBUG
16437
16438     fgFirstColdBlock = firstColdBlock;
16439 }
16440
16441 #ifdef _PREFAST_
16442 #pragma warning(push)
16443 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
16444 #endif
16445 /*****************************************************************************
16446  *
16447  *  Function called to "comb" the basic block list.
16448  *  Removes any empty blocks, unreachable blocks and redundant jumps.
16449  *  Most of those appear after dead store removal and folding of conditionals.
16450  *
16451  *  Returns: true if the flowgraph has been modified
16452  *
16453  *  It also compacts basic blocks
16454  *   (consecutive basic blocks that should in fact be one).
16455  *
16456  *  NOTE:
16457  *    Debuggable code and Min Optimization JIT also introduces basic blocks
16458  *    but we do not optimize those!
16459  */
16460
16461 bool Compiler::fgUpdateFlowGraph(bool doTailDuplication)
16462 {
16463 #ifdef DEBUG
16464     if (verbose)
16465     {
16466         printf("\n*************** In fgUpdateFlowGraph()");
16467     }
16468 #endif // DEBUG
16469
16470     /* This should never be called for debuggable code */
16471
16472     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
16473
16474 #ifdef DEBUG
16475     if (verbose)
16476     {
16477         printf("\nBefore updating the flow graph:\n");
16478         fgDispBasicBlocks(verboseTrees);
16479         printf("\n");
16480     }
16481 #endif // DEBUG
16482
16483     /* Walk all the basic blocks - look for unconditional jumps, empty blocks, blocks to compact, etc...
16484      *
16485      * OBSERVATION:
16486      *      Once a block is removed the predecessors are not accurate (assuming they were at the beginning)
16487      *      For now we will only use the information in bbRefs because it is easier to be updated
16488      */
16489
16490     bool modified = false;
16491     bool change;
16492     do
16493     {
16494         change = false;
16495
16496         BasicBlock* block;           // the current block
16497         BasicBlock* bPrev = nullptr; // the previous non-worthless block
16498         BasicBlock* bNext;           // the successor of the current block
16499         BasicBlock* bDest;           // the jump target of the current block
16500
16501         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
16502         {
16503             /*  Some blocks may be already marked removed by other optimizations
16504              *  (e.g worthless loop removal), without being explicitly removed
16505              *  from the list.
16506              */
16507
16508             if (block->bbFlags & BBF_REMOVED)
16509             {
16510                 if (bPrev)
16511                 {
16512                     bPrev->setNext(block->bbNext);
16513                 }
16514                 else
16515                 {
16516                     /* WEIRD first basic block is removed - should have an assert here */
16517                     noway_assert(!"First basic block marked as BBF_REMOVED???");
16518
16519                     fgFirstBB = block->bbNext;
16520                 }
16521                 continue;
16522             }
16523
16524         /*  We jump to the REPEAT label if we performed a change involving the current block
16525          *  This is in case there are other optimizations that can show up
16526          *  (e.g. - compact 3 blocks in a row)
16527          *  If nothing happens, we then finish the iteration and move to the next block
16528          */
16529
16530         REPEAT:;
16531
16532             bNext = block->bbNext;
16533             bDest = nullptr;
16534
16535             if (block->bbJumpKind == BBJ_ALWAYS)
16536             {
16537                 bDest = block->bbJumpDest;
16538                 if (doTailDuplication && fgOptimizeUncondBranchToSimpleCond(block, bDest))
16539                 {
16540                     change   = true;
16541                     modified = true;
16542                     bDest    = block->bbJumpDest;
16543                     bNext    = block->bbNext;
16544                 }
16545             }
16546
16547             // Remove JUMPS to the following block
16548             // and optimize any JUMPS to JUMPS
16549
16550             if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
16551             {
16552                 bDest = block->bbJumpDest;
16553                 if (bDest == bNext)
16554                 {
16555                     if (fgOptimizeBranchToNext(block, bNext, bPrev))
16556                     {
16557                         change   = true;
16558                         modified = true;
16559                         bDest    = nullptr;
16560                     }
16561                 }
16562             }
16563
16564             if (bDest != nullptr)
16565             {
16566                 // Do we have a JUMP to an empty unconditional JUMP block?
16567                 if (bDest->isEmpty() && (bDest->bbJumpKind == BBJ_ALWAYS) &&
16568                     (bDest != bDest->bbJumpDest)) // special case for self jumps
16569                 {
16570                     if (fgOptimizeBranchToEmptyUnconditional(block, bDest))
16571                     {
16572                         change   = true;
16573                         modified = true;
16574                         goto REPEAT;
16575                     }
16576                 }
16577
16578                 // Check for a conditional branch that just skips over an empty BBJ_ALWAYS block
16579
16580                 if ((block->bbJumpKind == BBJ_COND) &&   // block is a BBJ_COND block
16581                     (bNext != nullptr) &&                // block is not the last block
16582                     (bNext->bbRefs == 1) &&              // No other block jumps to bNext
16583                     (bNext->bbNext == bDest) &&          // The block after bNext is the BBJ_COND jump dest
16584                     (bNext->bbJumpKind == BBJ_ALWAYS) && // The next block is a BBJ_ALWAYS block
16585                     bNext->isEmpty() &&                  // and it is an an empty block
16586                     (bNext != bNext->bbJumpDest) &&      // special case for self jumps
16587                     (bDest != fgFirstColdBlock))
16588                 {
16589                     bool optimizeJump = true;
16590
16591                     // We do not optimize jumps between two different try regions.
16592                     // However jumping to a block that is not in any try region is OK
16593                     //
16594                     if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
16595                     {
16596                         optimizeJump = false;
16597                     }
16598
16599                     // Also consider bNext's try region
16600                     //
16601                     if (bNext->hasTryIndex() && !BasicBlock::sameTryRegion(block, bNext))
16602                     {
16603                         optimizeJump = false;
16604                     }
16605
16606                     // If we are optimizing using real profile weights
16607                     // then don't optimize a conditional jump to an unconditional jump
16608                     // until after we have computed the edge weights
16609                     //
16610                     if (fgIsUsingProfileWeights())
16611                     {
16612                         // if block and bdest are in different hot/cold regions we can't do this this optimization
16613                         // because we can't allow fall-through into the cold region.
16614                         if (!fgEdgeWeightsComputed || fgInDifferentRegions(block, bDest))
16615                         {
16616                             fgNeedsUpdateFlowGraph = true;
16617                             optimizeJump           = false;
16618                         }
16619                     }
16620
16621                     if (optimizeJump)
16622                     {
16623 #ifdef DEBUG
16624                         if (verbose)
16625                         {
16626                             printf("\nReversing a conditional jump around an unconditional jump (BB%02u -> BB%02u -> "
16627                                    "BB%02u)\n",
16628                                    block->bbNum, bDest->bbNum, bNext->bbJumpDest->bbNum);
16629                         }
16630 #endif // DEBUG
16631                         /* Reverse the jump condition */
16632
16633                         GenTree* test = block->lastNode();
16634                         noway_assert(test->OperIsConditionalJump());
16635
16636                         if (test->OperGet() == GT_JTRUE)
16637                         {
16638                             GenTree* cond = gtReverseCond(test->gtOp.gtOp1);
16639                             assert(cond == test->gtOp.gtOp1); // Ensure `gtReverseCond` did not create a new node.
16640                             test->gtOp.gtOp1 = cond;
16641                         }
16642                         else
16643                         {
16644                             gtReverseCond(test);
16645                         }
16646
16647                         // Optimize the Conditional JUMP to go to the new target
16648                         block->bbJumpDest = bNext->bbJumpDest;
16649
16650                         fgAddRefPred(bNext->bbJumpDest, block, fgRemoveRefPred(bNext->bbJumpDest, bNext));
16651
16652                         /*
16653                           Unlink bNext from the BasicBlock list; note that we can
16654                           do this even though other blocks could jump to it - the
16655                           reason is that elsewhere in this function we always
16656                           redirect jumps to jumps to jump to the final label,
16657                           so even if another block jumps to bNext it won't matter
16658                           once we're done since any such jump will be redirected
16659                           to the final target by the time we're done here.
16660                         */
16661
16662                         fgRemoveRefPred(bNext, block);
16663                         fgUnlinkBlock(bNext);
16664
16665                         /* Mark the block as removed */
16666                         bNext->bbFlags |= BBF_REMOVED;
16667
16668                         // If this is the first Cold basic block update fgFirstColdBlock
16669                         if (bNext == fgFirstColdBlock)
16670                         {
16671                             fgFirstColdBlock = bNext->bbNext;
16672                         }
16673
16674                         //
16675                         // If we removed the end of a try region or handler region
16676                         // we will need to update ebdTryLast or ebdHndLast.
16677                         //
16678
16679                         EHblkDsc* HBtab;
16680                         EHblkDsc* HBtabEnd;
16681
16682                         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd;
16683                              HBtab++)
16684                         {
16685                             if ((HBtab->ebdTryLast == bNext) || (HBtab->ebdHndLast == bNext))
16686                             {
16687                                 fgSkipRmvdBlocks(HBtab);
16688                             }
16689                         }
16690
16691                         // we optimized this JUMP - goto REPEAT to catch similar cases
16692                         change   = true;
16693                         modified = true;
16694
16695 #ifdef DEBUG
16696                         if (verbose)
16697                         {
16698                             printf("\nAfter reversing the jump:\n");
16699                             fgDispBasicBlocks(verboseTrees);
16700                         }
16701 #endif // DEBUG
16702
16703                         /*
16704                            For a rare special case we cannot jump to REPEAT
16705                            as jumping to REPEAT will cause us to delete 'block'
16706                            because it currently appears to be unreachable.  As
16707                            it is a self loop that only has a single bbRef (itself)
16708                            However since the unlinked bNext has additional bbRefs
16709                            (that we will later connect to 'block'), it is not really
16710                            unreachable.
16711                         */
16712                         if ((bNext->bbRefs > 0) && (bNext->bbJumpDest == block) && (block->bbRefs == 1))
16713                         {
16714                             continue;
16715                         }
16716
16717                         goto REPEAT;
16718                     }
16719                 }
16720             }
16721
16722             //
16723             // Update the switch jump table such that it follows jumps to jumps:
16724             //
16725             if (block->bbJumpKind == BBJ_SWITCH)
16726             {
16727                 if (fgOptimizeSwitchBranches(block))
16728                 {
16729                     change   = true;
16730                     modified = true;
16731                     goto REPEAT;
16732                 }
16733             }
16734
16735             noway_assert(!(block->bbFlags & BBF_REMOVED));
16736
16737             /* COMPACT blocks if possible */
16738
16739             if (fgCanCompactBlocks(block, bNext))
16740             {
16741                 fgCompactBlocks(block, bNext);
16742
16743                 /* we compacted two blocks - goto REPEAT to catch similar cases */
16744                 change   = true;
16745                 modified = true;
16746                 goto REPEAT;
16747             }
16748
16749             /* Remove unreachable or empty blocks - do not consider blocks marked BBF_DONT_REMOVE or genReturnBB block
16750              * These include first and last block of a TRY, exception handlers and RANGE_CHECK_FAIL THROW blocks */
16751
16752             if ((block->bbFlags & BBF_DONT_REMOVE) == BBF_DONT_REMOVE || block == genReturnBB)
16753             {
16754                 bPrev = block;
16755                 continue;
16756             }
16757
16758 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16759             // Don't remove the BBJ_ALWAYS block of a BBJ_CALLFINALLY/BBJ_ALWAYS pair.
16760             if (block->countOfInEdges() == 0 && bPrev->bbJumpKind == BBJ_CALLFINALLY)
16761             {
16762                 assert(bPrev->isBBCallAlwaysPair());
16763                 noway_assert(!(bPrev->bbFlags & BBF_RETLESS_CALL));
16764                 noway_assert(block->bbJumpKind == BBJ_ALWAYS);
16765                 bPrev = block;
16766                 continue;
16767             }
16768 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16769
16770             noway_assert(!block->bbCatchTyp);
16771             noway_assert(!(block->bbFlags & BBF_TRY_BEG));
16772
16773             /* Remove unreachable blocks
16774              *
16775              * We'll look for blocks that have countOfInEdges() = 0 (blocks may become
16776              * unreachable due to a BBJ_ALWAYS introduced by conditional folding for example)
16777              */
16778
16779             if (block->countOfInEdges() == 0)
16780             {
16781                 /* no references -> unreachable - remove it */
16782                 /* For now do not update the bbNum, do it at the end */
16783
16784                 fgRemoveBlock(block, true);
16785
16786                 change   = true;
16787                 modified = true;
16788
16789                 /* we removed the current block - the rest of the optimizations won't have a target
16790                  * continue with the next one */
16791
16792                 continue;
16793             }
16794             else if (block->countOfInEdges() == 1)
16795             {
16796                 switch (block->bbJumpKind)
16797                 {
16798                     case BBJ_COND:
16799                     case BBJ_ALWAYS:
16800                         if (block->bbJumpDest == block)
16801                         {
16802                             fgRemoveBlock(block, true);
16803
16804                             change   = true;
16805                             modified = true;
16806
16807                             /* we removed the current block - the rest of the optimizations
16808                              * won't have a target so continue with the next block */
16809
16810                             continue;
16811                         }
16812                         break;
16813
16814                     default:
16815                         break;
16816                 }
16817             }
16818
16819             noway_assert(!(block->bbFlags & BBF_REMOVED));
16820
16821             /* Remove EMPTY blocks */
16822
16823             if (block->isEmpty())
16824             {
16825                 assert(bPrev == block->bbPrev);
16826                 if (fgOptimizeEmptyBlock(block))
16827                 {
16828                     change   = true;
16829                     modified = true;
16830                 }
16831
16832                 /* Have we removed the block? */
16833
16834                 if (block->bbFlags & BBF_REMOVED)
16835                 {
16836                     /* block was removed - no change to bPrev */
16837                     continue;
16838                 }
16839             }
16840
16841             /* Set the predecessor of the last reachable block
16842              * If we removed the current block, the predecessor remains unchanged
16843              * otherwise, since the current block is ok, it becomes the predecessor */
16844
16845             noway_assert(!(block->bbFlags & BBF_REMOVED));
16846
16847             bPrev = block;
16848         }
16849     } while (change);
16850
16851     fgNeedsUpdateFlowGraph = false;
16852
16853 #ifdef DEBUG
16854     if (verbose && modified)
16855     {
16856         printf("\nAfter updating the flow graph:\n");
16857         fgDispBasicBlocks(verboseTrees);
16858         fgDispHandlerTab();
16859     }
16860
16861     if (compRationalIRForm)
16862     {
16863         for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
16864         {
16865             LIR::AsRange(block).CheckLIR(this);
16866         }
16867     }
16868
16869     fgVerifyHandlerTab();
16870     // Make sure that the predecessor lists are accurate
16871     fgDebugCheckBBlist();
16872     fgDebugCheckUpdate();
16873 #endif // DEBUG
16874
16875     return modified;
16876 }
16877 #ifdef _PREFAST_
16878 #pragma warning(pop)
16879 #endif
16880
16881 /*****************************************************************************
16882  *  Check that the flow graph is really updated
16883  */
16884
16885 #ifdef DEBUG
16886
16887 void Compiler::fgDebugCheckUpdate()
16888 {
16889     if (!compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))
16890     {
16891         return;
16892     }
16893
16894     /* We check for these conditions:
16895      * no unreachable blocks  -> no blocks have countOfInEdges() = 0
16896      * no empty blocks        -> no blocks have bbTreeList = 0
16897      * no un-imported blocks  -> no blocks have BBF_IMPORTED not set (this is
16898      *                           kind of redundand with the above, but to make sure)
16899      * no un-compacted blocks -> BBJ_NONE followed by block with no jumps to it (countOfInEdges() = 1)
16900      */
16901
16902     BasicBlock* prev;
16903     BasicBlock* block;
16904     for (prev = nullptr, block = fgFirstBB; block != nullptr; prev = block, block = block->bbNext)
16905     {
16906         /* no unreachable blocks */
16907
16908         if ((block->countOfInEdges() == 0) && !(block->bbFlags & BBF_DONT_REMOVE)
16909 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16910             // With funclets, we never get rid of the BBJ_ALWAYS part of a BBJ_CALLFINALLY/BBJ_ALWAYS pair,
16911             // even if we can prove that the finally block never returns.
16912             && (prev == NULL || block->bbJumpKind != BBJ_ALWAYS || !prev->isBBCallAlwaysPair())
16913 #endif // FEATURE_EH_FUNCLETS
16914                 )
16915         {
16916             noway_assert(!"Unreachable block not removed!");
16917         }
16918
16919         /* no empty blocks */
16920
16921         if (block->isEmpty() && !(block->bbFlags & BBF_DONT_REMOVE))
16922         {
16923             switch (block->bbJumpKind)
16924             {
16925                 case BBJ_CALLFINALLY:
16926                 case BBJ_EHFINALLYRET:
16927                 case BBJ_EHFILTERRET:
16928                 case BBJ_RETURN:
16929                 /* for BBJ_ALWAYS is probably just a GOTO, but will have to be treated */
16930                 case BBJ_ALWAYS:
16931                 case BBJ_EHCATCHRET:
16932                     /* These jump kinds are allowed to have empty tree lists */
16933                     break;
16934
16935                 default:
16936                     /* it may be the case that the block had more than one reference to it
16937                      * so we couldn't remove it */
16938
16939                     if (block->countOfInEdges() == 0)
16940                     {
16941                         noway_assert(!"Empty block not removed!");
16942                     }
16943                     break;
16944             }
16945         }
16946
16947         /* no un-imported blocks */
16948
16949         if (!(block->bbFlags & BBF_IMPORTED))
16950         {
16951             /* internal blocks do not count */
16952
16953             if (!(block->bbFlags & BBF_INTERNAL))
16954             {
16955                 noway_assert(!"Non IMPORTED block not removed!");
16956             }
16957         }
16958
16959         bool prevIsCallAlwaysPair = ((prev != nullptr) && prev->isBBCallAlwaysPair());
16960
16961         // Check for an unnecessary jumps to the next block
16962         bool doAssertOnJumpToNextBlock = false; // unless we have a BBJ_COND or BBJ_ALWAYS we can not assert
16963
16964         if (block->bbJumpKind == BBJ_COND)
16965         {
16966             // A conditional branch should never jump to the next block
16967             // as it can be folded into a BBJ_NONE;
16968             doAssertOnJumpToNextBlock = true;
16969         }
16970         else if (block->bbJumpKind == BBJ_ALWAYS)
16971         {
16972             // Generally we will want to assert if a BBJ_ALWAYS branches to the next block
16973             doAssertOnJumpToNextBlock = true;
16974
16975             // If the BBF_KEEP_BBJ_ALWAYS flag is set we allow it to jump to the next block
16976             if (block->bbFlags & BBF_KEEP_BBJ_ALWAYS)
16977             {
16978                 doAssertOnJumpToNextBlock = false;
16979             }
16980
16981             // A call/always pair is also allowed to jump to the next block
16982             if (prevIsCallAlwaysPair)
16983             {
16984                 doAssertOnJumpToNextBlock = false;
16985             }
16986
16987             // We are allowed to have a branch from a hot 'block' to a cold 'bbNext'
16988             //
16989             if ((block->bbNext != nullptr) && fgInDifferentRegions(block, block->bbNext))
16990             {
16991                 doAssertOnJumpToNextBlock = false;
16992             }
16993         }
16994
16995         if (doAssertOnJumpToNextBlock)
16996         {
16997             if (block->bbJumpDest == block->bbNext)
16998             {
16999                 noway_assert(!"Unnecessary jump to the next block!");
17000             }
17001         }
17002
17003         /* Make sure BBF_KEEP_BBJ_ALWAYS is set correctly */
17004
17005         if ((block->bbJumpKind == BBJ_ALWAYS) && prevIsCallAlwaysPair)
17006         {
17007             noway_assert(block->bbFlags & BBF_KEEP_BBJ_ALWAYS);
17008         }
17009
17010         /* For a BBJ_CALLFINALLY block we make sure that we are followed by */
17011         /* an BBJ_ALWAYS block with BBF_INTERNAL set */
17012         /* or that it's a BBF_RETLESS_CALL */
17013         if (block->bbJumpKind == BBJ_CALLFINALLY)
17014         {
17015             assert((block->bbFlags & BBF_RETLESS_CALL) || block->isBBCallAlwaysPair());
17016         }
17017
17018         /* no un-compacted blocks */
17019
17020         if (fgCanCompactBlocks(block, block->bbNext))
17021         {
17022             noway_assert(!"Found un-compacted blocks!");
17023         }
17024     }
17025 }
17026
17027 #endif // DEBUG
17028
17029 /*****************************************************************************
17030  * We've inserted a new block before 'block' that should be part of the same EH region as 'block'.
17031  * Update the EH table to make this so. Also, set the new block to have the right EH region data
17032  * (copy the bbTryIndex, bbHndIndex, and bbCatchTyp from 'block' to the new predecessor, and clear
17033  * 'bbCatchTyp' from 'block').
17034  */
17035 void Compiler::fgExtendEHRegionBefore(BasicBlock* block)
17036 {
17037     assert(block->bbPrev != nullptr);
17038
17039     BasicBlock* bPrev = block->bbPrev;
17040
17041     bPrev->copyEHRegion(block);
17042
17043     // The first block (and only the first block) of a handler has bbCatchTyp set
17044     bPrev->bbCatchTyp = block->bbCatchTyp;
17045     block->bbCatchTyp = BBCT_NONE;
17046
17047     EHblkDsc* HBtab;
17048     EHblkDsc* HBtabEnd;
17049
17050     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
17051     {
17052         /* Multiple pointers in EHblkDsc can point to same block. We can not early out after the first match. */
17053         if (HBtab->ebdTryBeg == block)
17054         {
17055 #ifdef DEBUG
17056             if (verbose)
17057             {
17058                 printf("EH#%u: New first block of try: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
17059             }
17060 #endif // DEBUG
17061             HBtab->ebdTryBeg = bPrev;
17062             bPrev->bbFlags |= BBF_TRY_BEG | BBF_DONT_REMOVE | BBF_HAS_LABEL;
17063
17064             // clear the TryBeg flag unless it begins another try region
17065             if (!bbIsTryBeg(block))
17066             {
17067                 block->bbFlags &= ~BBF_TRY_BEG;
17068             }
17069         }
17070
17071         if (HBtab->ebdHndBeg == block)
17072         {
17073 #ifdef DEBUG
17074             if (verbose)
17075             {
17076                 printf("EH#%u: New first block of handler: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
17077             }
17078 #endif // DEBUG
17079
17080             // The first block of a handler has an artificial extra refcount. Transfer that to the new block.
17081             assert(block->bbRefs > 0);
17082             block->bbRefs--;
17083
17084             HBtab->ebdHndBeg = bPrev;
17085             bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL;
17086
17087 #if FEATURE_EH_FUNCLETS
17088             if (fgFuncletsCreated)
17089             {
17090                 assert((block->bbFlags & BBF_FUNCLET_BEG) != 0);
17091                 bPrev->bbFlags |= BBF_FUNCLET_BEG;
17092                 block->bbFlags &= ~BBF_FUNCLET_BEG;
17093             }
17094 #endif // FEATURE_EH_FUNCLETS
17095
17096             bPrev->bbRefs++;
17097
17098             // If this is a handler for a filter, the last block of the filter will end with
17099             // a BBJ_EJFILTERRET block that has a bbJumpDest that jumps to the first block of
17100             // it's handler.  So we need to update it to keep things in sync.
17101             //
17102             if (HBtab->HasFilter())
17103             {
17104                 BasicBlock* bFilterLast = HBtab->BBFilterLast();
17105                 assert(bFilterLast != nullptr);
17106                 assert(bFilterLast->bbJumpKind == BBJ_EHFILTERRET);
17107                 assert(bFilterLast->bbJumpDest == block);
17108 #ifdef DEBUG
17109                 if (verbose)
17110                 {
17111                     printf("EH#%u: Updating bbJumpDest for filter ret block: BB%02u => BB%02u\n", ehGetIndex(HBtab),
17112                            bFilterLast->bbNum, bPrev->bbNum);
17113                 }
17114 #endif // DEBUG
17115                 // Change the bbJumpDest for bFilterLast from the old first 'block' to the new first 'bPrev'
17116                 bFilterLast->bbJumpDest = bPrev;
17117             }
17118         }
17119
17120         if (HBtab->HasFilter() && (HBtab->ebdFilter == block))
17121         {
17122 #ifdef DEBUG
17123             if (verbose)
17124             {
17125                 printf("EH#%u: New first block of filter: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
17126             }
17127 #endif // DEBUG
17128
17129             // The first block of a filter has an artificial extra refcount. Transfer that to the new block.
17130             assert(block->bbRefs > 0);
17131             block->bbRefs--;
17132
17133             HBtab->ebdFilter = bPrev;
17134             bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL;
17135
17136 #if FEATURE_EH_FUNCLETS
17137             if (fgFuncletsCreated)
17138             {
17139                 assert((block->bbFlags & BBF_FUNCLET_BEG) != 0);
17140                 bPrev->bbFlags |= BBF_FUNCLET_BEG;
17141                 block->bbFlags &= ~BBF_FUNCLET_BEG;
17142             }
17143 #endif // FEATURE_EH_FUNCLETS
17144
17145             bPrev->bbRefs++;
17146         }
17147     }
17148 }
17149
17150 /*****************************************************************************
17151  * We've inserted a new block after 'block' that should be part of the same EH region as 'block'.
17152  * Update the EH table to make this so. Also, set the new block to have the right EH region data.
17153  */
17154
17155 void Compiler::fgExtendEHRegionAfter(BasicBlock* block)
17156 {
17157     BasicBlock* newBlk = block->bbNext;
17158     assert(newBlk != nullptr);
17159
17160     newBlk->copyEHRegion(block);
17161     newBlk->bbCatchTyp =
17162         BBCT_NONE; // Only the first block of a catch has this set, and 'newBlk' can't be the first block of a catch.
17163
17164     // TODO-Throughput: if the block is not in an EH region, then we don't need to walk the EH table looking for 'last'
17165     // block pointers to update.
17166     ehUpdateLastBlocks(block, newBlk);
17167 }
17168
17169 /*****************************************************************************
17170  *
17171  * Insert a BasicBlock before the given block.
17172  */
17173
17174 BasicBlock* Compiler::fgNewBBbefore(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion)
17175 {
17176     // Create a new BasicBlock and chain it in
17177
17178     BasicBlock* newBlk = bbNewBasicBlock(jumpKind);
17179     newBlk->bbFlags |= BBF_INTERNAL;
17180
17181     fgInsertBBbefore(block, newBlk);
17182
17183     newBlk->bbRefs = 0;
17184
17185     if (newBlk->bbFallsThrough() && block->isRunRarely())
17186     {
17187         newBlk->bbSetRunRarely();
17188     }
17189
17190     if (extendRegion)
17191     {
17192         fgExtendEHRegionBefore(block);
17193     }
17194     else
17195     {
17196         // When extendRegion is false the caller is responsible for setting these two values
17197         newBlk->setTryIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
17198         newBlk->setHndIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
17199     }
17200
17201     // We assume that if the block we are inserting before is in the cold region, then this new
17202     // block will also be in the cold region.
17203     newBlk->bbFlags |= (block->bbFlags & BBF_COLD);
17204
17205     return newBlk;
17206 }
17207
17208 /*****************************************************************************
17209  *
17210  * Insert a BasicBlock after the given block.
17211  */
17212
17213 BasicBlock* Compiler::fgNewBBafter(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion)
17214 {
17215     // Create a new BasicBlock and chain it in
17216
17217     BasicBlock* newBlk = bbNewBasicBlock(jumpKind);
17218     newBlk->bbFlags |= BBF_INTERNAL;
17219
17220     fgInsertBBafter(block, newBlk);
17221
17222     newBlk->bbRefs = 0;
17223
17224     if (block->bbFallsThrough() && block->isRunRarely())
17225     {
17226         newBlk->bbSetRunRarely();
17227     }
17228
17229     if (extendRegion)
17230     {
17231         fgExtendEHRegionAfter(block);
17232     }
17233     else
17234     {
17235         // When extendRegion is false the caller is responsible for setting these two values
17236         newBlk->setTryIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
17237         newBlk->setHndIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
17238     }
17239
17240     // If the new block is in the cold region (because the block we are inserting after
17241     // is in the cold region), mark it as such.
17242     newBlk->bbFlags |= (block->bbFlags & BBF_COLD);
17243
17244     return newBlk;
17245 }
17246
17247 /*****************************************************************************
17248  *  Inserts basic block before existing basic block.
17249  *
17250  *  If insertBeforeBlk is in the funclet region, then newBlk will be in the funclet region.
17251  *  (If insertBeforeBlk is the first block of the funclet region, then 'newBlk' will be the
17252  *  new first block of the funclet region.)
17253  */
17254 void Compiler::fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk)
17255 {
17256     if (insertBeforeBlk->bbPrev)
17257     {
17258         fgInsertBBafter(insertBeforeBlk->bbPrev, newBlk);
17259     }
17260     else
17261     {
17262         newBlk->setNext(fgFirstBB);
17263
17264         fgFirstBB      = newBlk;
17265         newBlk->bbPrev = nullptr;
17266     }
17267
17268 #if FEATURE_EH_FUNCLETS
17269
17270     /* Update fgFirstFuncletBB if insertBeforeBlk is the first block of the funclet region. */
17271
17272     if (fgFirstFuncletBB == insertBeforeBlk)
17273     {
17274         fgFirstFuncletBB = newBlk;
17275     }
17276
17277 #endif // FEATURE_EH_FUNCLETS
17278 }
17279
17280 /*****************************************************************************
17281  *  Inserts basic block after existing basic block.
17282  *
17283  *  If insertBeforeBlk is in the funclet region, then newBlk will be in the funclet region.
17284  *  (It can't be used to insert a block as the first block of the funclet region).
17285  */
17286 void Compiler::fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk)
17287 {
17288     newBlk->bbNext = insertAfterBlk->bbNext;
17289
17290     if (insertAfterBlk->bbNext)
17291     {
17292         insertAfterBlk->bbNext->bbPrev = newBlk;
17293     }
17294
17295     insertAfterBlk->bbNext = newBlk;
17296     newBlk->bbPrev         = insertAfterBlk;
17297
17298     if (fgLastBB == insertAfterBlk)
17299     {
17300         fgLastBB = newBlk;
17301         assert(fgLastBB->bbNext == nullptr);
17302     }
17303 }
17304
17305 // We have two edges (bAlt => bCur) and (bCur => bNext).
17306 //
17307 // Returns true if the weight of (bAlt => bCur)
17308 //  is greater than the weight of (bCur => bNext).
17309 // We compare the edge weights if we have valid edge weights
17310 //  otherwise we compare blocks weights.
17311 //
17312 bool Compiler::fgIsBetterFallThrough(BasicBlock* bCur, BasicBlock* bAlt)
17313 {
17314     // bCur can't be NULL and must be a fall through bbJumpKind
17315     noway_assert(bCur != nullptr);
17316     noway_assert(bCur->bbFallsThrough());
17317     noway_assert(bAlt != nullptr);
17318
17319     // We only handle the cases when bAlt is a BBJ_ALWAYS or a BBJ_COND
17320     if ((bAlt->bbJumpKind != BBJ_ALWAYS) && (bAlt->bbJumpKind != BBJ_COND))
17321     {
17322         return false;
17323     }
17324
17325     // if bAlt doesn't jump to bCur it can't be a better fall through than bCur
17326     if (bAlt->bbJumpDest != bCur)
17327     {
17328         return false;
17329     }
17330
17331     // Currently bNext is the fall through for bCur
17332     BasicBlock* bNext = bCur->bbNext;
17333     noway_assert(bNext != nullptr);
17334
17335     // We will set result to true if bAlt is a better fall through than bCur
17336     bool result;
17337     if (fgHaveValidEdgeWeights)
17338     {
17339         // We will compare the edge weight for our two choices
17340         flowList* edgeFromAlt = fgGetPredForBlock(bCur, bAlt);
17341         flowList* edgeFromCur = fgGetPredForBlock(bNext, bCur);
17342         noway_assert(edgeFromCur != nullptr);
17343         noway_assert(edgeFromAlt != nullptr);
17344
17345         result = (edgeFromAlt->flEdgeWeightMin > edgeFromCur->flEdgeWeightMax);
17346     }
17347     else
17348     {
17349         if (bAlt->bbJumpKind == BBJ_ALWAYS)
17350         {
17351             // Our result is true if bAlt's weight is more than bCur's weight
17352             result = (bAlt->bbWeight > bCur->bbWeight);
17353         }
17354         else
17355         {
17356             noway_assert(bAlt->bbJumpKind == BBJ_COND);
17357             // Our result is true if bAlt's weight is more than twice bCur's weight
17358             result = (bAlt->bbWeight > (2 * bCur->bbWeight));
17359         }
17360     }
17361     return result;
17362 }
17363
17364 //------------------------------------------------------------------------
17365 // fgCheckEHCanInsertAfterBlock: Determine if a block can be inserted after
17366 // 'blk' and legally be put in the EH region specified by 'regionIndex'. This
17367 // can be true if the most nested region the block is in is already 'regionIndex',
17368 // as we'll just extend the most nested region (and any region ending at the same block).
17369 // It can also be true if it is the end of (a set of) EH regions, such that
17370 // inserting the block and properly extending some EH regions (if necessary)
17371 // puts the block in the correct region. We only consider the case of extending
17372 // an EH region after 'blk' (that is, to include 'blk' and the newly insert block);
17373 // we don't consider inserting a block as the the first block of an EH region following 'blk'.
17374 //
17375 // Consider this example:
17376 //
17377 //      try3   try2   try1
17378 //      |---   |      |      BB01
17379 //      |      |---   |      BB02
17380 //      |      |      |---   BB03
17381 //      |      |      |      BB04
17382 //      |      |---   |---   BB05
17383 //      |                    BB06
17384 //      |-----------------   BB07
17385 //
17386 // Passing BB05 and try1/try2/try3 as the region to insert into (as well as putInTryRegion==true)
17387 // will all return 'true'. Here are the cases:
17388 // 1. Insert into try1: the most nested EH region BB05 is in is already try1, so we can insert after
17389 //    it and extend try1 (and try2).
17390 // 2. Insert into try2: we can extend try2, but leave try1 alone.
17391 // 3. Insert into try3: we can leave try1 and try2 alone, and put the new block just in try3. Note that
17392 //    in this case, after we "loop outwards" in the EH nesting, we get to a place where we're in the middle
17393 //    of the try3 region, not at the end of it.
17394 // In all cases, it is possible to put a block after BB05 and put it in any of these three 'try' regions legally.
17395 //
17396 // Filters are ignored; if 'blk' is in a filter, the answer will be false.
17397 //
17398 // Arguments:
17399 //    blk - the BasicBlock we are checking to see if we can insert after.
17400 //    regionIndex - the EH region we want to insert a block into. regionIndex is
17401 //          in the range [0..compHndBBtabCount]; 0 means "main method".
17402 //    putInTryRegion - 'true' if the new block should be inserted in the 'try' region of 'regionIndex'.
17403 //          For regionIndex 0 (the "main method"), this should be 'true'.
17404 //
17405 // Return Value:
17406 //    'true' if a block can be inserted after 'blk' and put in EH region 'regionIndex', else 'false'.
17407 //
17408 bool Compiler::fgCheckEHCanInsertAfterBlock(BasicBlock* blk, unsigned regionIndex, bool putInTryRegion)
17409 {
17410     assert(blk != nullptr);
17411     assert(regionIndex <= compHndBBtabCount);
17412
17413     if (regionIndex == 0)
17414     {
17415         assert(putInTryRegion);
17416     }
17417
17418     bool     inTryRegion;
17419     unsigned nestedRegionIndex = ehGetMostNestedRegionIndex(blk, &inTryRegion);
17420
17421     bool insertOK = true;
17422     for (;;)
17423     {
17424         if (nestedRegionIndex == regionIndex)
17425         {
17426             // This block is in the region we want to be in. We can insert here if it's the right type of region.
17427             // (If we want to be in the 'try' region, but the block is in the handler region, then inserting a
17428             // new block after 'blk' can't put it in the 'try' region, and vice-versa, since we only consider
17429             // extending regions after, not prepending to regions.)
17430             // This check will be 'true' if we are trying to put something in the main function (as putInTryRegion
17431             // must be 'true' if regionIndex is zero, and inTryRegion will also be 'true' if nestedRegionIndex is zero).
17432             insertOK = (putInTryRegion == inTryRegion);
17433             break;
17434         }
17435         else if (nestedRegionIndex == 0)
17436         {
17437             // The block is in the main function, but we want to put something in a nested region. We can't do that.
17438             insertOK = false;
17439             break;
17440         }
17441
17442         assert(nestedRegionIndex > 0);
17443         EHblkDsc* ehDsc = ehGetDsc(nestedRegionIndex - 1); // ehGetDsc uses [0..compHndBBtabCount) form.
17444
17445         if (inTryRegion)
17446         {
17447             if (blk != ehDsc->ebdTryLast)
17448             {
17449                 // Not the last block? Then it must be somewhere else within the try region, so we can't insert here.
17450                 insertOK = false;
17451                 break; // exit the 'for' loop
17452             }
17453         }
17454         else
17455         {
17456             // We ignore filters.
17457             if (blk != ehDsc->ebdHndLast)
17458             {
17459                 // Not the last block? Then it must be somewhere else within the handler region, so we can't insert
17460                 // here.
17461                 insertOK = false;
17462                 break; // exit the 'for' loop
17463             }
17464         }
17465
17466         // Things look good for this region; check the enclosing regions, if any.
17467
17468         nestedRegionIndex =
17469             ehGetEnclosingRegionIndex(nestedRegionIndex - 1,
17470                                       &inTryRegion); // ehGetEnclosingRegionIndex uses [0..compHndBBtabCount) form.
17471
17472         // Convert to [0..compHndBBtabCount] form.
17473         nestedRegionIndex = (nestedRegionIndex == EHblkDsc::NO_ENCLOSING_INDEX) ? 0 : nestedRegionIndex + 1;
17474     } // end of for(;;)
17475
17476     return insertOK;
17477 }
17478
17479 //------------------------------------------------------------------------
17480 // Finds the block closest to endBlk in the range [startBlk..endBlk) after which a block can be
17481 // inserted easily. Note that endBlk cannot be returned; its predecessor is the last block that can
17482 // be returned. The new block will be put in an EH region described by the arguments regionIndex,
17483 // putInTryRegion, startBlk, and endBlk (explained below), so it must be legal to place to put the
17484 // new block after the insertion location block, give it the specified EH region index, and not break
17485 // EH nesting rules. This function is careful to choose a block in the correct EH region. However,
17486 // it assumes that the new block can ALWAYS be placed at the end (just before endBlk). That means
17487 // that the caller must ensure that is true.
17488 //
17489 // Below are the possible cases for the arguments to this method:
17490 //      1. putInTryRegion == true and regionIndex > 0:
17491 //         Search in the try region indicated by regionIndex.
17492 //      2. putInTryRegion == false and regionIndex > 0:
17493 //         a. If startBlk is the first block of a filter and endBlk is the block after the end of the
17494 //            filter (that is, the startBlk and endBlk match a filter bounds exactly), then choose a
17495 //            location within this filter region. (Note that, due to IL rules, filters do not have any
17496 //            EH nested within them.) Otherwise, filters are skipped.
17497 //         b. Else, search in the handler region indicated by regionIndex.
17498 //      3. regionIndex = 0:
17499 //         Search in the entire main method, excluding all EH regions. In this case, putInTryRegion must be true.
17500 //
17501 // This method makes sure to find an insertion point which would not cause the inserted block to
17502 // be put inside any inner try/filter/handler regions.
17503 //
17504 // The actual insertion occurs after the returned block. Note that the returned insertion point might
17505 // be the last block of a more nested EH region, because the new block will be inserted after the insertion
17506 // point, and will not extend the more nested EH region. For example:
17507 //
17508 //      try3   try2   try1
17509 //      |---   |      |      BB01
17510 //      |      |---   |      BB02
17511 //      |      |      |---   BB03
17512 //      |      |      |      BB04
17513 //      |      |---   |---   BB05
17514 //      |                    BB06
17515 //      |-----------------   BB07
17516 //
17517 // for regionIndex==try3, putInTryRegion==true, we might return BB05, even though BB05 will have a try index
17518 // for try1 (the most nested 'try' region the block is in). That's because when we insert after BB05, the new
17519 // block will be in the correct, desired EH region, since try1 and try2 regions will not be extended to include
17520 // the inserted block. Furthermore, for regionIndex==try2, putInTryRegion==true, we can also return BB05. In this
17521 // case, when the new block is inserted, the try1 region remains the same, but we need extend region 'try2' to
17522 // include the inserted block. (We also need to check all parent regions as well, just in case any parent regions
17523 // also end on the same block, in which case we would also need to extend the parent regions. This is standard
17524 // procedure when inserting a block at the end of an EH region.)
17525 //
17526 // If nearBlk is non-nullptr then we return the closest block after nearBlk that will work best.
17527 //
17528 // We try to find a block in the appropriate region that is not a fallthrough block, so we can insert after it
17529 // without the need to insert a jump around the inserted block.
17530 //
17531 // Note that regionIndex is numbered the same as BasicBlock::bbTryIndex and BasicBlock::bbHndIndex, that is, "0" is
17532 // "main method" and otherwise is +1 from normal, so we can call, e.g., ehGetDsc(tryIndex - 1).
17533 //
17534 // Arguments:
17535 //    regionIndex - the region index where the new block will be inserted. Zero means entire method;
17536 //          non-zero means either a "try" or a "handler" region, depending on what putInTryRegion says.
17537 //    putInTryRegion - 'true' to put the block in the 'try' region corresponding to 'regionIndex', 'false'
17538 //          to put the block in the handler region. Should be 'true' if regionIndex==0.
17539 //    startBlk - start block of range to search.
17540 //    endBlk - end block of range to search (don't include this block in the range). Can be nullptr to indicate
17541 //          the end of the function.
17542 //    nearBlk - If non-nullptr, try to find an insertion location closely after this block. If nullptr, we insert
17543 //          at the best location found towards the end of the acceptable block range.
17544 //    jumpBlk - When nearBlk is set, this can be set to the block which jumps to bNext->bbNext (TODO: need to review
17545 //    this?)
17546 //    runRarely - true if the block being inserted is expected to be rarely run. This helps determine
17547 //          the best place to put the new block, by putting in a place that has the same 'rarely run' characteristic.
17548 //
17549 // Return Value:
17550 //    A block with the desired characteristics, so the new block will be inserted after this one.
17551 //    If there is no suitable location, return nullptr. This should basically never happen.
17552 //
17553 BasicBlock* Compiler::fgFindInsertPoint(unsigned    regionIndex,
17554                                         bool        putInTryRegion,
17555                                         BasicBlock* startBlk,
17556                                         BasicBlock* endBlk,
17557                                         BasicBlock* nearBlk,
17558                                         BasicBlock* jumpBlk,
17559                                         bool        runRarely)
17560 {
17561     noway_assert(startBlk != nullptr);
17562     noway_assert(startBlk != endBlk);
17563     noway_assert((regionIndex == 0 && putInTryRegion) || // Search in the main method
17564                  (putInTryRegion && regionIndex > 0 &&
17565                   startBlk->bbTryIndex == regionIndex) || // Search in the specified try     region
17566                  (!putInTryRegion && regionIndex > 0 &&
17567                   startBlk->bbHndIndex == regionIndex)); // Search in the specified handler region
17568
17569 #ifdef DEBUG
17570     // Assert that startBlk precedes endBlk in the block list.
17571     // We don't want to use bbNum to assert this condition, as we cannot depend on the block numbers being
17572     // sequential at all times.
17573     for (BasicBlock* b = startBlk; b != endBlk; b = b->bbNext)
17574     {
17575         assert(b != nullptr); // We reached the end of the block list, but never found endBlk.
17576     }
17577 #endif // DEBUG
17578
17579     JITDUMP("fgFindInsertPoint(regionIndex=%u, putInTryRegion=%s, startBlk=BB%02u, endBlk=BB%02u, nearBlk=BB%02u, "
17580             "jumpBlk=BB%02u, runRarely=%s)\n",
17581             regionIndex, dspBool(putInTryRegion), startBlk->bbNum, (endBlk == nullptr) ? 0 : endBlk->bbNum,
17582             (nearBlk == nullptr) ? 0 : nearBlk->bbNum, (jumpBlk == nullptr) ? 0 : jumpBlk->bbNum, dspBool(runRarely));
17583
17584     bool insertingIntoFilter = false;
17585     if (!putInTryRegion)
17586     {
17587         EHblkDsc* const dsc = ehGetDsc(regionIndex - 1);
17588         insertingIntoFilter = dsc->HasFilter() && (startBlk == dsc->ebdFilter) && (endBlk == dsc->ebdHndBeg);
17589     }
17590
17591     bool        reachedNear = false; // Have we reached 'nearBlk' in our search? If not, we'll keep searching.
17592     bool        inFilter    = false; // Are we in a filter region that we need to skip?
17593     BasicBlock* bestBlk =
17594         nullptr; // Set to the best insertion point we've found so far that meets all the EH requirements.
17595     BasicBlock* goodBlk =
17596         nullptr; // Set to an acceptable insertion point that we'll use if we don't find a 'best' option.
17597     BasicBlock* blk;
17598
17599     if (nearBlk != nullptr)
17600     {
17601         // Does the nearBlk precede the startBlk?
17602         for (blk = nearBlk; blk != nullptr; blk = blk->bbNext)
17603         {
17604             if (blk == startBlk)
17605             {
17606                 reachedNear = true;
17607                 break;
17608             }
17609             else if (blk == endBlk)
17610             {
17611                 break;
17612             }
17613         }
17614     }
17615
17616     for (blk = startBlk; blk != endBlk; blk = blk->bbNext)
17617     {
17618         // The only way (blk == nullptr) could be true is if the caller passed an endBlk that preceded startBlk in the
17619         // block list, or if endBlk isn't in the block list at all. In DEBUG, we'll instead hit the similar
17620         // well-formedness assert earlier in this function.
17621         noway_assert(blk != nullptr);
17622
17623         if (blk == nearBlk)
17624         {
17625             reachedNear = true;
17626         }
17627
17628         if (blk->bbCatchTyp == BBCT_FILTER)
17629         {
17630             // Record the fact that we entered a filter region, so we don't insert into filters...
17631             // Unless the caller actually wanted the block inserted in this exact filter region.
17632             if (!insertingIntoFilter || (blk != startBlk))
17633             {
17634                 inFilter = true;
17635             }
17636         }
17637         else if (blk->bbCatchTyp == BBCT_FILTER_HANDLER)
17638         {
17639             // Record the fact that we exited a filter region.
17640             inFilter = false;
17641         }
17642
17643         // Don't insert a block inside this filter region.
17644         if (inFilter)
17645         {
17646             continue;
17647         }
17648
17649         // Note that the new block will be inserted AFTER "blk". We check to make sure that doing so
17650         // would put the block in the correct EH region. We make an assumption here that you can
17651         // ALWAYS insert the new block before "endBlk" (that is, at the end of the search range)
17652         // and be in the correct EH region. This is must be guaranteed by the caller (as it is by
17653         // fgNewBBinRegion(), which passes the search range as an exact EH region block range).
17654         // Because of this assumption, we only check the EH information for blocks before the last block.
17655         if (blk->bbNext != endBlk)
17656         {
17657             // We are in the middle of the search range. We can't insert the new block in
17658             // an inner try or handler region. We can, however, set the insertion
17659             // point to the last block of an EH try/handler region, if the enclosing
17660             // region is the region we wish to insert in. (Since multiple regions can
17661             // end at the same block, we need to search outwards, checking that the
17662             // block is the last block of every EH region out to the region we want
17663             // to insert in.) This is especially useful for putting a call-to-finally
17664             // block on AMD64 immediately after its corresponding 'try' block, so in the
17665             // common case, we'll just fall through to it. For example:
17666             //
17667             //      BB01
17668             //      BB02 -- first block of try
17669             //      BB03
17670             //      BB04 -- last block of try
17671             //      BB05 -- first block of finally
17672             //      BB06
17673             //      BB07 -- last block of handler
17674             //      BB08
17675             //
17676             // Assume there is only one try/finally, so BB01 and BB08 are in the "main function".
17677             // For AMD64 call-to-finally, we'll want to insert the BBJ_CALLFINALLY in
17678             // the main function, immediately after BB04. This allows us to do that.
17679
17680             if (!fgCheckEHCanInsertAfterBlock(blk, regionIndex, putInTryRegion))
17681             {
17682                 // Can't insert here.
17683                 continue;
17684             }
17685         }
17686
17687         // Look for an insert location:
17688         // 1. We want blocks that don't end with a fall through,
17689         // 2. Also, when blk equals nearBlk we may want to insert here.
17690         if (!blk->bbFallsThrough() || (blk == nearBlk))
17691         {
17692             bool updateBestBlk = true; // We will probably update the bestBlk
17693
17694             // If blk falls through then we must decide whether to use the nearBlk
17695             // hint
17696             if (blk->bbFallsThrough())
17697             {
17698                 noway_assert(blk == nearBlk);
17699                 if (jumpBlk != nullptr)
17700                 {
17701                     updateBestBlk = fgIsBetterFallThrough(blk, jumpBlk);
17702                 }
17703                 else
17704                 {
17705                     updateBestBlk = false;
17706                 }
17707             }
17708
17709             // If we already have a best block, see if the 'runRarely' flags influences
17710             // our choice. If we want a runRarely insertion point, and the existing best
17711             // block is run rarely but the current block isn't run rarely, then don't
17712             // update the best block.
17713             // TODO-CQ: We should also handle the reverse case, where runRarely is false (we
17714             // want a non-rarely-run block), but bestBlock->isRunRarely() is true. In that
17715             // case, we should update the block, also. Probably what we want is:
17716             //    (bestBlk->isRunRarely() != runRarely) && (blk->isRunRarely() == runRarely)
17717             if (updateBestBlk && (bestBlk != nullptr) && runRarely && bestBlk->isRunRarely() && !blk->isRunRarely())
17718             {
17719                 updateBestBlk = false;
17720             }
17721
17722             if (updateBestBlk)
17723             {
17724                 // We found a 'best' insertion location, so save it away.
17725                 bestBlk = blk;
17726
17727                 // If we've reached nearBlk, we've satisfied all the criteria,
17728                 // so we're done.
17729                 if (reachedNear)
17730                 {
17731                     goto DONE;
17732                 }
17733
17734                 // If we haven't reached nearBlk, keep looking for a 'best' location, just
17735                 // in case we'll find one at or after nearBlk. If no nearBlk was specified,
17736                 // we prefer inserting towards the end of the given range, so keep looking
17737                 // for more acceptable insertion locations.
17738             }
17739         }
17740
17741         // No need to update goodBlk after we have set bestBlk, but we could still find a better
17742         // bestBlk, so keep looking.
17743         if (bestBlk != nullptr)
17744         {
17745             continue;
17746         }
17747
17748         // Set the current block as a "good enough" insertion point, if it meets certain criteria.
17749         // We'll return this block if we don't find a "best" block in the search range. The block
17750         // can't be a BBJ_CALLFINALLY of a BBJ_CALLFINALLY/BBJ_ALWAYS pair (since we don't want
17751         // to insert anything between these two blocks). Otherwise, we can use it. However,
17752         // if we'd previously chosen a BBJ_COND block, then we'd prefer the "good" block to be
17753         // something else. We keep updating it until we've reached the 'nearBlk', to push it as
17754         // close to endBlk as possible.
17755         if (!blk->isBBCallAlwaysPair())
17756         {
17757             if (goodBlk == nullptr)
17758             {
17759                 goodBlk = blk;
17760             }
17761             else if ((goodBlk->bbJumpKind == BBJ_COND) || (blk->bbJumpKind != BBJ_COND))
17762             {
17763                 if ((blk == nearBlk) || !reachedNear)
17764                 {
17765                     goodBlk = blk;
17766                 }
17767             }
17768         }
17769     }
17770
17771     // If we didn't find a non-fall_through block, then insert at the last good block.
17772
17773     if (bestBlk == nullptr)
17774     {
17775         bestBlk = goodBlk;
17776     }
17777
17778 DONE:
17779
17780 #if defined(JIT32_GCENCODER)
17781     // If we are inserting into a filter and the best block is the end of the filter region, we need to
17782     // insert after its predecessor instead: the JIT32 GC encoding used by the x86 CLR ABI  states that the
17783     // terminal block of a filter region is its exit block. If the filter region consists of a single block,
17784     // a new block cannot be inserted without either splitting the single block before inserting a new block
17785     // or inserting the new block before the single block and updating the filter description such that the
17786     // inserted block is marked as the entry block for the filter. Becuase this sort of split can be complex
17787     // (especially given that it must ensure that the liveness of the exception object is properly tracked),
17788     // we avoid this situation by never generating single-block filters on x86 (see impPushCatchArgOnStack).
17789     if (insertingIntoFilter && (bestBlk == endBlk->bbPrev))
17790     {
17791         assert(bestBlk != startBlk);
17792         bestBlk = bestBlk->bbPrev;
17793     }
17794 #endif // defined(JIT32_GCENCODER)
17795
17796     return bestBlk;
17797 }
17798
17799 //------------------------------------------------------------------------
17800 // Creates a new BasicBlock and inserts it in a specific EH region, given by 'tryIndex', 'hndIndex', and 'putInFilter'.
17801 //
17802 // If 'putInFilter' it true, then the block is inserted in the filter region given by 'hndIndex'. In this case, tryIndex
17803 // must be a less nested EH region (that is, tryIndex > hndIndex).
17804 //
17805 // Otherwise, the block is inserted in either the try region or the handler region, depending on which one is the inner
17806 // region. In other words, if the try region indicated by tryIndex is nested in the handler region indicated by
17807 // hndIndex,
17808 // then the new BB will be created in the try region. Vice versa.
17809 //
17810 // Note that tryIndex and hndIndex are numbered the same as BasicBlock::bbTryIndex and BasicBlock::bbHndIndex, that is,
17811 // "0" is "main method" and otherwise is +1 from normal, so we can call, e.g., ehGetDsc(tryIndex - 1).
17812 //
17813 // To be more specific, this function will create a new BB in one of the following 5 regions (if putInFilter is false):
17814 // 1. When tryIndex = 0 and hndIndex = 0:
17815 //    The new BB will be created in the method region.
17816 // 2. When tryIndex != 0 and hndIndex = 0:
17817 //    The new BB will be created in the try region indicated by tryIndex.
17818 // 3. When tryIndex == 0 and hndIndex != 0:
17819 //    The new BB will be created in the handler region indicated by hndIndex.
17820 // 4. When tryIndex != 0 and hndIndex != 0 and tryIndex < hndIndex:
17821 //    In this case, the try region is nested inside the handler region. Therefore, the new BB will be created
17822 //    in the try region indicated by tryIndex.
17823 // 5. When tryIndex != 0 and hndIndex != 0 and tryIndex > hndIndex:
17824 //    In this case, the handler region is nested inside the try region. Therefore, the new BB will be created
17825 //    in the handler region indicated by hndIndex.
17826 //
17827 // Note that if tryIndex != 0 and hndIndex != 0 then tryIndex must not be equal to hndIndex (this makes sense because
17828 // if they are equal, you are asking to put the new block in both the try and handler, which is impossible).
17829 //
17830 // The BasicBlock will not be inserted inside an EH region that is more nested than the requested tryIndex/hndIndex
17831 // region (so the function is careful to skip more nested EH regions when searching for a place to put the new block).
17832 //
17833 // This function cannot be used to insert a block as the first block of any region. It always inserts a block after
17834 // an existing block in the given region.
17835 //
17836 // If nearBlk is nullptr, or the block is run rarely, then the new block is assumed to be run rarely.
17837 //
17838 // Arguments:
17839 //    jumpKind - the jump kind of the new block to create.
17840 //    tryIndex - the try region to insert the new block in, described above. This must be a number in the range
17841 //               [0..compHndBBtabCount].
17842 //    hndIndex - the handler region to insert the new block in, described above. This must be a number in the range
17843 //               [0..compHndBBtabCount].
17844 //    nearBlk  - insert the new block closely after this block, if possible. If nullptr, put the new block anywhere
17845 //               in the requested region.
17846 //    putInFilter - put the new block in the filter region given by hndIndex, as described above.
17847 //    runRarely - 'true' if the new block is run rarely.
17848 //    insertAtEnd - 'true' if the block should be inserted at the end of the region. Note: this is currently only
17849 //                  implemented when inserting into the main function (not into any EH region).
17850 //
17851 // Return Value:
17852 //    The new block.
17853
17854 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind,
17855                                       unsigned    tryIndex,
17856                                       unsigned    hndIndex,
17857                                       BasicBlock* nearBlk,
17858                                       bool        putInFilter /* = false */,
17859                                       bool        runRarely /* = false */,
17860                                       bool        insertAtEnd /* = false */)
17861 {
17862     assert(tryIndex <= compHndBBtabCount);
17863     assert(hndIndex <= compHndBBtabCount);
17864
17865     /* afterBlk is the block which will precede the newBB */
17866     BasicBlock* afterBlk;
17867
17868     // start and end limit for inserting the block
17869     BasicBlock* startBlk = nullptr;
17870     BasicBlock* endBlk   = nullptr;
17871
17872     bool     putInTryRegion = true;
17873     unsigned regionIndex    = 0;
17874
17875     // First, figure out which region (the "try" region or the "handler" region) to put the newBB in.
17876     if ((tryIndex == 0) && (hndIndex == 0))
17877     {
17878         assert(!putInFilter);
17879
17880         endBlk = fgEndBBAfterMainFunction(); // don't put new BB in funclet region
17881
17882         if (insertAtEnd || (nearBlk == nullptr))
17883         {
17884             /* We'll just insert the block at the end of the method, before the funclets */
17885
17886             afterBlk = fgLastBBInMainFunction();
17887             goto _FoundAfterBlk;
17888         }
17889         else
17890         {
17891             // We'll search through the entire method
17892             startBlk = fgFirstBB;
17893         }
17894
17895         noway_assert(regionIndex == 0);
17896     }
17897     else
17898     {
17899         noway_assert(tryIndex > 0 || hndIndex > 0);
17900         PREFIX_ASSUME(tryIndex <= compHndBBtabCount);
17901         PREFIX_ASSUME(hndIndex <= compHndBBtabCount);
17902
17903         // Decide which region to put in, the "try" region or the "handler" region.
17904         if (tryIndex == 0)
17905         {
17906             noway_assert(hndIndex > 0);
17907             putInTryRegion = false;
17908         }
17909         else if (hndIndex == 0)
17910         {
17911             noway_assert(tryIndex > 0);
17912             noway_assert(putInTryRegion);
17913             assert(!putInFilter);
17914         }
17915         else
17916         {
17917             noway_assert(tryIndex > 0 && hndIndex > 0 && tryIndex != hndIndex);
17918             putInTryRegion = (tryIndex < hndIndex);
17919         }
17920
17921         if (putInTryRegion)
17922         {
17923             // Try region is the inner region.
17924             // In other words, try region must be nested inside the handler region.
17925             noway_assert(hndIndex == 0 || bbInHandlerRegions(hndIndex - 1, ehGetDsc(tryIndex - 1)->ebdTryBeg));
17926             assert(!putInFilter);
17927         }
17928         else
17929         {
17930             // Handler region is the inner region.
17931             // In other words, handler region must be nested inside the try region.
17932             noway_assert(tryIndex == 0 || bbInTryRegions(tryIndex - 1, ehGetDsc(hndIndex - 1)->ebdHndBeg));
17933         }
17934
17935         // Figure out the start and end block range to search for an insertion location. Pick the beginning and
17936         // ending blocks of the target EH region (the 'endBlk' is one past the last block of the EH region, to make
17937         // loop iteration easier). Note that, after funclets have been created (for FEATURE_EH_FUNCLETS),
17938         // this linear block range will not include blocks of handlers for try/handler clauses nested within
17939         // this EH region, as those blocks have been extracted as funclets. That is ok, though, because we don't
17940         // want to insert a block in any nested EH region.
17941
17942         if (putInTryRegion)
17943         {
17944             // We will put the newBB in the try region.
17945             EHblkDsc* ehDsc = ehGetDsc(tryIndex - 1);
17946             startBlk        = ehDsc->ebdTryBeg;
17947             endBlk          = ehDsc->ebdTryLast->bbNext;
17948             regionIndex     = tryIndex;
17949         }
17950         else if (putInFilter)
17951         {
17952             // We will put the newBB in the filter region.
17953             EHblkDsc* ehDsc = ehGetDsc(hndIndex - 1);
17954             startBlk        = ehDsc->ebdFilter;
17955             endBlk          = ehDsc->ebdHndBeg;
17956             regionIndex     = hndIndex;
17957         }
17958         else
17959         {
17960             // We will put the newBB in the handler region.
17961             EHblkDsc* ehDsc = ehGetDsc(hndIndex - 1);
17962             startBlk        = ehDsc->ebdHndBeg;
17963             endBlk          = ehDsc->ebdHndLast->bbNext;
17964             regionIndex     = hndIndex;
17965         }
17966
17967         noway_assert(regionIndex > 0);
17968     }
17969
17970     // Now find the insertion point.
17971     afterBlk = fgFindInsertPoint(regionIndex, putInTryRegion, startBlk, endBlk, nearBlk, nullptr, runRarely);
17972
17973 _FoundAfterBlk:;
17974
17975     /* We have decided to insert the block after 'afterBlk'. */
17976     noway_assert(afterBlk != nullptr);
17977
17978     JITDUMP("fgNewBBinRegion(jumpKind=%u, tryIndex=%u, hndIndex=%u, putInFilter=%s, runRarely=%s, insertAtEnd=%s): "
17979             "inserting after BB%02u\n",
17980             jumpKind, tryIndex, hndIndex, dspBool(putInFilter), dspBool(runRarely), dspBool(insertAtEnd),
17981             afterBlk->bbNum);
17982
17983     return fgNewBBinRegionWorker(jumpKind, afterBlk, regionIndex, putInTryRegion);
17984 }
17985
17986 //------------------------------------------------------------------------
17987 // Creates a new BasicBlock and inserts it in the same EH region as 'srcBlk'.
17988 //
17989 // See the implementation of fgNewBBinRegion() used by this one for more notes.
17990 //
17991 // Arguments:
17992 //    jumpKind - the jump kind of the new block to create.
17993 //    srcBlk   - insert the new block in the same EH region as this block, and closely after it if possible.
17994 //
17995 // Return Value:
17996 //    The new block.
17997
17998 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind,
17999                                       BasicBlock* srcBlk,
18000                                       bool        runRarely /* = false */,
18001                                       bool        insertAtEnd /* = false */)
18002 {
18003     assert(srcBlk != nullptr);
18004
18005     const unsigned tryIndex    = srcBlk->bbTryIndex;
18006     const unsigned hndIndex    = srcBlk->bbHndIndex;
18007     bool           putInFilter = false;
18008
18009     // Check to see if we need to put the new block in a filter. We do if srcBlk is in a filter.
18010     // This can only be true if there is a handler index, and the handler region is more nested than the
18011     // try region (if any). This is because no EH regions can be nested within a filter.
18012     if (BasicBlock::ehIndexMaybeMoreNested(hndIndex, tryIndex))
18013     {
18014         assert(hndIndex != 0); // If hndIndex is more nested, we must be in some handler!
18015         putInFilter = ehGetDsc(hndIndex - 1)->InFilterRegionBBRange(srcBlk);
18016     }
18017
18018     return fgNewBBinRegion(jumpKind, tryIndex, hndIndex, srcBlk, putInFilter, runRarely, insertAtEnd);
18019 }
18020
18021 //------------------------------------------------------------------------
18022 // Creates a new BasicBlock and inserts it at the end of the function.
18023 //
18024 // See the implementation of fgNewBBinRegion() used by this one for more notes.
18025 //
18026 // Arguments:
18027 //    jumpKind - the jump kind of the new block to create.
18028 //
18029 // Return Value:
18030 //    The new block.
18031
18032 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind)
18033 {
18034     return fgNewBBinRegion(jumpKind, 0, 0, nullptr, /* putInFilter */ false, /* runRarely */ false,
18035                            /* insertAtEnd */ true);
18036 }
18037
18038 //------------------------------------------------------------------------
18039 // Creates a new BasicBlock, and inserts it after 'afterBlk'.
18040 //
18041 // The block cannot be inserted into a more nested try/handler region than that specified by 'regionIndex'.
18042 // (It is given exactly 'regionIndex'.) Thus, the parameters must be passed to ensure proper EH nesting
18043 // rules are followed.
18044 //
18045 // Arguments:
18046 //    jumpKind - the jump kind of the new block to create.
18047 //    afterBlk - insert the new block after this one.
18048 //    regionIndex - the block will be put in this EH region.
18049 //    putInTryRegion - If true, put the new block in the 'try' region corresponding to 'regionIndex', and
18050 //          set its handler index to the most nested handler region enclosing that 'try' region.
18051 //          Otherwise, put the block in the handler region specified by 'regionIndex', and set its 'try'
18052 //          index to the most nested 'try' region enclosing that handler region.
18053 //
18054 // Return Value:
18055 //    The new block.
18056
18057 BasicBlock* Compiler::fgNewBBinRegionWorker(BBjumpKinds jumpKind,
18058                                             BasicBlock* afterBlk,
18059                                             unsigned    regionIndex,
18060                                             bool        putInTryRegion)
18061 {
18062     /* Insert the new block */
18063     BasicBlock* afterBlkNext = afterBlk->bbNext;
18064     (void)afterBlkNext; // prevent "unused variable" error from GCC
18065     BasicBlock* newBlk = fgNewBBafter(jumpKind, afterBlk, false);
18066
18067     if (putInTryRegion)
18068     {
18069         noway_assert(regionIndex <= MAX_XCPTN_INDEX);
18070         newBlk->bbTryIndex = (unsigned short)regionIndex;
18071         newBlk->bbHndIndex = bbFindInnermostHandlerRegionContainingTryRegion(regionIndex);
18072     }
18073     else
18074     {
18075         newBlk->bbTryIndex = bbFindInnermostTryRegionContainingHandlerRegion(regionIndex);
18076         noway_assert(regionIndex <= MAX_XCPTN_INDEX);
18077         newBlk->bbHndIndex = (unsigned short)regionIndex;
18078     }
18079
18080     // We're going to compare for equal try regions (to handle the case of 'mutually protect'
18081     // regions). We need to save off the current try region, otherwise we might change it
18082     // before it gets compared later, thereby making future comparisons fail.
18083
18084     BasicBlock* newTryBeg;
18085     BasicBlock* newTryLast;
18086     (void)ehInitTryBlockRange(newBlk, &newTryBeg, &newTryLast);
18087
18088     unsigned  XTnum;
18089     EHblkDsc* HBtab;
18090
18091     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
18092     {
18093         // Is afterBlk at the end of a try region?
18094         if (HBtab->ebdTryLast == afterBlk)
18095         {
18096             noway_assert(afterBlkNext == newBlk->bbNext);
18097
18098             bool extendTryRegion = false;
18099             if (newBlk->hasTryIndex())
18100             {
18101                 // We're adding a block after the last block of some try region. Do
18102                 // we extend the try region to include the block, or not?
18103                 // If the try region is exactly the same as the try region
18104                 // associated with the new block (based on the block's try index,
18105                 // which represents the innermost try the block is a part of), then
18106                 // we extend it.
18107                 // If the try region is a "parent" try region -- an enclosing try region
18108                 // that has the same last block as the new block's try region -- then
18109                 // we also extend. For example:
18110                 //      try { // 1
18111                 //          ...
18112                 //          try { // 2
18113                 //          ...
18114                 //      } /* 2 */ } /* 1 */
18115                 // This example is meant to indicate that both try regions 1 and 2 end at
18116                 // the same block, and we're extending 2. Thus, we must also extend 1. If we
18117                 // only extended 2, we would break proper nesting. (Dev11 bug 137967)
18118
18119                 extendTryRegion = HBtab->ebdIsSameTry(newTryBeg, newTryLast) || bbInTryRegions(XTnum, newBlk);
18120             }
18121
18122             // Does newBlk extend this try region?
18123             if (extendTryRegion)
18124             {
18125                 // Yes, newBlk extends this try region
18126
18127                 // newBlk is the now the new try last block
18128                 fgSetTryEnd(HBtab, newBlk);
18129             }
18130         }
18131
18132         // Is afterBlk at the end of a handler region?
18133         if (HBtab->ebdHndLast == afterBlk)
18134         {
18135             noway_assert(afterBlkNext == newBlk->bbNext);
18136
18137             // Does newBlk extend this handler region?
18138             bool extendHndRegion = false;
18139             if (newBlk->hasHndIndex())
18140             {
18141                 // We're adding a block after the last block of some handler region. Do
18142                 // we extend the handler region to include the block, or not?
18143                 // If the handler region is exactly the same as the handler region
18144                 // associated with the new block (based on the block's handler index,
18145                 // which represents the innermost handler the block is a part of), then
18146                 // we extend it.
18147                 // If the handler region is a "parent" handler region -- an enclosing
18148                 // handler region that has the same last block as the new block's handler
18149                 // region -- then we also extend. For example:
18150                 //      catch { // 1
18151                 //          ...
18152                 //          catch { // 2
18153                 //          ...
18154                 //      } /* 2 */ } /* 1 */
18155                 // This example is meant to indicate that both handler regions 1 and 2 end at
18156                 // the same block, and we're extending 2. Thus, we must also extend 1. If we
18157                 // only extended 2, we would break proper nesting. (Dev11 bug 372051)
18158
18159                 extendHndRegion = bbInHandlerRegions(XTnum, newBlk);
18160             }
18161
18162             if (extendHndRegion)
18163             {
18164                 // Yes, newBlk extends this handler region
18165
18166                 // newBlk is now the last block of the handler.
18167                 fgSetHndEnd(HBtab, newBlk);
18168             }
18169         }
18170     }
18171
18172     /* If afterBlk falls through, we insert a jump around newBlk */
18173     fgConnectFallThrough(afterBlk, newBlk->bbNext);
18174
18175 #ifdef DEBUG
18176     fgVerifyHandlerTab();
18177 #endif
18178
18179     return newBlk;
18180 }
18181
18182 /*****************************************************************************
18183  */
18184
18185 /* static */
18186 unsigned Compiler::acdHelper(SpecialCodeKind codeKind)
18187 {
18188     switch (codeKind)
18189     {
18190         case SCK_RNGCHK_FAIL:
18191             return CORINFO_HELP_RNGCHKFAIL;
18192         case SCK_ARG_EXCPN:
18193             return CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
18194         case SCK_ARG_RNG_EXCPN:
18195             return CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
18196         case SCK_DIV_BY_ZERO:
18197             return CORINFO_HELP_THROWDIVZERO;
18198         case SCK_ARITH_EXCPN:
18199             return CORINFO_HELP_OVERFLOW;
18200         default:
18201             assert(!"Bad codeKind");
18202             return 0;
18203     }
18204 }
18205
18206 /*****************************************************************************
18207  *
18208  *  Find/create an added code entry associated with the given block and with
18209  *  the given kind.
18210  */
18211
18212 BasicBlock* Compiler::fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, SpecialCodeKind kind, unsigned stkDepth)
18213 {
18214     // Record that the code will call a THROW_HELPER
18215     // so on Windows Amd64 we can allocate the 4 outgoing
18216     // arg slots on the stack frame if there are no other calls.
18217     compUsesThrowHelper = true;
18218
18219     if (!fgUseThrowHelperBlocks())
18220     {
18221         return nullptr;
18222     }
18223
18224     const static BBjumpKinds jumpKinds[] = {
18225         BBJ_NONE,   // SCK_NONE
18226         BBJ_THROW,  // SCK_RNGCHK_FAIL
18227         BBJ_ALWAYS, // SCK_PAUSE_EXEC
18228         BBJ_THROW,  // SCK_DIV_BY_ZERO
18229         BBJ_THROW,  // SCK_ARITH_EXCP, SCK_OVERFLOW
18230         BBJ_THROW,  // SCK_ARG_EXCPN
18231         BBJ_THROW,  // SCK_ARG_RNG_EXCPN
18232     };
18233
18234     noway_assert(sizeof(jumpKinds) == SCK_COUNT); // sanity check
18235
18236     /* First look for an existing entry that matches what we're looking for */
18237
18238     AddCodeDsc* add = fgFindExcptnTarget(kind, refData);
18239
18240     if (add) // found it
18241     {
18242 #if !FEATURE_FIXED_OUT_ARGS
18243         // If different range checks happen at different stack levels,
18244         // they can't all jump to the same "call @rngChkFailed" AND have
18245         // frameless methods, as the rngChkFailed may need to unwind the
18246         // stack, and we have to be able to report the stack level.
18247         //
18248         // The following check forces most methods that reference an
18249         // array element in a parameter list to have an EBP frame,
18250         // this restriction could be removed with more careful code
18251         // generation for BBJ_THROW (i.e. range check failed).
18252         //
18253         // For Linux/x86, we possibly need to insert stack alignment adjustment
18254         // before the first stack argument pushed for every call. But we
18255         // don't know what the stack alignment adjustment will be when
18256         // we morph a tree that calls fgAddCodeRef(), so the stack depth
18257         // number will be incorrect. For now, simply force all functions with
18258         // these helpers to have EBP frames. It might be possible to make
18259         // this less conservative. E.g., for top-level (not nested) calls
18260         // without stack args, the stack pointer hasn't changed and stack
18261         // depth will be known to be zero. Or, figure out a way to update
18262         // or generate all required helpers after all stack alignment
18263         // has been added, and the stack level at each call to fgAddCodeRef()
18264         // is known, or can be recalculated.
18265         CLANG_FORMAT_COMMENT_ANCHOR;
18266
18267 #if defined(UNIX_X86_ABI)
18268         codeGen->setFrameRequired(true);
18269         codeGen->setFramePointerRequiredGCInfo(true);
18270 #else  // !defined(UNIX_X86_ABI)
18271         if (add->acdStkLvl != stkDepth)
18272         {
18273             codeGen->setFrameRequired(true);
18274             codeGen->setFramePointerRequiredGCInfo(true);
18275         }
18276 #endif // !defined(UNIX_X86_ABI)
18277 #endif // !FEATURE_FIXED_OUT_ARGS
18278
18279         return add->acdDstBlk;
18280     }
18281
18282     /* We have to allocate a new entry and prepend it to the list */
18283
18284     add          = new (this, CMK_Unknown) AddCodeDsc;
18285     add->acdData = refData;
18286     add->acdKind = kind;
18287     add->acdNext = fgAddCodeList;
18288 #if !FEATURE_FIXED_OUT_ARGS
18289     add->acdStkLvl     = stkDepth;
18290     add->acdStkLvlInit = false;
18291 #endif // !FEATURE_FIXED_OUT_ARGS
18292
18293     fgAddCodeList = add;
18294
18295     /* Create the target basic block */
18296
18297     BasicBlock* newBlk;
18298
18299     newBlk = add->acdDstBlk = fgNewBBinRegion(jumpKinds[kind], srcBlk, /* runRarely */ true, /* insertAtEnd */ true);
18300
18301     add->acdDstBlk->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
18302
18303 #ifdef DEBUG
18304     if (verbose)
18305     {
18306         const char* msgWhere = "";
18307         if (!srcBlk->hasTryIndex() && !srcBlk->hasHndIndex())
18308         {
18309             msgWhere = "non-EH region";
18310         }
18311         else if (!srcBlk->hasTryIndex())
18312         {
18313             msgWhere = "handler";
18314         }
18315         else if (!srcBlk->hasHndIndex())
18316         {
18317             msgWhere = "try";
18318         }
18319         else if (srcBlk->getTryIndex() < srcBlk->getHndIndex())
18320         {
18321             msgWhere = "try";
18322         }
18323         else
18324         {
18325             msgWhere = "handler";
18326         }
18327
18328         const char* msg;
18329         switch (kind)
18330         {
18331             case SCK_RNGCHK_FAIL:
18332                 msg = " for RNGCHK_FAIL";
18333                 break;
18334             case SCK_PAUSE_EXEC:
18335                 msg = " for PAUSE_EXEC";
18336                 break;
18337             case SCK_DIV_BY_ZERO:
18338                 msg = " for DIV_BY_ZERO";
18339                 break;
18340             case SCK_OVERFLOW:
18341                 msg = " for OVERFLOW";
18342                 break;
18343             case SCK_ARG_EXCPN:
18344                 msg = " for ARG_EXCPN";
18345                 break;
18346             case SCK_ARG_RNG_EXCPN:
18347                 msg = " for ARG_RNG_EXCPN";
18348                 break;
18349             default:
18350                 msg = " for ??";
18351                 break;
18352         }
18353
18354         printf("\nfgAddCodeRef - Add BB in %s%s, new block %s, stkDepth is %d\n", msgWhere, msg,
18355                add->acdDstBlk->dspToString(), stkDepth);
18356     }
18357 #endif // DEBUG
18358
18359 #ifdef DEBUG
18360     newBlk->bbTgtStkDepth = stkDepth;
18361 #endif // DEBUG
18362
18363     /* Mark the block as added by the compiler and not removable by future flow
18364        graph optimizations. Note that no bbJumpDest points to these blocks. */
18365
18366     newBlk->bbFlags |= BBF_IMPORTED;
18367     newBlk->bbFlags |= BBF_DONT_REMOVE;
18368
18369     /* Remember that we're adding a new basic block */
18370
18371     fgAddCodeModf      = true;
18372     fgRngChkThrowAdded = true;
18373
18374     /* Now figure out what code to insert */
18375
18376     GenTreeCall* tree;
18377     int          helper = CORINFO_HELP_UNDEF;
18378
18379     switch (kind)
18380     {
18381         case SCK_RNGCHK_FAIL:
18382             helper = CORINFO_HELP_RNGCHKFAIL;
18383             break;
18384
18385         case SCK_DIV_BY_ZERO:
18386             helper = CORINFO_HELP_THROWDIVZERO;
18387             break;
18388
18389         case SCK_ARITH_EXCPN:
18390             helper = CORINFO_HELP_OVERFLOW;
18391             noway_assert(SCK_OVERFLOW == SCK_ARITH_EXCPN);
18392             break;
18393
18394         case SCK_ARG_EXCPN:
18395             helper = CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
18396             break;
18397
18398         case SCK_ARG_RNG_EXCPN:
18399             helper = CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
18400             break;
18401
18402         // case SCK_PAUSE_EXEC:
18403         //     noway_assert(!"add code to pause exec");
18404
18405         default:
18406             noway_assert(!"unexpected code addition kind");
18407             return nullptr;
18408     }
18409
18410     noway_assert(helper != CORINFO_HELP_UNDEF);
18411
18412     // Add the appropriate helper call.
18413     tree = gtNewHelperCallNode(helper, TYP_VOID);
18414
18415     // There are no args here but fgMorphArgs has side effects
18416     // such as setting the outgoing arg area (which is necessary
18417     // on AMD if there are any calls).
18418     tree = fgMorphArgs(tree);
18419
18420     // Store the tree in the new basic block.
18421     assert(!srcBlk->isEmpty());
18422     if (!srcBlk->IsLIR())
18423     {
18424         fgInsertStmtAtEnd(newBlk, fgNewStmtFromTree(tree));
18425     }
18426     else
18427     {
18428         LIR::AsRange(newBlk).InsertAtEnd(LIR::SeqTree(this, tree));
18429     }
18430
18431     return add->acdDstBlk;
18432 }
18433
18434 /*****************************************************************************
18435  * Finds the block to jump to, to throw a given kind of exception
18436  * We maintain a cache of one AddCodeDsc for each kind, to make searching fast.
18437  * Note : Each block uses the same (maybe shared) block as the jump target for
18438  * a given type of exception
18439  */
18440
18441 Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData)
18442 {
18443     assert(fgUseThrowHelperBlocks());
18444     if (!(fgExcptnTargetCache[kind] && // Try the cached value first
18445           fgExcptnTargetCache[kind]->acdData == refData))
18446     {
18447         // Too bad, have to search for the jump target for the exception
18448
18449         AddCodeDsc* add = nullptr;
18450
18451         for (add = fgAddCodeList; add != nullptr; add = add->acdNext)
18452         {
18453             if (add->acdData == refData && add->acdKind == kind)
18454             {
18455                 break;
18456             }
18457         }
18458
18459         fgExcptnTargetCache[kind] = add; // Cache it
18460     }
18461
18462     return fgExcptnTargetCache[kind];
18463 }
18464
18465 /*****************************************************************************
18466  *
18467  *  The given basic block contains an array range check; return the label this
18468  *  range check is to jump to upon failure.
18469  */
18470
18471 BasicBlock* Compiler::fgRngChkTarget(BasicBlock* block, unsigned stkDepth, SpecialCodeKind kind)
18472 {
18473 #ifdef DEBUG
18474     if (verbose)
18475     {
18476         printf("*** Computing fgRngChkTarget for block BB%02u to stkDepth %d\n", block->bbNum, stkDepth);
18477         if (!block->IsLIR())
18478         {
18479             gtDispTree(compCurStmt);
18480         }
18481     }
18482 #endif // DEBUG
18483
18484     /* We attach the target label to the containing try block (if any) */
18485     noway_assert(!compIsForInlining());
18486     return fgAddCodeRef(block, bbThrowIndex(block), kind, stkDepth);
18487 }
18488
18489 // Sequences the tree.
18490 // prevTree is what gtPrev of the first node in execution order gets set to.
18491 // Returns the first node (execution order) in the sequenced tree.
18492 GenTree* Compiler::fgSetTreeSeq(GenTree* tree, GenTree* prevTree, bool isLIR)
18493 {
18494     GenTree list;
18495
18496     if (prevTree == nullptr)
18497     {
18498         prevTree = &list;
18499     }
18500     fgTreeSeqLst = prevTree;
18501     fgTreeSeqNum = 0;
18502     fgTreeSeqBeg = nullptr;
18503     fgSetTreeSeqHelper(tree, isLIR);
18504
18505     GenTree* result = prevTree->gtNext;
18506     if (prevTree == &list)
18507     {
18508         list.gtNext->gtPrev = nullptr;
18509     }
18510
18511     return result;
18512 }
18513
18514 /*****************************************************************************
18515  *
18516  *  Assigns sequence numbers to the given tree and its sub-operands, and
18517  *  threads all the nodes together via the 'gtNext' and 'gtPrev' fields.
18518  *  Uses 'global' - fgTreeSeqLst
18519  */
18520
18521 void Compiler::fgSetTreeSeqHelper(GenTree* tree, bool isLIR)
18522 {
18523     genTreeOps oper;
18524     unsigned   kind;
18525
18526     noway_assert(tree);
18527     assert(!IsUninitialized(tree));
18528     noway_assert(tree->gtOper != GT_STMT);
18529
18530     /* Figure out what kind of a node we have */
18531
18532     oper = tree->OperGet();
18533     kind = tree->OperKind();
18534
18535     /* Is this a leaf/constant node? */
18536
18537     if (kind & (GTK_CONST | GTK_LEAF))
18538     {
18539         fgSetTreeSeqFinish(tree, isLIR);
18540         return;
18541     }
18542
18543     // Special handling for dynamic block ops.
18544     if (tree->OperIsDynBlkOp())
18545     {
18546         GenTreeDynBlk* dynBlk;
18547         GenTree*       src;
18548         GenTree*       asg = tree;
18549         if (tree->OperGet() == GT_ASG)
18550         {
18551             dynBlk = tree->gtGetOp1()->AsDynBlk();
18552             src    = tree->gtGetOp2();
18553         }
18554         else
18555         {
18556             dynBlk = tree->AsDynBlk();
18557             src    = dynBlk->Data();
18558             asg    = nullptr;
18559         }
18560         GenTree* sizeNode = dynBlk->gtDynamicSize;
18561         GenTree* dstAddr  = dynBlk->Addr();
18562         if (dynBlk->gtEvalSizeFirst)
18563         {
18564             fgSetTreeSeqHelper(sizeNode, isLIR);
18565         }
18566         if (tree->gtFlags & GTF_REVERSE_OPS)
18567         {
18568             fgSetTreeSeqHelper(src, isLIR);
18569             fgSetTreeSeqHelper(dstAddr, isLIR);
18570         }
18571         else
18572         {
18573             fgSetTreeSeqHelper(dstAddr, isLIR);
18574             fgSetTreeSeqHelper(src, isLIR);
18575         }
18576         if (!dynBlk->gtEvalSizeFirst)
18577         {
18578             fgSetTreeSeqHelper(sizeNode, isLIR);
18579         }
18580         fgSetTreeSeqFinish(dynBlk, isLIR);
18581         if (asg != nullptr)
18582         {
18583             fgSetTreeSeqFinish(asg, isLIR);
18584         }
18585         return;
18586     }
18587
18588     /* Is it a 'simple' unary/binary operator? */
18589
18590     if (kind & GTK_SMPOP)
18591     {
18592         GenTree* op1 = tree->gtOp.gtOp1;
18593         GenTree* op2 = tree->gtGetOp2IfPresent();
18594
18595         // Special handling for GT_LIST
18596         if (tree->OperGet() == GT_LIST)
18597         {
18598             // First, handle the list items, which will be linked in forward order.
18599             // As we go, we will link the GT_LIST nodes in reverse order - we will number
18600             // them and update fgTreeSeqList in a subsequent traversal.
18601             GenTree* nextList = tree;
18602             GenTree* list     = nullptr;
18603             while (nextList != nullptr && nextList->OperGet() == GT_LIST)
18604             {
18605                 list              = nextList;
18606                 GenTree* listItem = list->gtOp.gtOp1;
18607                 fgSetTreeSeqHelper(listItem, isLIR);
18608                 nextList = list->gtOp.gtOp2;
18609                 if (nextList != nullptr)
18610                 {
18611                     nextList->gtNext = list;
18612                 }
18613                 list->gtPrev = nextList;
18614             }
18615             // Next, handle the GT_LIST nodes.
18616             // Note that fgSetTreeSeqFinish() sets the gtNext to null, so we need to capture the nextList
18617             // before we call that method.
18618             nextList = list;
18619             do
18620             {
18621                 assert(list != nullptr);
18622                 list     = nextList;
18623                 nextList = list->gtNext;
18624                 fgSetTreeSeqFinish(list, isLIR);
18625             } while (list != tree);
18626             return;
18627         }
18628
18629         /* Special handling for AddrMode */
18630         if (tree->OperIsAddrMode())
18631         {
18632             bool reverse = ((tree->gtFlags & GTF_REVERSE_OPS) != 0);
18633             if (reverse)
18634             {
18635                 assert(op1 != nullptr && op2 != nullptr);
18636                 fgSetTreeSeqHelper(op2, isLIR);
18637             }
18638             if (op1 != nullptr)
18639             {
18640                 fgSetTreeSeqHelper(op1, isLIR);
18641             }
18642             if (!reverse && op2 != nullptr)
18643             {
18644                 fgSetTreeSeqHelper(op2, isLIR);
18645             }
18646
18647             fgSetTreeSeqFinish(tree, isLIR);
18648             return;
18649         }
18650
18651         /* Check for a nilary operator */
18652
18653         if (op1 == nullptr)
18654         {
18655             noway_assert(op2 == nullptr);
18656             fgSetTreeSeqFinish(tree, isLIR);
18657             return;
18658         }
18659
18660         /* Is this a unary operator?
18661          * Although UNARY GT_IND has a special structure */
18662
18663         if (oper == GT_IND)
18664         {
18665             /* Visit the indirection first - op2 may point to the
18666              * jump Label for array-index-out-of-range */
18667
18668             fgSetTreeSeqHelper(op1, isLIR);
18669             fgSetTreeSeqFinish(tree, isLIR);
18670             return;
18671         }
18672
18673         /* Now this is REALLY a unary operator */
18674
18675         if (!op2)
18676         {
18677             /* Visit the (only) operand and we're done */
18678
18679             fgSetTreeSeqHelper(op1, isLIR);
18680             fgSetTreeSeqFinish(tree, isLIR);
18681             return;
18682         }
18683
18684         /*
18685            For "real" ?: operators, we make sure the order is
18686            as follows:
18687
18688                condition
18689                1st operand
18690                GT_COLON
18691                2nd operand
18692                GT_QMARK
18693         */
18694
18695         if (oper == GT_QMARK)
18696         {
18697             noway_assert((tree->gtFlags & GTF_REVERSE_OPS) == 0);
18698
18699             fgSetTreeSeqHelper(op1, isLIR);
18700             // Here, for the colon, the sequence does not actually represent "order of evaluation":
18701             // one or the other of the branches is executed, not both.  Still, to make debugging checks
18702             // work, we want the sequence to match the order in which we'll generate code, which means
18703             // "else" clause then "then" clause.
18704             fgSetTreeSeqHelper(op2->AsColon()->ElseNode(), isLIR);
18705             fgSetTreeSeqHelper(op2, isLIR);
18706             fgSetTreeSeqHelper(op2->AsColon()->ThenNode(), isLIR);
18707
18708             fgSetTreeSeqFinish(tree, isLIR);
18709             return;
18710         }
18711
18712         if (oper == GT_COLON)
18713         {
18714             fgSetTreeSeqFinish(tree, isLIR);
18715             return;
18716         }
18717
18718         /* This is a binary operator */
18719
18720         if (tree->gtFlags & GTF_REVERSE_OPS)
18721         {
18722             fgSetTreeSeqHelper(op2, isLIR);
18723             fgSetTreeSeqHelper(op1, isLIR);
18724         }
18725         else
18726         {
18727             fgSetTreeSeqHelper(op1, isLIR);
18728             fgSetTreeSeqHelper(op2, isLIR);
18729         }
18730
18731         fgSetTreeSeqFinish(tree, isLIR);
18732         return;
18733     }
18734
18735     /* See what kind of a special operator we have here */
18736
18737     switch (oper)
18738     {
18739         case GT_FIELD:
18740             noway_assert(tree->gtField.gtFldObj == nullptr);
18741             break;
18742
18743         case GT_CALL:
18744
18745             /* We'll evaluate the 'this' argument value first */
18746             if (tree->gtCall.gtCallObjp)
18747             {
18748                 fgSetTreeSeqHelper(tree->gtCall.gtCallObjp, isLIR);
18749             }
18750
18751             /* We'll evaluate the arguments next, left to right
18752              * NOTE: setListOrder needs cleanup - eliminate the #ifdef afterwards */
18753
18754             if (tree->gtCall.gtCallArgs)
18755             {
18756                 fgSetTreeSeqHelper(tree->gtCall.gtCallArgs, isLIR);
18757             }
18758
18759             /* Evaluate the temp register arguments list
18760              * This is a "hidden" list and its only purpose is to
18761              * extend the life of temps until we make the call */
18762
18763             if (tree->gtCall.gtCallLateArgs)
18764             {
18765                 fgSetTreeSeqHelper(tree->gtCall.gtCallLateArgs, isLIR);
18766             }
18767
18768             if ((tree->gtCall.gtCallType == CT_INDIRECT) && (tree->gtCall.gtCallCookie != nullptr))
18769             {
18770                 fgSetTreeSeqHelper(tree->gtCall.gtCallCookie, isLIR);
18771             }
18772
18773             if (tree->gtCall.gtCallType == CT_INDIRECT)
18774             {
18775                 fgSetTreeSeqHelper(tree->gtCall.gtCallAddr, isLIR);
18776             }
18777
18778             if (tree->gtCall.gtControlExpr)
18779             {
18780                 fgSetTreeSeqHelper(tree->gtCall.gtControlExpr, isLIR);
18781             }
18782
18783             break;
18784
18785         case GT_ARR_ELEM:
18786
18787             fgSetTreeSeqHelper(tree->gtArrElem.gtArrObj, isLIR);
18788
18789             unsigned dim;
18790             for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
18791             {
18792                 fgSetTreeSeqHelper(tree->gtArrElem.gtArrInds[dim], isLIR);
18793             }
18794
18795             break;
18796
18797         case GT_ARR_OFFSET:
18798             fgSetTreeSeqHelper(tree->gtArrOffs.gtOffset, isLIR);
18799             fgSetTreeSeqHelper(tree->gtArrOffs.gtIndex, isLIR);
18800             fgSetTreeSeqHelper(tree->gtArrOffs.gtArrObj, isLIR);
18801             break;
18802
18803         case GT_CMPXCHG:
18804             // Evaluate the trees left to right
18805             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpLocation, isLIR);
18806             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpValue, isLIR);
18807             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpComparand, isLIR);
18808             break;
18809
18810         case GT_ARR_BOUNDS_CHECK:
18811 #ifdef FEATURE_SIMD
18812         case GT_SIMD_CHK:
18813 #endif // FEATURE_SIMD
18814 #ifdef FEATURE_HW_INTRINSICS
18815         case GT_HW_INTRINSIC_CHK:
18816 #endif // FEATURE_HW_INTRINSICS
18817             // Evaluate the trees left to right
18818             fgSetTreeSeqHelper(tree->gtBoundsChk.gtIndex, isLIR);
18819             fgSetTreeSeqHelper(tree->gtBoundsChk.gtArrLen, isLIR);
18820             break;
18821
18822         case GT_STORE_DYN_BLK:
18823         case GT_DYN_BLK:
18824             noway_assert(!"DYN_BLK nodes should be sequenced as a special case");
18825             break;
18826
18827         case GT_INDEX_ADDR:
18828             // Evaluate the index first, then the array address
18829             assert((tree->gtFlags & GTF_REVERSE_OPS) != 0);
18830             fgSetTreeSeqHelper(tree->AsIndexAddr()->Index(), isLIR);
18831             fgSetTreeSeqHelper(tree->AsIndexAddr()->Arr(), isLIR);
18832             break;
18833
18834         default:
18835 #ifdef DEBUG
18836             gtDispTree(tree);
18837             noway_assert(!"unexpected operator");
18838 #endif // DEBUG
18839             break;
18840     }
18841
18842     fgSetTreeSeqFinish(tree, isLIR);
18843 }
18844
18845 void Compiler::fgSetTreeSeqFinish(GenTree* tree, bool isLIR)
18846 {
18847     // If we are sequencing for LIR:
18848     // - Clear the reverse ops flag
18849     // - If we are processing a node that does not appear in LIR, do not add it to the list.
18850     if (isLIR)
18851     {
18852         tree->gtFlags &= ~GTF_REVERSE_OPS;
18853
18854         if ((tree->OperGet() == GT_LIST) || (tree->OperGet() == GT_ARGPLACE) ||
18855             (tree->OperGet() == GT_FIELD_LIST && !tree->AsFieldList()->IsFieldListHead()))
18856         {
18857             return;
18858         }
18859     }
18860
18861     /* Append to the node list */
18862     ++fgTreeSeqNum;
18863
18864 #ifdef DEBUG
18865     tree->gtSeqNum = fgTreeSeqNum;
18866
18867     if (verbose & 0)
18868     {
18869         printf("SetTreeOrder: ");
18870         printTreeID(fgTreeSeqLst);
18871         printf(" followed by ");
18872         printTreeID(tree);
18873         printf("\n");
18874     }
18875 #endif // DEBUG
18876
18877     fgTreeSeqLst->gtNext = tree;
18878     tree->gtNext         = nullptr;
18879     tree->gtPrev         = fgTreeSeqLst;
18880     fgTreeSeqLst         = tree;
18881
18882     /* Remember the very first node */
18883
18884     if (!fgTreeSeqBeg)
18885     {
18886         fgTreeSeqBeg = tree;
18887         assert(tree->gtSeqNum == 1);
18888     }
18889 }
18890
18891 /*****************************************************************************
18892  *
18893  *  Figure out the order in which operators should be evaluated, along with
18894  *  other information (such as the register sets trashed by each subtree).
18895  *  Also finds blocks that need GC polls and inserts them as needed.
18896  */
18897
18898 void Compiler::fgSetBlockOrder()
18899 {
18900 #ifdef DEBUG
18901     if (verbose)
18902     {
18903         printf("*************** In fgSetBlockOrder()\n");
18904     }
18905 #endif // DEBUG
18906
18907 #ifdef DEBUG
18908     BasicBlock::s_nMaxTrees = 0;
18909 #endif
18910
18911     /* Walk the basic blocks to assign sequence numbers */
18912
18913     /* If we don't compute the doms, then we never mark blocks as loops. */
18914     if (fgDomsComputed)
18915     {
18916         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18917         {
18918             /* If this block is a loop header, mark it appropriately */
18919
18920             if (block->isLoopHead())
18921             {
18922                 fgMarkLoopHead(block);
18923             }
18924         }
18925     }
18926     // only enable fully interruptible code for if we're hijacking.
18927     else if (GCPOLL_NONE == opts.compGCPollType)
18928     {
18929         /* If we don't have the dominators, use an abbreviated test for fully interruptible.  If there are
18930          * any back edges, check the source and destination blocks to see if they're GC Safe.  If not, then
18931          * go fully interruptible. */
18932
18933         /* XXX Mon 1/21/2008
18934          * Wouldn't it be nice to have a block iterator that can do this loop?
18935          */
18936         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18937         {
18938 // true if the edge is forward, or if it is a back edge and either the source and dest are GC safe.
18939 #define EDGE_IS_GC_SAFE(src, dst)                                                                                      \
18940     (((src)->bbNum < (dst)->bbNum) || (((src)->bbFlags | (dst)->bbFlags) & BBF_GC_SAFE_POINT))
18941
18942             bool partiallyInterruptible = true;
18943             switch (block->bbJumpKind)
18944             {
18945                 case BBJ_COND:
18946                 case BBJ_ALWAYS:
18947                     partiallyInterruptible = EDGE_IS_GC_SAFE(block, block->bbJumpDest);
18948                     break;
18949
18950                 case BBJ_SWITCH:
18951
18952                     unsigned jumpCnt;
18953                     jumpCnt = block->bbJumpSwt->bbsCount;
18954                     BasicBlock** jumpPtr;
18955                     jumpPtr = block->bbJumpSwt->bbsDstTab;
18956
18957                     do
18958                     {
18959                         partiallyInterruptible &= EDGE_IS_GC_SAFE(block, *jumpPtr);
18960                     } while (++jumpPtr, --jumpCnt);
18961
18962                     break;
18963
18964                 default:
18965                     break;
18966             }
18967
18968             if (!partiallyInterruptible)
18969             {
18970                 // DDB 204533:
18971                 // The GC encoding for fully interruptible methods does not
18972                 // support more than 1023 pushed arguments, so we can't set
18973                 // genInterruptible here when we have 1024 or more pushed args
18974                 //
18975                 if (compCanEncodePtrArgCntMax())
18976                 {
18977                     genInterruptible = true;
18978                 }
18979                 break;
18980             }
18981 #undef EDGE_IS_GC_SAFE
18982         }
18983     }
18984
18985     if (!fgGCPollsCreated)
18986     {
18987         fgCreateGCPolls();
18988     }
18989
18990     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18991     {
18992
18993 #if FEATURE_FASTTAILCALL
18994 #ifndef JIT32_GCENCODER
18995         if (block->endsWithTailCallOrJmp(this, true) && optReachWithoutCall(fgFirstBB, block))
18996         {
18997             // We have a tail call that is reachable without making any other
18998             // 'normal' call that would have counted as a GC Poll.  If we were
18999             // using polls, all return blocks meeting this criteria would have
19000             // already added polls and then marked as being GC safe
19001             // (BBF_GC_SAFE_POINT). Thus we can only reach here when *NOT*
19002             // using GC polls, but instead relying on the JIT to generate
19003             // fully-interruptible code.
19004             noway_assert(GCPOLL_NONE == opts.compGCPollType);
19005
19006             // This tail call might combine with other tail calls to form a
19007             // loop.  Thus we need to either add a poll, or make the method
19008             // fully interruptible.  I chose the later because that's what
19009             // JIT64 does.
19010             genInterruptible = true;
19011         }
19012 #endif // !JIT32_GCENCODER
19013 #endif // FEATURE_FASTTAILCALL
19014
19015         fgSetBlockOrder(block);
19016     }
19017
19018     /* Remember that now the tree list is threaded */
19019
19020     fgStmtListThreaded = true;
19021
19022 #ifdef DEBUG
19023     if (verbose)
19024     {
19025         printf("The biggest BB has %4u tree nodes\n", BasicBlock::s_nMaxTrees);
19026     }
19027     fgDebugCheckLinks();
19028 #endif // DEBUG
19029 }
19030
19031 /*****************************************************************************/
19032
19033 void Compiler::fgSetStmtSeq(GenTree* tree)
19034 {
19035     GenTree list; // helper node that we use to start the StmtList
19036                   // It's located in front of the first node in the list
19037
19038     noway_assert(tree->gtOper == GT_STMT);
19039
19040     /* Assign numbers and next/prev links for this tree */
19041
19042     fgTreeSeqNum = 0;
19043     fgTreeSeqLst = &list;
19044     fgTreeSeqBeg = nullptr;
19045
19046     fgSetTreeSeqHelper(tree->gtStmt.gtStmtExpr, false);
19047
19048     /* Record the address of the first node */
19049
19050     tree->gtStmt.gtStmtList = fgTreeSeqBeg;
19051
19052 #ifdef DEBUG
19053
19054     if (list.gtNext->gtPrev != &list)
19055     {
19056         printf("&list ");
19057         printTreeID(&list);
19058         printf(" != list.next->prev ");
19059         printTreeID(list.gtNext->gtPrev);
19060         printf("\n");
19061         goto BAD_LIST;
19062     }
19063
19064     GenTree* temp;
19065     GenTree* last;
19066     for (temp = list.gtNext, last = &list; temp; last = temp, temp = temp->gtNext)
19067     {
19068         if (temp->gtPrev != last)
19069         {
19070             printTreeID(temp);
19071             printf("->gtPrev = ");
19072             printTreeID(temp->gtPrev);
19073             printf(", but last = ");
19074             printTreeID(last);
19075             printf("\n");
19076
19077         BAD_LIST:;
19078
19079             printf("\n");
19080             gtDispTree(tree->gtStmt.gtStmtExpr);
19081             printf("\n");
19082
19083             for (GenTree* bad = &list; bad; bad = bad->gtNext)
19084             {
19085                 printf("  entry at ");
19086                 printTreeID(bad);
19087                 printf(" (prev=");
19088                 printTreeID(bad->gtPrev);
19089                 printf(",next=)");
19090                 printTreeID(bad->gtNext);
19091                 printf("\n");
19092             }
19093
19094             printf("\n");
19095             noway_assert(!"Badly linked tree");
19096             break;
19097         }
19098     }
19099 #endif // DEBUG
19100
19101     /* Fix the first node's 'prev' link */
19102
19103     noway_assert(list.gtNext->gtPrev == &list);
19104     list.gtNext->gtPrev = nullptr;
19105
19106 #ifdef DEBUG
19107     /* Keep track of the highest # of tree nodes */
19108
19109     if (BasicBlock::s_nMaxTrees < fgTreeSeqNum)
19110     {
19111         BasicBlock::s_nMaxTrees = fgTreeSeqNum;
19112     }
19113 #endif // DEBUG
19114 }
19115
19116 /*****************************************************************************/
19117
19118 void Compiler::fgSetBlockOrder(BasicBlock* block)
19119 {
19120     GenTree* tree;
19121
19122     tree = block->bbTreeList;
19123     if (!tree)
19124     {
19125         return;
19126     }
19127
19128     for (;;)
19129     {
19130         fgSetStmtSeq(tree);
19131
19132         /* Are there any more trees in this basic block? */
19133
19134         if (tree->gtNext == nullptr)
19135         {
19136             /* last statement in the tree list */
19137             noway_assert(block->lastStmt() == tree);
19138             break;
19139         }
19140
19141 #ifdef DEBUG
19142         if (block->bbTreeList == tree)
19143         {
19144             /* first statement in the list */
19145             noway_assert(tree->gtPrev->gtNext == nullptr);
19146         }
19147         else
19148         {
19149             noway_assert(tree->gtPrev->gtNext == tree);
19150         }
19151
19152         noway_assert(tree->gtNext->gtPrev == tree);
19153 #endif // DEBUG
19154
19155         tree = tree->gtNext;
19156     }
19157 }
19158
19159 #ifdef LEGACY_BACKEND
19160 //------------------------------------------------------------------------
19161 // fgOrderBlockOps: Get the execution order for a block assignment
19162 //
19163 // Arguments:
19164 //    tree    - The block assignment
19165 //    reg0    - The register for the destination
19166 //    reg1    - The register for the source
19167 //    reg2    - The register for the size
19168 //    opsPtr  - An array of 3 GenTree*'s, an out argument for the operands, in order
19169 //    regsPtr - An array of three regMaskTP - an out argument for the registers, in order
19170 //
19171 // Return Value:
19172 //    The return values go into the arrays that are passed in, and provide the
19173 //    operands and associated registers, in execution order.
19174 //
19175 // Notes:
19176 //    This method is somewhat convoluted in order to preserve old behavior from when
19177 //    block assignments had their dst and src in a GT_LIST as op1, and their size as op2.
19178 //    The old tree was like this:
19179 //                                tree->gtOp
19180 //                               /        \
19181 //                           GT_LIST  [size/clsHnd]
19182 //                           /      \
19183 //                       [dest]     [val/src]
19184 //
19185 //    The new tree looks like this:
19186 //                                GT_ASG
19187 //                               /       \
19188 //                           blk/obj   [val/src]
19189 //                           /      \
19190 //                    [destAddr]     [*size/clsHnd] *only for GT_DYN_BLK
19191 //
19192 //    For the (usual) case of GT_BLK or GT_OBJ, the size is always "evaluated" (i.e.
19193 //    instantiated into a register) last. In those cases, the GTF_REVERSE_OPS flag
19194 //    on the assignment works as usual.
19195 //    In order to preserve previous possible orderings, the order for evaluating
19196 //    the size of a GT_DYN_BLK node is controlled by its gtEvalSizeFirst flag. If
19197 //    that is set, the size is evaluated first, and then the src and dst are evaluated
19198 //    according to the GTF_REVERSE_OPS flag on the assignment.
19199
19200 void Compiler::fgOrderBlockOps(GenTree*   tree,
19201                                regMaskTP  reg0,
19202                                regMaskTP  reg1,
19203                                regMaskTP  reg2,
19204                                GenTree**  opsPtr,  // OUT
19205                                regMaskTP* regsPtr) // OUT
19206 {
19207     assert(tree->OperIsBlkOp());
19208
19209     GenTreeBlk* destBlk     = tree->gtOp.gtOp1->AsBlk();
19210     GenTree*    destAddr    = destBlk->Addr();
19211     GenTree*    srcPtrOrVal = tree->gtOp.gtOp2;
19212     if (tree->OperIsCopyBlkOp())
19213     {
19214         assert(srcPtrOrVal->OperIsIndir());
19215         srcPtrOrVal = srcPtrOrVal->AsIndir()->Addr();
19216     }
19217
19218     assert(destAddr != nullptr);
19219     assert(srcPtrOrVal != nullptr);
19220
19221     GenTree* ops[3] = {
19222         destAddr,    // Dest address
19223         srcPtrOrVal, // Val / Src address
19224         nullptr      // Size of block
19225     };
19226
19227     regMaskTP regs[3] = {reg0, reg1, reg2};
19228
19229     static int blockOpsOrder[4][3] =
19230         //                destBlk->gtEvalSizeFirst |       tree->gtFlags
19231         {
19232             //            -------------------------+----------------------------
19233             {0, 1, 2}, //          false           |              -
19234             {2, 0, 1}, //          true            |              -
19235             {1, 0, 2}, //          false           |       GTF_REVERSE_OPS
19236             {2, 1, 0}  //          true            |       GTF_REVERSE_OPS
19237         };
19238
19239     int orderNum = ((tree->gtFlags & GTF_REVERSE_OPS) == 0) ? 0 : 2;
19240     if (destBlk->OperIs(GT_DYN_BLK))
19241     {
19242         GenTreeDynBlk* const dynBlk = destBlk->AsDynBlk();
19243         if (dynBlk->gtEvalSizeFirst)
19244         {
19245             orderNum++;
19246         }
19247         ops[2] = dynBlk->gtDynamicSize;
19248     }
19249
19250     assert(orderNum < 4);
19251
19252     int* order = blockOpsOrder[orderNum];
19253
19254     PREFIX_ASSUME(order != NULL);
19255
19256     // Fill in the OUT arrays according to the order we have selected
19257
19258     opsPtr[0] = ops[order[0]];
19259     opsPtr[1] = ops[order[1]];
19260     opsPtr[2] = ops[order[2]];
19261
19262     regsPtr[0] = regs[order[0]];
19263     regsPtr[1] = regs[order[1]];
19264     regsPtr[2] = regs[order[2]];
19265 }
19266 #endif // LEGACY_BACKEND
19267
19268 //------------------------------------------------------------------------
19269 // fgGetFirstNode: Get the first node in the tree, in execution order
19270 //
19271 // Arguments:
19272 //    tree - The top node of the tree of interest
19273 //
19274 // Return Value:
19275 //    The first node in execution order, that belongs to tree.
19276 //
19277 // Assumptions:
19278 //     'tree' must either be a leaf, or all of its constituent nodes must be contiguous
19279 //     in execution order.
19280 //     TODO-Cleanup: Add a debug-only method that verifies this.
19281
19282 /* static */
19283 GenTree* Compiler::fgGetFirstNode(GenTree* tree)
19284 {
19285     GenTree* child = tree;
19286     while (child->NumChildren() > 0)
19287     {
19288         if (child->OperIsBinary() && child->IsReverseOp())
19289         {
19290             child = child->GetChild(1);
19291         }
19292         else
19293         {
19294             child = child->GetChild(0);
19295         }
19296     }
19297     return child;
19298 }
19299
19300 // Examine the bbTreeList and return the estimated code size for this block
19301 unsigned Compiler::fgGetCodeEstimate(BasicBlock* block)
19302 {
19303     unsigned costSz = 0; // estimate of blocks code size cost
19304
19305     switch (block->bbJumpKind)
19306     {
19307         case BBJ_NONE:
19308             costSz = 0;
19309             break;
19310         case BBJ_ALWAYS:
19311         case BBJ_EHCATCHRET:
19312         case BBJ_LEAVE:
19313         case BBJ_COND:
19314             costSz = 2;
19315             break;
19316         case BBJ_CALLFINALLY:
19317             costSz = 5;
19318             break;
19319         case BBJ_SWITCH:
19320             costSz = 10;
19321             break;
19322         case BBJ_THROW:
19323             costSz = 1; // We place a int3 after the code for a throw block
19324             break;
19325         case BBJ_EHFINALLYRET:
19326         case BBJ_EHFILTERRET:
19327             costSz = 1;
19328             break;
19329         case BBJ_RETURN: // return from method
19330             costSz = 3;
19331             break;
19332         default:
19333             noway_assert(!"Bad bbJumpKind");
19334             break;
19335     }
19336
19337     GenTree* tree = block->FirstNonPhiDef();
19338     if (tree)
19339     {
19340         do
19341         {
19342             noway_assert(tree->gtOper == GT_STMT);
19343
19344             if (tree->gtCostSz < MAX_COST)
19345             {
19346                 costSz += tree->gtCostSz;
19347             }
19348             else
19349             {
19350                 // We could walk the tree to find out the real gtCostSz,
19351                 // but just using MAX_COST for this trees code size works OK
19352                 costSz += tree->gtCostSz;
19353             }
19354
19355             tree = tree->gtNext;
19356         } while (tree);
19357     }
19358
19359     return costSz;
19360 }
19361
19362 #if DUMP_FLOWGRAPHS
19363
19364 struct escapeMapping_t
19365 {
19366     char        ch;
19367     const char* sub;
19368 };
19369
19370 // clang-format off
19371 static escapeMapping_t s_EscapeFileMapping[] =
19372 {
19373     {':', "="},
19374     {'<', "["},
19375     {'>', "]"},
19376     {';', "~semi~"},
19377     {'|', "~bar~"},
19378     {'&', "~amp~"},
19379     {'"', "~quot~"},
19380     {'*', "~star~"},
19381     {0, nullptr}
19382 };
19383
19384 static escapeMapping_t s_EscapeMapping[] =
19385 {
19386     {'<', "&lt;"},
19387     {'>', "&gt;"},
19388     {'&', "&amp;"},
19389     {'"', "&quot;"},
19390     {0, nullptr}
19391 };
19392 // clang-format on
19393
19394 const char* Compiler::fgProcessEscapes(const char* nameIn, escapeMapping_t* map)
19395 {
19396     const char* nameOut = nameIn;
19397     unsigned    lengthOut;
19398     unsigned    index;
19399     bool        match;
19400     bool        subsitutionRequired;
19401     const char* pChar;
19402
19403     lengthOut           = 1;
19404     subsitutionRequired = false;
19405     pChar               = nameIn;
19406     while (*pChar != '\0')
19407     {
19408         match = false;
19409         index = 0;
19410         while (map[index].ch != 0)
19411         {
19412             if (*pChar == map[index].ch)
19413             {
19414                 match = true;
19415                 break;
19416             }
19417             index++;
19418         }
19419         if (match)
19420         {
19421             subsitutionRequired = true;
19422             lengthOut += (unsigned)strlen(map[index].sub);
19423         }
19424         else
19425         {
19426             lengthOut += 1;
19427         }
19428         pChar++;
19429     }
19430
19431     if (subsitutionRequired)
19432     {
19433         char* newName = (char*)compGetMem(lengthOut, CMK_DebugOnly);
19434         char* pDest;
19435         pDest = newName;
19436         pChar = nameIn;
19437         while (*pChar != '\0')
19438         {
19439             match = false;
19440             index = 0;
19441             while (map[index].ch != 0)
19442             {
19443                 if (*pChar == map[index].ch)
19444                 {
19445                     match = true;
19446                     break;
19447                 }
19448                 index++;
19449             }
19450             if (match)
19451             {
19452                 strcpy(pDest, map[index].sub);
19453                 pDest += strlen(map[index].sub);
19454             }
19455             else
19456             {
19457                 *pDest++ = *pChar;
19458             }
19459             pChar++;
19460         }
19461         *pDest++ = '\0';
19462         nameOut  = (const char*)newName;
19463     }
19464
19465     return nameOut;
19466 }
19467
19468 static void fprintfDouble(FILE* fgxFile, double value)
19469 {
19470     assert(value >= 0.0);
19471
19472     if ((value >= 0.010) || (value == 0.0))
19473     {
19474         fprintf(fgxFile, "\"%7.3f\"", value);
19475     }
19476     else if (value >= 0.00010)
19477     {
19478         fprintf(fgxFile, "\"%7.5f\"", value);
19479     }
19480     else
19481     {
19482         fprintf(fgxFile, "\"%7E\"", value);
19483     }
19484 }
19485
19486 //------------------------------------------------------------------------
19487 // fgOpenFlowGraphFile: Open a file to dump either the xml or dot format flow graph
19488 //
19489 // Arguments:
19490 //    wbDontClose - A boolean out argument that indicates whether the caller should close the file
19491 //    phase       - A phase identifier to indicate which phase is associated with the dump
19492 //    type        - A (wide) string indicating the type of dump, "dot" or "xml"
19493 //
19494 // Return Value:
19495 //    Opens a file to which a flowgraph can be dumped, whose name is based on the current
19496 //    config vales.
19497
19498 FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR type)
19499 {
19500     FILE*       fgxFile;
19501     LPCWSTR     pattern  = nullptr;
19502     LPCWSTR     filename = nullptr;
19503     LPCWSTR     pathname = nullptr;
19504     const char* escapedString;
19505     bool        createDuplicateFgxFiles = true;
19506
19507 #ifdef DEBUG
19508     if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
19509     {
19510         pattern  = JitConfig.NgenDumpFg();
19511         filename = JitConfig.NgenDumpFgFile();
19512         pathname = JitConfig.NgenDumpFgDir();
19513     }
19514     else
19515     {
19516         pattern  = JitConfig.JitDumpFg();
19517         filename = JitConfig.JitDumpFgFile();
19518         pathname = JitConfig.JitDumpFgDir();
19519     }
19520 #endif // DEBUG
19521
19522     if (fgBBcount <= 1)
19523     {
19524         return nullptr;
19525     }
19526
19527     if (pattern == nullptr)
19528     {
19529         return nullptr;
19530     }
19531
19532     if (wcslen(pattern) == 0)
19533     {
19534         return nullptr;
19535     }
19536
19537     LPCWSTR phasePattern = JitConfig.JitDumpFgPhase();
19538     LPCWSTR phaseName    = PhaseShortNames[phase];
19539     if (phasePattern == nullptr)
19540     {
19541         if (phase != PHASE_DETERMINE_FIRST_COLD_BLOCK)
19542         {
19543             return nullptr;
19544         }
19545     }
19546     else if (*phasePattern != W('*'))
19547     {
19548         if (wcsstr(phasePattern, phaseName) == nullptr)
19549         {
19550             return nullptr;
19551         }
19552     }
19553
19554     if (*pattern != W('*'))
19555     {
19556         bool hasColon = (wcschr(pattern, W(':')) != nullptr);
19557
19558         if (hasColon)
19559         {
19560             const char* className = info.compClassName;
19561             if (*pattern == W('*'))
19562             {
19563                 pattern++;
19564             }
19565             else
19566             {
19567                 while ((*pattern != W(':')) && (*pattern != W('*')))
19568                 {
19569                     if (*pattern != *className)
19570                     {
19571                         return nullptr;
19572                     }
19573
19574                     pattern++;
19575                     className++;
19576                 }
19577                 if (*pattern == W('*'))
19578                 {
19579                     pattern++;
19580                 }
19581                 else
19582                 {
19583                     if (*className != 0)
19584                     {
19585                         return nullptr;
19586                     }
19587                 }
19588             }
19589             if (*pattern != W(':'))
19590             {
19591                 return nullptr;
19592             }
19593
19594             pattern++;
19595         }
19596
19597         const char* methodName = info.compMethodName;
19598         if (*pattern == W('*'))
19599         {
19600             pattern++;
19601         }
19602         else
19603         {
19604             while ((*pattern != 0) && (*pattern != W('*')))
19605             {
19606                 if (*pattern != *methodName)
19607                 {
19608                     return nullptr;
19609                 }
19610
19611                 pattern++;
19612                 methodName++;
19613             }
19614             if (*pattern == W('*'))
19615             {
19616                 pattern++;
19617             }
19618             else
19619             {
19620                 if (*methodName != 0)
19621                 {
19622                     return nullptr;
19623                 }
19624             }
19625         }
19626         if (*pattern != 0)
19627         {
19628             return nullptr;
19629         }
19630     }
19631
19632     if (filename == nullptr)
19633     {
19634         filename = W("default");
19635     }
19636
19637     if (wcscmp(filename, W("profiled")) == 0)
19638     {
19639         if (fgFirstBB->hasProfileWeight())
19640         {
19641             createDuplicateFgxFiles = true;
19642             goto ONE_FILE_PER_METHOD;
19643         }
19644         else
19645         {
19646             return nullptr;
19647         }
19648     }
19649     if (wcscmp(filename, W("hot")) == 0)
19650     {
19651         if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT)
19652
19653         {
19654             createDuplicateFgxFiles = true;
19655             goto ONE_FILE_PER_METHOD;
19656         }
19657         else
19658         {
19659             return nullptr;
19660         }
19661     }
19662     else if (wcscmp(filename, W("cold")) == 0)
19663     {
19664         if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD)
19665         {
19666             createDuplicateFgxFiles = true;
19667             goto ONE_FILE_PER_METHOD;
19668         }
19669         else
19670         {
19671             return nullptr;
19672         }
19673     }
19674     else if (wcscmp(filename, W("jit")) == 0)
19675     {
19676         if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT)
19677         {
19678             createDuplicateFgxFiles = true;
19679             goto ONE_FILE_PER_METHOD;
19680         }
19681         else
19682         {
19683             return nullptr;
19684         }
19685     }
19686     else if (wcscmp(filename, W("all")) == 0)
19687     {
19688         createDuplicateFgxFiles = true;
19689
19690     ONE_FILE_PER_METHOD:;
19691
19692         escapedString     = fgProcessEscapes(info.compFullName, s_EscapeFileMapping);
19693         size_t wCharCount = strlen(escapedString) + wcslen(phaseName) + 1 + strlen("~999") + wcslen(type) + 1;
19694         if (pathname != nullptr)
19695         {
19696             wCharCount += wcslen(pathname) + 1;
19697         }
19698         filename = (LPCWSTR)alloca(wCharCount * sizeof(WCHAR));
19699         if (pathname != nullptr)
19700         {
19701             swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S-%s.%s"), pathname, escapedString, phaseName, type);
19702         }
19703         else
19704         {
19705             swprintf_s((LPWSTR)filename, wCharCount, W("%S.%s"), escapedString, type);
19706         }
19707         fgxFile = _wfopen(filename, W("r")); // Check if this file already exists
19708         if (fgxFile != nullptr)
19709         {
19710             // For Generic methods we will have both hot and cold versions
19711             if (createDuplicateFgxFiles == false)
19712             {
19713                 fclose(fgxFile);
19714                 return nullptr;
19715             }
19716             // Yes, this filename already exists, so create a different one by appending ~2, ~3, etc...
19717             for (int i = 2; i < 1000; i++)
19718             {
19719                 fclose(fgxFile);
19720                 if (pathname != nullptr)
19721                 {
19722                     swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S~%d.%s"), pathname, escapedString, i, type);
19723                 }
19724                 else
19725                 {
19726                     swprintf_s((LPWSTR)filename, wCharCount, W("%S~%d.%s"), escapedString, i, type);
19727                 }
19728                 fgxFile = _wfopen(filename, W("r")); // Check if this file exists
19729                 if (fgxFile == nullptr)
19730                 {
19731                     break;
19732                 }
19733             }
19734             // If we have already created 1000 files with this name then just fail
19735             if (fgxFile != nullptr)
19736             {
19737                 fclose(fgxFile);
19738                 return nullptr;
19739             }
19740         }
19741         fgxFile      = _wfopen(filename, W("a+"));
19742         *wbDontClose = false;
19743     }
19744     else if (wcscmp(filename, W("stdout")) == 0)
19745     {
19746         fgxFile      = jitstdout;
19747         *wbDontClose = true;
19748     }
19749     else if (wcscmp(filename, W("stderr")) == 0)
19750     {
19751         fgxFile      = stderr;
19752         *wbDontClose = true;
19753     }
19754     else
19755     {
19756         LPCWSTR origFilename = filename;
19757         size_t  wCharCount   = wcslen(origFilename) + wcslen(type) + 2;
19758         if (pathname != nullptr)
19759         {
19760             wCharCount += wcslen(pathname) + 1;
19761         }
19762         filename = (LPCWSTR)alloca(wCharCount * sizeof(WCHAR));
19763         if (pathname != nullptr)
19764         {
19765             swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%s.%s"), pathname, origFilename, type);
19766         }
19767         else
19768         {
19769             swprintf_s((LPWSTR)filename, wCharCount, W("%s.%s"), origFilename, type);
19770         }
19771         fgxFile      = _wfopen(filename, W("a+"));
19772         *wbDontClose = false;
19773     }
19774
19775     return fgxFile;
19776 }
19777
19778 //------------------------------------------------------------------------
19779 // fgDumpFlowGraph: Dump the xml or dot format flow graph, if enabled for this phase.
19780 //
19781 // Arguments:
19782 //    phase       - A phase identifier to indicate which phase is associated with the dump,
19783 //                  i.e. which phase has just completed.
19784 //
19785 // Return Value:
19786 //    True iff a flowgraph has been dumped.
19787 //
19788 // Notes:
19789 //    The xml dumps are the historical mechanism for dumping the flowgraph.
19790 //    The dot format can be viewed by:
19791 //    - Graphviz (http://www.graphviz.org/)
19792 //      - The command "C:\Program Files (x86)\Graphviz2.38\bin\dot.exe" -Tsvg -oFoo.svg -Kdot Foo.dot
19793 //        will produce a Foo.svg file that can be opened with any svg-capable browser (e.g. IE).
19794 //    - http://rise4fun.com/Agl/
19795 //      - Cut and paste the graph from your .dot file, replacing the digraph on the page, and then click the play
19796 //        button.
19797 //      - It will show a rotating '/' and then render the graph in the browser.
19798 //    MSAGL has also been open-sourced to https://github.com/Microsoft/automatic-graph-layout.git.
19799 //
19800 //    Here are the config values that control it:
19801 //      COMPlus_JitDumpFg       A string (ala the COMPlus_JitDump string) indicating what methods to dump flowgraphs
19802 //                              for.
19803 //      COMPlus_JitDumpFgDir    A path to a directory into which the flowgraphs will be dumped.
19804 //      COMPlus_JitDumpFgFile   The filename to use. The default is "default.[xml|dot]".
19805 //                              Note that the new graphs will be appended to this file if it already exists.
19806 //      COMPlus_JitDumpFgPhase  Phase(s) after which to dump the flowgraph.
19807 //                              Set to the short name of a phase to see the flowgraph after that phase.
19808 //                              Leave unset to dump after COLD-BLK (determine first cold block) or set to * for all
19809 //                              phases.
19810 //      COMPlus_JitDumpFgDot    Set to non-zero to emit Dot instead of Xml Flowgraph dump. (Default is xml format.)
19811
19812 bool Compiler::fgDumpFlowGraph(Phases phase)
19813 {
19814     bool result        = false;
19815     bool dontClose     = false;
19816     bool createDotFile = false;
19817     if (JitConfig.JitDumpFgDot())
19818     {
19819         createDotFile = true;
19820     }
19821
19822     FILE* fgxFile = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx"));
19823
19824     if (fgxFile == nullptr)
19825     {
19826         return false;
19827     }
19828     bool        validWeights  = fgHaveValidEdgeWeights;
19829     unsigned    calledCount   = max(fgCalledCount, BB_UNITY_WEIGHT) / BB_UNITY_WEIGHT;
19830     double      weightDivisor = (double)(calledCount * BB_UNITY_WEIGHT);
19831     const char* escapedString;
19832     const char* regionString = "NONE";
19833
19834     if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT)
19835     {
19836         regionString = "HOT";
19837     }
19838     else if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD)
19839     {
19840         regionString = "COLD";
19841     }
19842     else if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT)
19843     {
19844         regionString = "JIT";
19845     }
19846
19847     if (createDotFile)
19848     {
19849         fprintf(fgxFile, "digraph %s\n{\n", info.compMethodName);
19850         fprintf(fgxFile, "/* Method %d, after phase %s */", Compiler::jitTotalMethodCompiled, PhaseNames[phase]);
19851     }
19852     else
19853     {
19854         fprintf(fgxFile, "<method");
19855
19856         escapedString = fgProcessEscapes(info.compFullName, s_EscapeMapping);
19857         fprintf(fgxFile, "\n    name=\"%s\"", escapedString);
19858
19859         escapedString = fgProcessEscapes(info.compClassName, s_EscapeMapping);
19860         fprintf(fgxFile, "\n    className=\"%s\"", escapedString);
19861
19862         escapedString = fgProcessEscapes(info.compMethodName, s_EscapeMapping);
19863         fprintf(fgxFile, "\n    methodName=\"%s\"", escapedString);
19864         fprintf(fgxFile, "\n    ngenRegion=\"%s\"", regionString);
19865
19866         fprintf(fgxFile, "\n    bytesOfIL=\"%d\"", info.compILCodeSize);
19867         fprintf(fgxFile, "\n    localVarCount=\"%d\"", lvaCount);
19868
19869         if (fgHaveProfileData())
19870         {
19871             fprintf(fgxFile, "\n    calledCount=\"%d\"", calledCount);
19872             fprintf(fgxFile, "\n    profileData=\"true\"");
19873         }
19874         if (compHndBBtabCount > 0)
19875         {
19876             fprintf(fgxFile, "\n    hasEHRegions=\"true\"");
19877         }
19878         if (fgHasLoops)
19879         {
19880             fprintf(fgxFile, "\n    hasLoops=\"true\"");
19881         }
19882         if (validWeights)
19883         {
19884             fprintf(fgxFile, "\n    validEdgeWeights=\"true\"");
19885             if (!fgSlopUsedInEdgeWeights && !fgRangeUsedInEdgeWeights)
19886             {
19887                 fprintf(fgxFile, "\n    exactEdgeWeights=\"true\"");
19888             }
19889         }
19890         if (fgFirstColdBlock != nullptr)
19891         {
19892             fprintf(fgxFile, "\n    firstColdBlock=\"%d\"", fgFirstColdBlock->bbNum);
19893         }
19894
19895         fprintf(fgxFile, ">");
19896
19897         fprintf(fgxFile, "\n    <blocks");
19898         fprintf(fgxFile, "\n        blockCount=\"%d\"", fgBBcount);
19899         fprintf(fgxFile, ">");
19900     }
19901
19902     static const char* kindImage[] = {"EHFINALLYRET", "EHFILTERRET", "EHCATCHRET",  "THROW", "RETURN", "NONE",
19903                                       "ALWAYS",       "LEAVE",       "CALLFINALLY", "COND",  "SWITCH"};
19904
19905     BasicBlock* block;
19906     unsigned    blockOrdinal;
19907     for (block = fgFirstBB, blockOrdinal = 1; block != nullptr; block = block->bbNext, blockOrdinal++)
19908     {
19909         if (createDotFile)
19910         {
19911             // Add constraint edges to try to keep nodes ordered.
19912             // It seems to work best if these edges are all created first.
19913             switch (block->bbJumpKind)
19914             {
19915                 case BBJ_COND:
19916                 case BBJ_NONE:
19917                     assert(block->bbNext != nullptr);
19918                     fprintf(fgxFile, "    BB%02u -> BB%02u\n", block->bbNum, block->bbNext->bbNum);
19919                     break;
19920                 default:
19921                     // These may or may not have an edge to the next block.
19922                     // Add a transparent edge to keep nodes ordered.
19923                     if (block->bbNext != nullptr)
19924                     {
19925                         fprintf(fgxFile, "    BB%02u -> BB%02u [arrowtail=none,color=transparent]\n", block->bbNum,
19926                                 block->bbNext->bbNum);
19927                     }
19928             }
19929         }
19930         else
19931         {
19932             fprintf(fgxFile, "\n        <block");
19933             fprintf(fgxFile, "\n            id=\"%d\"", block->bbNum);
19934             fprintf(fgxFile, "\n            ordinal=\"%d\"", blockOrdinal);
19935             fprintf(fgxFile, "\n            jumpKind=\"%s\"", kindImage[block->bbJumpKind]);
19936             if (block->hasTryIndex())
19937             {
19938                 fprintf(fgxFile, "\n            inTry=\"%s\"", "true");
19939             }
19940             if (block->hasHndIndex())
19941             {
19942                 fprintf(fgxFile, "\n            inHandler=\"%s\"", "true");
19943             }
19944             if ((fgFirstBB->hasProfileWeight()) && ((block->bbFlags & BBF_COLD) == 0))
19945             {
19946                 fprintf(fgxFile, "\n            hot=\"true\"");
19947             }
19948             if (block->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY))
19949             {
19950                 fprintf(fgxFile, "\n            callsNew=\"true\"");
19951             }
19952             if (block->bbFlags & BBF_LOOP_HEAD)
19953             {
19954                 fprintf(fgxFile, "\n            loopHead=\"true\"");
19955             }
19956             fprintf(fgxFile, "\n            weight=");
19957             fprintfDouble(fgxFile, ((double)block->bbWeight) / weightDivisor);
19958             fprintf(fgxFile, "\n            codeEstimate=\"%d\"", fgGetCodeEstimate(block));
19959             fprintf(fgxFile, "\n            startOffset=\"%d\"", block->bbCodeOffs);
19960             fprintf(fgxFile, "\n            endOffset=\"%d\"", block->bbCodeOffsEnd);
19961             fprintf(fgxFile, ">");
19962             fprintf(fgxFile, "\n        </block>");
19963         }
19964     }
19965
19966     if (!createDotFile)
19967     {
19968         fprintf(fgxFile, "\n    </blocks>");
19969
19970         fprintf(fgxFile, "\n    <edges");
19971         fprintf(fgxFile, "\n        edgeCount=\"%d\"", fgEdgeCount);
19972         fprintf(fgxFile, ">");
19973     }
19974
19975     unsigned    edgeNum = 1;
19976     BasicBlock* bTarget;
19977     for (bTarget = fgFirstBB; bTarget != nullptr; bTarget = bTarget->bbNext)
19978     {
19979         double targetWeightDivisor;
19980         if (bTarget->bbWeight == BB_ZERO_WEIGHT)
19981         {
19982             targetWeightDivisor = 1.0;
19983         }
19984         else
19985         {
19986             targetWeightDivisor = (double)bTarget->bbWeight;
19987         }
19988
19989         flowList* edge;
19990         for (edge = bTarget->bbPreds; edge != nullptr; edge = edge->flNext, edgeNum++)
19991         {
19992             BasicBlock* bSource = edge->flBlock;
19993             double      sourceWeightDivisor;
19994             if (bSource->bbWeight == BB_ZERO_WEIGHT)
19995             {
19996                 sourceWeightDivisor = 1.0;
19997             }
19998             else
19999             {
20000                 sourceWeightDivisor = (double)bSource->bbWeight;
20001             }
20002             if (createDotFile)
20003             {
20004                 // Don't duplicate the edges we added above.
20005                 if ((bSource->bbNum == (bTarget->bbNum - 1)) &&
20006                     ((bSource->bbJumpKind == BBJ_NONE) || (bSource->bbJumpKind == BBJ_COND)))
20007                 {
20008                     continue;
20009                 }
20010                 fprintf(fgxFile, "    BB%02u -> BB%02u", bSource->bbNum, bTarget->bbNum);
20011                 if ((bSource->bbNum > bTarget->bbNum))
20012                 {
20013                     fprintf(fgxFile, "[arrowhead=normal,arrowtail=none,color=green]\n");
20014                 }
20015                 else
20016                 {
20017                     fprintf(fgxFile, "\n");
20018                 }
20019             }
20020             else
20021             {
20022                 fprintf(fgxFile, "\n        <edge");
20023                 fprintf(fgxFile, "\n            id=\"%d\"", edgeNum);
20024                 fprintf(fgxFile, "\n            source=\"%d\"", bSource->bbNum);
20025                 fprintf(fgxFile, "\n            target=\"%d\"", bTarget->bbNum);
20026                 if (bSource->bbJumpKind == BBJ_SWITCH)
20027                 {
20028                     if (edge->flDupCount >= 2)
20029                     {
20030                         fprintf(fgxFile, "\n            switchCases=\"%d\"", edge->flDupCount);
20031                     }
20032                     if (bSource->bbJumpSwt->getDefault() == bTarget)
20033                     {
20034                         fprintf(fgxFile, "\n            switchDefault=\"true\"");
20035                     }
20036                 }
20037                 if (validWeights)
20038                 {
20039                     unsigned edgeWeight = (edge->flEdgeWeightMin + edge->flEdgeWeightMax) / 2;
20040                     fprintf(fgxFile, "\n            weight=");
20041                     fprintfDouble(fgxFile, ((double)edgeWeight) / weightDivisor);
20042
20043                     if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
20044                     {
20045                         fprintf(fgxFile, "\n            minWeight=");
20046                         fprintfDouble(fgxFile, ((double)edge->flEdgeWeightMin) / weightDivisor);
20047                         fprintf(fgxFile, "\n            maxWeight=");
20048                         fprintfDouble(fgxFile, ((double)edge->flEdgeWeightMax) / weightDivisor);
20049                     }
20050
20051                     if (edgeWeight > 0)
20052                     {
20053                         if (edgeWeight < bSource->bbWeight)
20054                         {
20055                             fprintf(fgxFile, "\n            out=");
20056                             fprintfDouble(fgxFile, ((double)edgeWeight) / sourceWeightDivisor);
20057                         }
20058                         if (edgeWeight < bTarget->bbWeight)
20059                         {
20060                             fprintf(fgxFile, "\n            in=");
20061                             fprintfDouble(fgxFile, ((double)edgeWeight) / targetWeightDivisor);
20062                         }
20063                     }
20064                 }
20065             }
20066             if (!createDotFile)
20067             {
20068                 fprintf(fgxFile, ">");
20069                 fprintf(fgxFile, "\n        </edge>");
20070             }
20071         }
20072     }
20073     if (createDotFile)
20074     {
20075         fprintf(fgxFile, "}\n");
20076     }
20077     else
20078     {
20079         fprintf(fgxFile, "\n    </edges>");
20080         fprintf(fgxFile, "\n</method>\n");
20081     }
20082
20083     if (dontClose)
20084     {
20085         // fgxFile is jitstdout or stderr
20086         fprintf(fgxFile, "\n");
20087     }
20088     else
20089     {
20090         fclose(fgxFile);
20091     }
20092
20093     return result;
20094 }
20095
20096 #endif // DUMP_FLOWGRAPHS
20097
20098 /*****************************************************************************/
20099 #ifdef DEBUG
20100
20101 void Compiler::fgDispReach()
20102 {
20103     printf("------------------------------------------------\n");
20104     printf("BBnum  Reachable by \n");
20105     printf("------------------------------------------------\n");
20106
20107     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
20108     {
20109         printf("BB%02u : ", block->bbNum);
20110         BlockSetOps::Iter iter(this, block->bbReach);
20111         unsigned          bbNum = 0;
20112         while (iter.NextElem(&bbNum))
20113         {
20114             printf("BB%02u ", bbNum);
20115         }
20116         printf("\n");
20117     }
20118 }
20119
20120 void Compiler::fgDispDoms()
20121 {
20122     // Don't bother printing this when we have a large number of BasicBlocks in the method
20123     if (fgBBcount > 256)
20124     {
20125         return;
20126     }
20127
20128     printf("------------------------------------------------\n");
20129     printf("BBnum  Dominated by\n");
20130     printf("------------------------------------------------\n");
20131
20132     for (unsigned i = 1; i <= fgBBNumMax; ++i)
20133     {
20134         BasicBlock* current = fgBBInvPostOrder[i];
20135         printf("BB%02u:  ", current->bbNum);
20136         while (current != current->bbIDom)
20137         {
20138             printf("BB%02u ", current->bbNum);
20139             current = current->bbIDom;
20140         }
20141         printf("\n");
20142     }
20143 }
20144
20145 /*****************************************************************************/
20146
20147 void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 */)
20148 {
20149     const unsigned __int64 flags    = block->bbFlags;
20150     unsigned               bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax;
20151     int                    maxBlockNumWidth = CountDigits(bbNumMax);
20152     maxBlockNumWidth                        = max(maxBlockNumWidth, 2);
20153     int blockNumWidth                       = CountDigits(block->bbNum);
20154     blockNumWidth                           = max(blockNumWidth, 2);
20155     int blockNumPadding                     = maxBlockNumWidth - blockNumWidth;
20156
20157     printf("%s %2u", block->dspToString(blockNumPadding), block->bbRefs);
20158
20159     //
20160     // Display EH 'try' region index
20161     //
20162
20163     if (block->hasTryIndex())
20164     {
20165         printf(" %2u", block->getTryIndex());
20166     }
20167     else
20168     {
20169         printf("   ");
20170     }
20171
20172     //
20173     // Display EH handler region index
20174     //
20175
20176     if (block->hasHndIndex())
20177     {
20178         printf(" %2u", block->getHndIndex());
20179     }
20180     else
20181     {
20182         printf("   ");
20183     }
20184
20185     printf(" ");
20186
20187     //
20188     // Display block predecessor list
20189     //
20190
20191     unsigned charCnt;
20192     if (fgCheapPredsValid)
20193     {
20194         charCnt = block->dspCheapPreds();
20195     }
20196     else
20197     {
20198         charCnt = block->dspPreds();
20199     }
20200
20201     if (charCnt < 19)
20202     {
20203         printf("%*s", 19 - charCnt, "");
20204     }
20205
20206     printf(" ");
20207
20208     //
20209     // Display block weight
20210     //
20211
20212     if (block->isMaxBBWeight())
20213     {
20214         printf(" MAX  ");
20215     }
20216     else
20217     {
20218         BasicBlock::weight_t weight = block->getBBWeight(this);
20219
20220         if (weight > 99999) // Is it going to be more than 6 characters?
20221         {
20222             if (weight <= 99999 * BB_UNITY_WEIGHT)
20223             {
20224                 // print weight in this format ddddd.
20225                 printf("%5u.", (weight + (BB_UNITY_WEIGHT / 2)) / BB_UNITY_WEIGHT);
20226             }
20227             else // print weight in terms of k (i.e. 156k )
20228             {
20229                 // print weight in this format dddddk
20230                 BasicBlock::weight_t weightK = weight / 1000;
20231                 printf("%5uk", (weightK + (BB_UNITY_WEIGHT / 2)) / BB_UNITY_WEIGHT);
20232             }
20233         }
20234         else // print weight in this format ddd.dd
20235         {
20236             printf("%6s", refCntWtd2str(weight));
20237         }
20238     }
20239     printf(" ");
20240
20241     //
20242     // Display optional IBC weight column.
20243     // Note that iColWidth includes one character for a leading space, if there is an IBC column.
20244     //
20245
20246     if (ibcColWidth > 0)
20247     {
20248         if (block->hasProfileWeight())
20249         {
20250             printf("%*u", ibcColWidth, block->bbWeight);
20251         }
20252         else
20253         {
20254             // No IBC data. Just print spaces to align the column.
20255             printf("%*s", ibcColWidth, "");
20256         }
20257     }
20258
20259     printf(" ");
20260
20261     //
20262     // Display block IL range
20263     //
20264
20265     block->dspBlockILRange();
20266
20267     //
20268     // Display block branch target
20269     //
20270
20271     if (flags & BBF_REMOVED)
20272     {
20273         printf("[removed]       ");
20274     }
20275     else
20276     {
20277         switch (block->bbJumpKind)
20278         {
20279             case BBJ_COND:
20280                 printf("-> BB%02u%*s ( cond )", block->bbJumpDest->bbNum,
20281                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20282                 break;
20283
20284             case BBJ_CALLFINALLY:
20285                 printf("-> BB%02u%*s (callf )", block->bbJumpDest->bbNum,
20286                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20287                 break;
20288
20289             case BBJ_ALWAYS:
20290                 if (flags & BBF_KEEP_BBJ_ALWAYS)
20291                 {
20292                     printf("-> BB%02u%*s (ALWAYS)", block->bbJumpDest->bbNum,
20293                            maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20294                 }
20295                 else
20296                 {
20297                     printf("-> BB%02u%*s (always)", block->bbJumpDest->bbNum,
20298                            maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20299                 }
20300                 break;
20301
20302             case BBJ_LEAVE:
20303                 printf("-> BB%02u%*s (leave )", block->bbJumpDest->bbNum,
20304                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20305                 break;
20306
20307             case BBJ_EHFINALLYRET:
20308                 printf("%*s        (finret)", maxBlockNumWidth - 2, "");
20309                 break;
20310
20311             case BBJ_EHFILTERRET:
20312                 printf("%*s        (fltret)", maxBlockNumWidth - 2, "");
20313                 break;
20314
20315             case BBJ_EHCATCHRET:
20316                 printf("-> BB%02u%*s ( cret )", block->bbJumpDest->bbNum,
20317                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20318                 break;
20319
20320             case BBJ_THROW:
20321                 printf("%*s        (throw )", maxBlockNumWidth - 2, "");
20322                 break;
20323
20324             case BBJ_RETURN:
20325                 printf("%*s        (return)", maxBlockNumWidth - 2, "");
20326                 break;
20327
20328             default:
20329                 printf("%*s                ", maxBlockNumWidth - 2, "");
20330                 break;
20331
20332             case BBJ_SWITCH:
20333                 printf("->");
20334
20335                 unsigned jumpCnt;
20336                 jumpCnt = block->bbJumpSwt->bbsCount;
20337                 BasicBlock** jumpTab;
20338                 jumpTab = block->bbJumpSwt->bbsDstTab;
20339                 int switchWidth;
20340                 switchWidth = 0;
20341                 do
20342                 {
20343                     printf("%cBB%02u", (jumpTab == block->bbJumpSwt->bbsDstTab) ? ' ' : ',', (*jumpTab)->bbNum);
20344                     switchWidth += 1 /* space/comma */ + 2 /* BB */ + max(CountDigits((*jumpTab)->bbNum), 2);
20345                 } while (++jumpTab, --jumpCnt);
20346
20347                 if (switchWidth < 7)
20348                 {
20349                     printf("%*s", 8 - switchWidth, "");
20350                 }
20351
20352                 printf(" (switch)");
20353                 break;
20354         }
20355     }
20356
20357     printf(" ");
20358
20359     //
20360     // Display block EH region and type, including nesting indicator
20361     //
20362
20363     if (block->hasTryIndex())
20364     {
20365         printf("T%d ", block->getTryIndex());
20366     }
20367     else
20368     {
20369         printf("   ");
20370     }
20371
20372     if (block->hasHndIndex())
20373     {
20374         printf("H%d ", block->getHndIndex());
20375     }
20376     else
20377     {
20378         printf("   ");
20379     }
20380
20381     if (flags & BBF_FUNCLET_BEG)
20382     {
20383         printf("F ");
20384     }
20385     else
20386     {
20387         printf("  ");
20388     }
20389
20390     int cnt = 0;
20391
20392     switch (block->bbCatchTyp)
20393     {
20394         case BBCT_NONE:
20395             break;
20396         case BBCT_FAULT:
20397             printf("fault ");
20398             cnt += 6;
20399             break;
20400         case BBCT_FINALLY:
20401             printf("finally ");
20402             cnt += 8;
20403             break;
20404         case BBCT_FILTER:
20405             printf("filter ");
20406             cnt += 7;
20407             break;
20408         case BBCT_FILTER_HANDLER:
20409             printf("filtHnd ");
20410             cnt += 8;
20411             break;
20412         default:
20413             printf("catch ");
20414             cnt += 6;
20415             break;
20416     }
20417
20418     if (block->bbCatchTyp != BBCT_NONE)
20419     {
20420         cnt += 2;
20421         printf("{ ");
20422         /* brace matching editor workaround to compensate for the preceding line: } */
20423     }
20424
20425     if (flags & BBF_TRY_BEG)
20426     {
20427         // Output a brace for every try region that this block opens
20428
20429         EHblkDsc* HBtab;
20430         EHblkDsc* HBtabEnd;
20431
20432         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
20433         {
20434             if (HBtab->ebdTryBeg == block)
20435             {
20436                 cnt += 6;
20437                 printf("try { ");
20438                 /* brace matching editor workaround to compensate for the preceding line: } */
20439             }
20440         }
20441     }
20442
20443     EHblkDsc* HBtab;
20444     EHblkDsc* HBtabEnd;
20445
20446     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
20447     {
20448         if (HBtab->ebdTryLast == block)
20449         {
20450             cnt += 2;
20451             /* brace matching editor workaround to compensate for the following line: { */
20452             printf("} ");
20453         }
20454         if (HBtab->ebdHndLast == block)
20455         {
20456             cnt += 2;
20457             /* brace matching editor workaround to compensate for the following line: { */
20458             printf("} ");
20459         }
20460         if (HBtab->HasFilter() && block->bbNext == HBtab->ebdHndBeg)
20461         {
20462             cnt += 2;
20463             /* brace matching editor workaround to compensate for the following line: { */
20464             printf("} ");
20465         }
20466     }
20467
20468     while (cnt < 12)
20469     {
20470         cnt++;
20471         printf(" ");
20472     }
20473
20474     //
20475     // Display block flags
20476     //
20477
20478     block->dspFlags();
20479
20480     printf("\n");
20481 }
20482
20483 /****************************************************************************
20484     Dump blocks from firstBlock to lastBlock.
20485 */
20486
20487 void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, bool dumpTrees)
20488 {
20489     BasicBlock* block;
20490
20491     // If any block has IBC data, we add an "IBC weight" column just before the 'IL range' column. This column is as
20492     // wide as necessary to accommodate all the various IBC weights. It's at least 4 characters wide, to accommodate
20493     // the "IBC" title and leading space.
20494     int ibcColWidth = 0;
20495     for (block = firstBlock; block != nullptr; block = block->bbNext)
20496     {
20497         if (block->hasProfileWeight())
20498         {
20499             int thisIbcWidth = CountDigits(block->bbWeight);
20500             ibcColWidth      = max(ibcColWidth, thisIbcWidth);
20501         }
20502
20503         if (block == lastBlock)
20504         {
20505             break;
20506         }
20507     }
20508     if (ibcColWidth > 0)
20509     {
20510         ibcColWidth = max(ibcColWidth, 3) + 1; // + 1 for the leading space
20511     }
20512
20513     unsigned bbNumMax         = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax;
20514     int      maxBlockNumWidth = CountDigits(bbNumMax);
20515     maxBlockNumWidth          = max(maxBlockNumWidth, 2);
20516     int padWidth              = maxBlockNumWidth - 2; // Account for functions with a large number of blocks.
20517
20518     // clang-format off
20519
20520     printf("\n");
20521     printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n",
20522         padWidth, "------------",
20523         ibcColWidth, "------------",
20524         maxBlockNumWidth, "----");
20525     printf("BBnum %*sBBid ref try hnd %s     weight  %*s%s  [IL range]     [jump]%*s    [EH region]         [flags]\n",
20526         padWidth, "",
20527         fgCheapPredsValid       ? "cheap preds" :
20528         (fgComputePredsDone     ? "preds      "
20529                                 : "           "),
20530         ((ibcColWidth > 0) ? ibcColWidth - 3 : 0), "",  // Subtract 3 for the width of "IBC", printed next.
20531         ((ibcColWidth > 0)      ? "IBC"
20532                                 : ""),
20533         maxBlockNumWidth, ""
20534         );
20535     printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n",
20536         padWidth, "------------",
20537         ibcColWidth, "------------",
20538         maxBlockNumWidth, "----");
20539
20540     // clang-format on
20541
20542     for (block = firstBlock; block; block = block->bbNext)
20543     {
20544         // First, do some checking on the bbPrev links
20545         if (block->bbPrev)
20546         {
20547             if (block->bbPrev->bbNext != block)
20548             {
20549                 printf("bad prev link\n");
20550             }
20551         }
20552         else if (block != fgFirstBB)
20553         {
20554             printf("bad prev link!\n");
20555         }
20556
20557         if (block == fgFirstColdBlock)
20558         {
20559             printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~"
20560                    "~~~~~~~~~~~~~~~~\n",
20561                    padWidth, "~~~~~~~~~~~~", ibcColWidth, "~~~~~~~~~~~~", maxBlockNumWidth, "~~~~");
20562         }
20563
20564 #if FEATURE_EH_FUNCLETS
20565         if (block == fgFirstFuncletBB)
20566         {
20567             printf("++++++%*s+++++++++++++++++++++++++++++++++++++%*s+++++++++++++++++++++++%*s++++++++++++++++++++++++"
20568                    "++++++++++++++++ funclets follow\n",
20569                    padWidth, "++++++++++++", ibcColWidth, "++++++++++++", maxBlockNumWidth, "++++");
20570         }
20571 #endif // FEATURE_EH_FUNCLETS
20572
20573         fgTableDispBasicBlock(block, ibcColWidth);
20574
20575         if (block == lastBlock)
20576         {
20577             break;
20578         }
20579     }
20580
20581     printf("------%*s-------------------------------------%*s-----------------------%*s--------------------------------"
20582            "--------\n",
20583            padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----");
20584
20585     if (dumpTrees)
20586     {
20587         fgDumpTrees(firstBlock, lastBlock);
20588     }
20589 }
20590
20591 /*****************************************************************************/
20592
20593 void Compiler::fgDispBasicBlocks(bool dumpTrees)
20594 {
20595     fgDispBasicBlocks(fgFirstBB, nullptr, dumpTrees);
20596 }
20597
20598 /*****************************************************************************/
20599 //  Increment the stmtNum and dump the tree using gtDispTree
20600 //
20601 void Compiler::fgDumpStmtTree(GenTree* stmt, unsigned bbNum)
20602 {
20603     compCurStmtNum++; // Increment the current stmtNum
20604
20605     printf("\n***** BB%02u, stmt %d\n", bbNum, compCurStmtNum);
20606
20607     if (fgOrder == FGOrderLinear || opts.compDbgInfo)
20608     {
20609         gtDispTree(stmt);
20610     }
20611     else
20612     {
20613         gtDispTree(stmt->gtStmt.gtStmtExpr);
20614     }
20615 }
20616
20617 //------------------------------------------------------------------------
20618 // Compiler::fgDumpBlock: dumps the contents of the given block to stdout.
20619 //
20620 // Arguments:
20621 //    block - The block to dump.
20622 //
20623 void Compiler::fgDumpBlock(BasicBlock* block)
20624 {
20625     printf("\n------------ ");
20626     block->dspBlockHeader(this);
20627
20628     if (!block->IsLIR())
20629     {
20630         for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
20631         {
20632             fgDumpStmtTree(stmt, block->bbNum);
20633             if (stmt == block->bbTreeList)
20634             {
20635                 block->bbStmtNum = compCurStmtNum; // Set the block->bbStmtNum
20636             }
20637         }
20638     }
20639     else
20640     {
20641         gtDispRange(LIR::AsRange(block));
20642     }
20643 }
20644
20645 /*****************************************************************************/
20646 //  Walk the BasicBlock list calling fgDumpTree once per Stmt
20647 //
20648 void Compiler::fgDumpTrees(BasicBlock* firstBlock, BasicBlock* lastBlock)
20649 {
20650     compCurStmtNum = 0; // Reset the current stmtNum
20651
20652     /* Walk the basic blocks */
20653
20654     // Note that typically we have already called fgDispBasicBlocks()
20655     //  so we don't need to print the preds and succs again here
20656     //
20657     for (BasicBlock* block = firstBlock; block; block = block->bbNext)
20658     {
20659         fgDumpBlock(block);
20660
20661         if (block == lastBlock)
20662         {
20663             break;
20664         }
20665     }
20666     printf("\n---------------------------------------------------------------------------------------------------------"
20667            "----------\n");
20668 }
20669
20670 /*****************************************************************************
20671  * Try to create as many candidates for GTF_MUL_64RSLT as possible.
20672  * We convert 'intOp1*intOp2' into 'int(long(nop(intOp1))*long(intOp2))'.
20673  */
20674
20675 /* static */
20676 Compiler::fgWalkResult Compiler::fgStress64RsltMulCB(GenTree** pTree, fgWalkData* data)
20677 {
20678     GenTree*  tree  = *pTree;
20679     Compiler* pComp = data->compiler;
20680
20681     if (tree->gtOper != GT_MUL || tree->gtType != TYP_INT || (tree->gtOverflow()))
20682     {
20683         return WALK_CONTINUE;
20684     }
20685
20686 #ifdef DEBUG
20687     if (pComp->verbose)
20688     {
20689         printf("STRESS_64RSLT_MUL before:\n");
20690         pComp->gtDispTree(tree);
20691     }
20692 #endif // DEBUG
20693
20694     // To ensure optNarrowTree() doesn't fold back to the original tree.
20695     tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, false, TYP_LONG);
20696     tree->gtOp.gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->gtOp.gtOp1);
20697     tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, false, TYP_LONG);
20698     tree->gtOp.gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp2, false, TYP_LONG);
20699     tree->gtType     = TYP_LONG;
20700     *pTree           = pComp->gtNewCastNode(TYP_INT, tree, false, TYP_INT);
20701
20702 #ifdef DEBUG
20703     if (pComp->verbose)
20704     {
20705         printf("STRESS_64RSLT_MUL after:\n");
20706         pComp->gtDispTree(*pTree);
20707     }
20708 #endif // DEBUG
20709
20710     return WALK_SKIP_SUBTREES;
20711 }
20712
20713 void Compiler::fgStress64RsltMul()
20714 {
20715     if (!compStressCompile(STRESS_64RSLT_MUL, 20))
20716     {
20717         return;
20718     }
20719
20720     fgWalkAllTreesPre(fgStress64RsltMulCB, (void*)this);
20721 }
20722
20723 // This variable is used to generate "traversal labels": one-time constants with which
20724 // we label basic blocks that are members of the basic block list, in order to have a
20725 // fast, high-probability test for membership in that list.  Type is "volatile" because
20726 // it's incremented with an atomic operation, which wants a volatile type; "long" so that
20727 // wrap-around to 0 (which I think has the highest probability of accidental collision) is
20728 // postponed a *long* time.
20729 static volatile int bbTraverseLabel = 1;
20730
20731 /*****************************************************************************
20732  *
20733  * A DEBUG routine to check the consistency of the flowgraph,
20734  * i.e. bbNum, bbRefs, bbPreds have to be up to date.
20735  *
20736  *****************************************************************************/
20737
20738 void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, bool checkBBRefs /* = true  */)
20739 {
20740 #ifdef DEBUG
20741     if (verbose)
20742     {
20743         printf("*************** In fgDebugCheckBBlist\n");
20744     }
20745 #endif // DEBUG
20746
20747     fgDebugCheckBlockLinks();
20748
20749     if (fgBBcount > 10000 && expensiveDebugCheckLevel < 1)
20750     {
20751         // The basic block checks are too expensive if there are too many blocks,
20752         // so give up unless we've been told to try hard.
20753         return;
20754     }
20755
20756     DWORD startTickCount = GetTickCount();
20757
20758     BasicBlock* block;
20759     BasicBlock* prevBlock;
20760     BasicBlock* blockPred;
20761     flowList*   pred;
20762     unsigned    blockRefs;
20763
20764 #if FEATURE_EH_FUNCLETS
20765     bool reachedFirstFunclet = false;
20766     if (fgFuncletsCreated)
20767     {
20768         //
20769         // Make sure that fgFirstFuncletBB is accurate.
20770         // It should be the first basic block in a handler region.
20771         //
20772         if (fgFirstFuncletBB != nullptr)
20773         {
20774             assert(fgFirstFuncletBB->hasHndIndex() == true);
20775             assert(fgFirstFuncletBB->bbFlags & BBF_FUNCLET_BEG);
20776         }
20777     }
20778 #endif // FEATURE_EH_FUNCLETS
20779
20780     /* Check bbNum, bbRefs and bbPreds */
20781     // First, pick a traversal stamp, and label all the blocks with it.
20782     unsigned curTraversalStamp = unsigned(InterlockedIncrement((LONG*)&bbTraverseLabel));
20783     for (block = fgFirstBB; block; block = block->bbNext)
20784     {
20785         block->bbTraversalStamp = curTraversalStamp;
20786     }
20787
20788     for (prevBlock = nullptr, block = fgFirstBB; block; prevBlock = block, block = block->bbNext)
20789     {
20790         blockRefs = 0;
20791
20792         /* First basic block has countOfInEdges() >= 1 */
20793
20794         if (block == fgFirstBB)
20795         {
20796             noway_assert(block->countOfInEdges() >= 1);
20797             blockRefs = 1;
20798         }
20799
20800         if (checkBBNum)
20801         {
20802             // Check that bbNum is sequential
20803             noway_assert(block->bbNext == nullptr || (block->bbNum + 1 == block->bbNext->bbNum));
20804         }
20805
20806         // If the block is a BBJ_COND, a BBJ_SWITCH or a
20807         // lowered GT_SWITCH_TABLE node then make sure it
20808         // ends with a conditional jump or a GT_SWITCH
20809
20810         if (block->bbJumpKind == BBJ_COND)
20811         {
20812             noway_assert(block->lastNode()->gtNext == nullptr && block->lastNode()->OperIsConditionalJump());
20813         }
20814         else if (block->bbJumpKind == BBJ_SWITCH)
20815         {
20816 #ifndef LEGACY_BACKEND
20817             noway_assert(block->lastNode()->gtNext == nullptr &&
20818                          (block->lastNode()->gtOper == GT_SWITCH || block->lastNode()->gtOper == GT_SWITCH_TABLE));
20819 #else  // LEGACY_BACKEND
20820             noway_assert(block->lastStmt()->gtNext == NULL && block->lastStmt()->gtStmtExpr->gtOper == GT_SWITCH);
20821 #endif // LEGACY_BACKEND
20822         }
20823         else if (!(block->bbJumpKind == BBJ_ALWAYS || block->bbJumpKind == BBJ_RETURN))
20824         {
20825             // this block cannot have a poll
20826             noway_assert(!(block->bbFlags & BBF_NEEDS_GCPOLL));
20827         }
20828
20829         if (block->bbCatchTyp == BBCT_FILTER)
20830         {
20831             if (!fgCheapPredsValid) // Don't check cheap preds
20832             {
20833                 // A filter has no predecessors
20834                 noway_assert(block->bbPreds == nullptr);
20835             }
20836         }
20837
20838 #if FEATURE_EH_FUNCLETS
20839         if (fgFuncletsCreated)
20840         {
20841             //
20842             // There should be no handler blocks until
20843             // we get to the fgFirstFuncletBB block,
20844             // then every block should be a handler block
20845             //
20846             if (!reachedFirstFunclet)
20847             {
20848                 if (block == fgFirstFuncletBB)
20849                 {
20850                     assert(block->hasHndIndex() == true);
20851                     reachedFirstFunclet = true;
20852                 }
20853                 else
20854                 {
20855                     assert(block->hasHndIndex() == false);
20856                 }
20857             }
20858             else // reachedFirstFunclet
20859             {
20860                 assert(block->hasHndIndex() == true);
20861             }
20862         }
20863 #endif // FEATURE_EH_FUNCLETS
20864
20865         // Don't check cheap preds.
20866         for (pred = (fgCheapPredsValid ? nullptr : block->bbPreds); pred != nullptr;
20867              blockRefs += pred->flDupCount, pred = pred->flNext)
20868         {
20869             assert(fgComputePredsDone); // If this isn't set, why do we have a preds list?
20870
20871             /*  make sure this pred is part of the BB list */
20872
20873             blockPred = pred->flBlock;
20874             noway_assert(blockPred->bbTraversalStamp == curTraversalStamp);
20875
20876             EHblkDsc* ehTryDsc = ehGetBlockTryDsc(block);
20877             if (ehTryDsc != nullptr)
20878             {
20879                 // You can jump to the start of a try
20880                 if (ehTryDsc->ebdTryBeg == block)
20881                 {
20882                     goto CHECK_HND;
20883                 }
20884
20885                 // You can jump within the same try region
20886                 if (bbInTryRegions(block->getTryIndex(), blockPred))
20887                 {
20888                     goto CHECK_HND;
20889                 }
20890
20891                 // The catch block can jump back into the middle of the try
20892                 if (bbInCatchHandlerRegions(block, blockPred))
20893                 {
20894                     goto CHECK_HND;
20895                 }
20896
20897                 // The end of a finally region is a BBJ_EHFINALLYRET block (during importing, BBJ_LEAVE) which
20898                 // is marked as "returning" to the BBJ_ALWAYS block following the BBJ_CALLFINALLY
20899                 // block that does a local call to the finally. This BBJ_ALWAYS is within
20900                 // the try region protected by the finally (for x86, ARM), but that's ok.
20901                 if (prevBlock->bbJumpKind == BBJ_CALLFINALLY && block->bbJumpKind == BBJ_ALWAYS &&
20902                     blockPred->bbJumpKind == BBJ_EHFINALLYRET)
20903                 {
20904                     goto CHECK_HND;
20905                 }
20906
20907                 printf("Jump into the middle of try region: BB%02u branches to BB%02u\n", blockPred->bbNum,
20908                        block->bbNum);
20909                 noway_assert(!"Jump into middle of try region");
20910             }
20911
20912         CHECK_HND:;
20913
20914             EHblkDsc* ehHndDsc = ehGetBlockHndDsc(block);
20915             if (ehHndDsc != nullptr)
20916             {
20917                 // You can do a BBJ_EHFINALLYRET or BBJ_EHFILTERRET into a handler region
20918                 if ((blockPred->bbJumpKind == BBJ_EHFINALLYRET) || (blockPred->bbJumpKind == BBJ_EHFILTERRET))
20919                 {
20920                     goto CHECK_JUMP;
20921                 }
20922
20923                 // Our try block can call our finally block
20924                 if ((block->bbCatchTyp == BBCT_FINALLY) && (blockPred->bbJumpKind == BBJ_CALLFINALLY) &&
20925                     ehCallFinallyInCorrectRegion(blockPred, block->getHndIndex()))
20926                 {
20927                     goto CHECK_JUMP;
20928                 }
20929
20930                 // You can jump within the same handler region
20931                 if (bbInHandlerRegions(block->getHndIndex(), blockPred))
20932                 {
20933                     goto CHECK_JUMP;
20934                 }
20935
20936                 // A filter can jump to the start of the filter handler
20937                 if (ehHndDsc->HasFilter())
20938                 {
20939                     goto CHECK_JUMP;
20940                 }
20941
20942                 printf("Jump into the middle of handler region: BB%02u branches to BB%02u\n", blockPred->bbNum,
20943                        block->bbNum);
20944                 noway_assert(!"Jump into the middle of handler region");
20945             }
20946
20947         CHECK_JUMP:;
20948
20949             switch (blockPred->bbJumpKind)
20950             {
20951                 case BBJ_COND:
20952                     noway_assert(blockPred->bbNext == block || blockPred->bbJumpDest == block);
20953                     break;
20954
20955                 case BBJ_NONE:
20956                     noway_assert(blockPred->bbNext == block);
20957                     break;
20958
20959                 case BBJ_CALLFINALLY:
20960                 case BBJ_ALWAYS:
20961                 case BBJ_EHCATCHRET:
20962                 case BBJ_EHFILTERRET:
20963                     noway_assert(blockPred->bbJumpDest == block);
20964                     break;
20965
20966                 case BBJ_EHFINALLYRET:
20967                 {
20968                     // If the current block is a successor to a BBJ_EHFINALLYRET (return from finally),
20969                     // then the lexically previous block should be a call to the same finally.
20970                     // Verify all of that.
20971
20972                     unsigned    hndIndex = blockPred->getHndIndex();
20973                     EHblkDsc*   ehDsc    = ehGetDsc(hndIndex);
20974                     BasicBlock* finBeg   = ehDsc->ebdHndBeg;
20975
20976                     // Because there is no bbPrev, we have to search for the lexically previous
20977                     // block.  We can shorten the search by only looking in places where it is legal
20978                     // to have a call to the finally.
20979
20980                     BasicBlock* begBlk;
20981                     BasicBlock* endBlk;
20982                     ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
20983
20984                     for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
20985                     {
20986                         if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
20987                         {
20988                             continue;
20989                         }
20990
20991                         if (block == bcall->bbNext)
20992                         {
20993                             goto PRED_OK;
20994                         }
20995                     }
20996
20997 #if FEATURE_EH_FUNCLETS
20998
20999                     if (fgFuncletsCreated)
21000                     {
21001                         // There is no easy way to search just the funclets that were pulled out of
21002                         // the corresponding try body, so instead we search all the funclets, and if
21003                         // we find a potential 'hit' we check if the funclet we're looking at is
21004                         // from the correct try region.
21005
21006                         for (BasicBlock* bcall = fgFirstFuncletBB; bcall; bcall = bcall->bbNext)
21007                         {
21008                             if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
21009                             {
21010                                 continue;
21011                             }
21012
21013                             if (block != bcall->bbNext)
21014                             {
21015                                 continue;
21016                             }
21017
21018                             if (ehCallFinallyInCorrectRegion(bcall, hndIndex))
21019                             {
21020                                 goto PRED_OK;
21021                             }
21022                         }
21023                     }
21024
21025 #endif // FEATURE_EH_FUNCLETS
21026
21027                     noway_assert(!"BBJ_EHFINALLYRET predecessor of block that doesn't follow a BBJ_CALLFINALLY!");
21028                 }
21029                 break;
21030
21031                 case BBJ_THROW:
21032                 case BBJ_RETURN:
21033                     noway_assert(!"THROW and RETURN block cannot be in the predecessor list!");
21034                     break;
21035
21036                 case BBJ_SWITCH:
21037                     unsigned jumpCnt;
21038                     jumpCnt = blockPred->bbJumpSwt->bbsCount;
21039                     BasicBlock** jumpTab;
21040                     jumpTab = blockPred->bbJumpSwt->bbsDstTab;
21041
21042                     do
21043                     {
21044                         if (block == *jumpTab)
21045                         {
21046                             goto PRED_OK;
21047                         }
21048                     } while (++jumpTab, --jumpCnt);
21049
21050                     noway_assert(!"SWITCH in the predecessor list with no jump label to BLOCK!");
21051                     break;
21052
21053                 default:
21054                     noway_assert(!"Unexpected bbJumpKind");
21055                     break;
21056             }
21057
21058         PRED_OK:;
21059         }
21060
21061         /* Check the bbRefs */
21062         if (checkBBRefs)
21063         {
21064             if (block->bbRefs != blockRefs)
21065             {
21066                 // Check to see if this block is the beginning of a filter or a handler and adjust the ref count
21067                 // appropriately.
21068                 for (EHblkDsc *HBtab = compHndBBtab, *HBtabEnd = &compHndBBtab[compHndBBtabCount]; HBtab != HBtabEnd;
21069                      HBtab++)
21070                 {
21071                     if (HBtab->ebdHndBeg == block)
21072                     {
21073                         blockRefs++;
21074                     }
21075                     if (HBtab->HasFilter() && (HBtab->ebdFilter == block))
21076                     {
21077                         blockRefs++;
21078                     }
21079                 }
21080             }
21081
21082             assert(block->bbRefs == blockRefs);
21083         }
21084
21085         /* Check that BBF_HAS_HANDLER is valid bbTryIndex */
21086         if (block->hasTryIndex())
21087         {
21088             noway_assert(block->getTryIndex() < compHndBBtabCount);
21089         }
21090
21091         /* Check if BBF_RUN_RARELY is set that we have bbWeight of zero */
21092         if (block->isRunRarely())
21093         {
21094             noway_assert(block->bbWeight == BB_ZERO_WEIGHT);
21095         }
21096         else
21097         {
21098             noway_assert(block->bbWeight > BB_ZERO_WEIGHT);
21099         }
21100     }
21101
21102     // Make sure the one return BB is not changed.
21103     if (genReturnBB)
21104     {
21105         noway_assert(genReturnBB->bbTreeList);
21106         noway_assert(genReturnBB->IsLIR() || genReturnBB->bbTreeList->gtOper == GT_STMT);
21107         noway_assert(genReturnBB->IsLIR() || genReturnBB->bbTreeList->gtType == TYP_VOID);
21108     }
21109
21110     // The general encoder/decoder (currently) only reports "this" as a generics context as a stack location,
21111     // so we mark info.compThisArg as lvAddrTaken to ensure that it is not enregistered. Otherwise, it should
21112     // not be address-taken.  This variable determines if the address-taken-ness of "thisArg" is "OK".
21113     bool copiedForGenericsCtxt;
21114 #ifndef JIT32_GCENCODER
21115     copiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0);
21116 #else  // JIT32_GCENCODER
21117     copiedForGenericsCtxt = FALSE;
21118 #endif // JIT32_GCENCODER
21119
21120     // This if only in support of the noway_asserts it contains.
21121     if (info.compIsStatic)
21122     {
21123         // For static method, should have never grabbed the temp.
21124         noway_assert(lvaArg0Var == BAD_VAR_NUM);
21125     }
21126     else
21127     {
21128         // For instance method:
21129         assert(info.compThisArg != BAD_VAR_NUM);
21130         bool compThisArgAddrExposedOK = !lvaTable[info.compThisArg].lvAddrExposed;
21131
21132 #ifndef JIT32_GCENCODER
21133         compThisArgAddrExposedOK = compThisArgAddrExposedOK || copiedForGenericsCtxt;
21134 #endif // !JIT32_GCENCODER
21135
21136         // Should never expose the address of arg 0 or write to arg 0.
21137         // In addition, lvArg0Var should remain 0 if arg0 is not
21138         // written to or address-exposed.
21139         noway_assert(
21140             compThisArgAddrExposedOK && !lvaTable[info.compThisArg].lvHasILStoreOp &&
21141             (lvaArg0Var == info.compThisArg ||
21142              lvaArg0Var != info.compThisArg &&
21143                  (lvaTable[lvaArg0Var].lvAddrExposed || lvaTable[lvaArg0Var].lvHasILStoreOp || copiedForGenericsCtxt)));
21144     }
21145 }
21146
21147 /*****************************************************************************
21148  *
21149  * A DEBUG routine to check the that the exception flags are correctly set.
21150  *
21151  ****************************************************************************/
21152
21153 void Compiler::fgDebugCheckFlags(GenTree* tree)
21154 {
21155     noway_assert(tree->gtOper != GT_STMT);
21156
21157     const genTreeOps oper      = tree->OperGet();
21158     const unsigned   kind      = tree->OperKind();
21159     unsigned         treeFlags = tree->gtFlags & GTF_ALL_EFFECT;
21160     unsigned         chkFlags  = 0;
21161
21162     if (tree->OperMayThrow(this))
21163     {
21164         chkFlags |= GTF_EXCEPT;
21165     }
21166
21167     /* Is this a leaf node? */
21168
21169     if (kind & GTK_LEAF)
21170     {
21171         switch (oper)
21172         {
21173             case GT_CLS_VAR:
21174                 chkFlags |= GTF_GLOB_REF;
21175                 break;
21176
21177             case GT_CATCH_ARG:
21178                 chkFlags |= GTF_ORDER_SIDEEFF;
21179                 break;
21180
21181             case GT_MEMORYBARRIER:
21182                 chkFlags |= GTF_GLOB_REF | GTF_ASG;
21183                 break;
21184
21185             default:
21186                 break;
21187         }
21188     }
21189
21190     /* Is it a 'simple' unary/binary operator? */
21191
21192     else if (kind & GTK_SMPOP)
21193     {
21194         GenTree* op1 = tree->gtOp.gtOp1;
21195         GenTree* op2 = tree->gtGetOp2IfPresent();
21196
21197         // During GS work, we make shadow copies for params.
21198         // In gsParamsToShadows(), we create a shadow var of TYP_INT for every small type param.
21199         // Then in gsReplaceShadowParams(), we change the gtLclNum to the shadow var.
21200         // We also change the types of the local var tree and the assignment tree to TYP_INT if necessary.
21201         // However, since we don't morph the tree at this late stage. Manually propagating
21202         // TYP_INT up to the GT_ASG tree is only correct if we don't need to propagate the TYP_INT back up.
21203         // The following checks will ensure this.
21204
21205         // Is the left child of "tree" a GT_ASG?
21206         //
21207         // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
21208         // (or) If GT_ASG is the left child of a GT_COMMA, the type of the GT_COMMA node will
21209         // be determined by its right child. So we don't need to propagate TYP_INT up either. We are fine.
21210         if (op1 && op1->gtOper == GT_ASG)
21211         {
21212             assert(tree->gtType == TYP_VOID || tree->gtOper == GT_COMMA);
21213         }
21214
21215         // Is the right child of "tree" a GT_ASG?
21216         //
21217         // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
21218         if (op2 && op2->gtOper == GT_ASG)
21219         {
21220             assert(tree->gtType == TYP_VOID);
21221         }
21222
21223         switch (oper)
21224         {
21225             case GT_QMARK:
21226                 if (op1->OperIsCompare())
21227                 {
21228                     noway_assert(op1->gtFlags & GTF_DONT_CSE);
21229                 }
21230                 else
21231                 {
21232                     noway_assert((op1->gtOper == GT_CNS_INT) &&
21233                                  ((op1->gtIntCon.gtIconVal == 0) || (op1->gtIntCon.gtIconVal == 1)));
21234                 }
21235                 break;
21236
21237             case GT_LIST:
21238             case GT_FIELD_LIST:
21239                 if ((op2 != nullptr) && op2->OperIsAnyList())
21240                 {
21241                     ArrayStack<GenTree*> stack(this);
21242                     while ((tree->gtGetOp2() != nullptr) && tree->gtGetOp2()->OperIsAnyList())
21243                     {
21244                         stack.Push(tree);
21245                         tree = tree->gtGetOp2();
21246                     }
21247
21248                     fgDebugCheckFlags(tree);
21249
21250                     while (stack.Height() > 0)
21251                     {
21252                         tree = stack.Pop();
21253                         assert((tree->gtFlags & GTF_REVERSE_OPS) == 0);
21254                         fgDebugCheckFlags(tree->gtOp.gtOp1);
21255                         chkFlags |= (tree->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT);
21256                         chkFlags |= (tree->gtGetOp2()->gtFlags & GTF_ALL_EFFECT);
21257                         fgDebugCheckFlagsHelper(tree, (tree->gtFlags & GTF_ALL_EFFECT), chkFlags);
21258                     }
21259
21260                     return;
21261                 }
21262                 break;
21263
21264             default:
21265                 break;
21266         }
21267
21268         /* Recursively check the subtrees */
21269
21270         if (op1)
21271         {
21272             fgDebugCheckFlags(op1);
21273         }
21274         if (op2)
21275         {
21276             fgDebugCheckFlags(op2);
21277         }
21278
21279         if (op1)
21280         {
21281             chkFlags |= (op1->gtFlags & GTF_ALL_EFFECT);
21282         }
21283         if (op2)
21284         {
21285             chkFlags |= (op2->gtFlags & GTF_ALL_EFFECT);
21286         }
21287
21288         // We reuse the value of GTF_REVERSE_OPS for a GT_IND-specific flag,
21289         // so exempt that (unary) operator.
21290         if (tree->OperGet() != GT_IND && tree->gtFlags & GTF_REVERSE_OPS)
21291         {
21292             /* Must have two operands if GTF_REVERSE is set */
21293             noway_assert(op1 && op2);
21294
21295             /* Make sure that the order of side effects has not been swapped. */
21296
21297             /* However CSE may introduce an assignment after the reverse flag
21298                was set and thus GTF_ASG cannot be considered here. */
21299
21300             /* For a GT_ASG(GT_IND(x), y) we are interested in the side effects of x */
21301             GenTree* op1p;
21302             if (GenTree::OperIsAssignment(oper) && (op1->gtOper == GT_IND))
21303             {
21304                 op1p = op1->gtOp.gtOp1;
21305             }
21306             else
21307             {
21308                 op1p = op1;
21309             }
21310
21311             /* This isn't true any more with the sticky GTF_REVERSE */
21312             /*
21313             // if op1p has side effects, then op2 cannot have side effects
21314             if (op1p->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
21315             {
21316                 if (op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
21317                     gtDispTree(tree);
21318                 noway_assert(!(op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG)));
21319             }
21320             */
21321         }
21322
21323         if (tree->OperRequiresAsgFlag())
21324         {
21325             chkFlags |= GTF_ASG;
21326         }
21327
21328         if (oper == GT_ADDR && (op1->OperIsLocal() || op1->gtOper == GT_CLS_VAR ||
21329                                 (op1->gtOper == GT_IND && op1->gtOp.gtOp1->gtOper == GT_CLS_VAR_ADDR)))
21330         {
21331             /* &aliasedVar doesn't need GTF_GLOB_REF, though alisasedVar does.
21332                Similarly for clsVar */
21333             treeFlags |= GTF_GLOB_REF;
21334         }
21335     }
21336
21337     /* See what kind of a special operator we have here */
21338
21339     else
21340     {
21341         switch (tree->OperGet())
21342         {
21343             case GT_CALL:
21344
21345                 GenTree*     args;
21346                 GenTree*     argx;
21347                 GenTreeCall* call;
21348
21349                 call = tree->AsCall();
21350
21351                 chkFlags |= GTF_CALL;
21352
21353                 if (call->gtCallObjp)
21354                 {
21355                     fgDebugCheckFlags(call->gtCallObjp);
21356                     chkFlags |= (call->gtCallObjp->gtFlags & GTF_SIDE_EFFECT);
21357
21358                     if (call->gtCallObjp->gtFlags & GTF_ASG)
21359                     {
21360                         treeFlags |= GTF_ASG;
21361                     }
21362                 }
21363
21364                 for (args = call->gtCallArgs; args; args = args->gtOp.gtOp2)
21365                 {
21366                     argx = args->gtOp.gtOp1;
21367                     fgDebugCheckFlags(argx);
21368
21369                     chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT);
21370
21371                     if (argx->gtFlags & GTF_ASG)
21372                     {
21373                         treeFlags |= GTF_ASG;
21374                     }
21375                 }
21376
21377                 for (args = call->gtCallLateArgs; args; args = args->gtOp.gtOp2)
21378                 {
21379                     argx = args->gtOp.gtOp1;
21380                     fgDebugCheckFlags(argx);
21381
21382                     chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT);
21383
21384                     if (argx->gtFlags & GTF_ASG)
21385                     {
21386                         treeFlags |= GTF_ASG;
21387                     }
21388                 }
21389
21390                 if ((call->gtCallType == CT_INDIRECT) && (call->gtCallCookie != nullptr))
21391                 {
21392                     fgDebugCheckFlags(call->gtCallCookie);
21393                     chkFlags |= (call->gtCallCookie->gtFlags & GTF_SIDE_EFFECT);
21394                 }
21395
21396                 if (call->gtCallType == CT_INDIRECT)
21397                 {
21398                     fgDebugCheckFlags(call->gtCallAddr);
21399                     chkFlags |= (call->gtCallAddr->gtFlags & GTF_SIDE_EFFECT);
21400                 }
21401
21402                 if (call->IsUnmanaged() && (call->gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL))
21403                 {
21404                     if (call->gtCallArgs->gtOp.gtOp1->OperGet() == GT_NOP)
21405                     {
21406                         noway_assert(call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL ||
21407                                      call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF);
21408                     }
21409                     else
21410                     {
21411                         noway_assert(call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL ||
21412                                      call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF);
21413                     }
21414                 }
21415                 break;
21416
21417             case GT_ARR_ELEM:
21418
21419                 GenTree* arrObj;
21420                 unsigned dim;
21421
21422                 arrObj = tree->gtArrElem.gtArrObj;
21423                 fgDebugCheckFlags(arrObj);
21424                 chkFlags |= (arrObj->gtFlags & GTF_ALL_EFFECT);
21425
21426                 for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
21427                 {
21428                     fgDebugCheckFlags(tree->gtArrElem.gtArrInds[dim]);
21429                     chkFlags |= tree->gtArrElem.gtArrInds[dim]->gtFlags & GTF_ALL_EFFECT;
21430                 }
21431                 break;
21432
21433             case GT_ARR_OFFSET:
21434
21435                 fgDebugCheckFlags(tree->gtArrOffs.gtOffset);
21436                 chkFlags |= (tree->gtArrOffs.gtOffset->gtFlags & GTF_ALL_EFFECT);
21437                 fgDebugCheckFlags(tree->gtArrOffs.gtIndex);
21438                 chkFlags |= (tree->gtArrOffs.gtIndex->gtFlags & GTF_ALL_EFFECT);
21439                 fgDebugCheckFlags(tree->gtArrOffs.gtArrObj);
21440                 chkFlags |= (tree->gtArrOffs.gtArrObj->gtFlags & GTF_ALL_EFFECT);
21441                 break;
21442
21443             case GT_ARR_BOUNDS_CHECK:
21444 #ifdef FEATURE_SIMD
21445             case GT_SIMD_CHK:
21446 #endif // FEATURE_SIMD
21447 #ifdef FEATURE_HW_INTRINSICS
21448             case GT_HW_INTRINSIC_CHK:
21449 #endif // FEATURE_HW_INTRINSICS
21450
21451                 GenTreeBoundsChk* bndsChk;
21452                 bndsChk = tree->AsBoundsChk();
21453                 fgDebugCheckFlags(bndsChk->gtIndex);
21454                 chkFlags |= (bndsChk->gtIndex->gtFlags & GTF_ALL_EFFECT);
21455                 fgDebugCheckFlags(bndsChk->gtArrLen);
21456                 chkFlags |= (bndsChk->gtArrLen->gtFlags & GTF_ALL_EFFECT);
21457                 break;
21458
21459             case GT_CMPXCHG:
21460
21461                 chkFlags |= (GTF_GLOB_REF | GTF_ASG);
21462                 GenTreeCmpXchg* cmpXchg;
21463                 cmpXchg = tree->AsCmpXchg();
21464                 fgDebugCheckFlags(cmpXchg->gtOpLocation);
21465                 chkFlags |= (cmpXchg->gtOpLocation->gtFlags & GTF_ALL_EFFECT);
21466                 fgDebugCheckFlags(cmpXchg->gtOpValue);
21467                 chkFlags |= (cmpXchg->gtOpValue->gtFlags & GTF_ALL_EFFECT);
21468                 fgDebugCheckFlags(cmpXchg->gtOpComparand);
21469                 chkFlags |= (cmpXchg->gtOpComparand->gtFlags & GTF_ALL_EFFECT);
21470                 break;
21471
21472             case GT_STORE_DYN_BLK:
21473             case GT_DYN_BLK:
21474
21475                 GenTreeDynBlk* dynBlk;
21476                 dynBlk = tree->AsDynBlk();
21477                 fgDebugCheckFlags(dynBlk->gtDynamicSize);
21478                 chkFlags |= (dynBlk->gtDynamicSize->gtFlags & GTF_ALL_EFFECT);
21479                 fgDebugCheckFlags(dynBlk->Addr());
21480                 chkFlags |= (dynBlk->Addr()->gtFlags & GTF_ALL_EFFECT);
21481                 if (tree->OperGet() == GT_STORE_DYN_BLK)
21482                 {
21483                     fgDebugCheckFlags(dynBlk->Data());
21484                     chkFlags |= (dynBlk->Data()->gtFlags & GTF_ALL_EFFECT);
21485                 }
21486                 break;
21487
21488             default:
21489
21490 #ifdef DEBUG
21491                 gtDispTree(tree);
21492 #endif
21493
21494                 assert(!"Unknown operator for fgDebugCheckFlags");
21495                 break;
21496         }
21497     }
21498
21499     fgDebugCheckFlagsHelper(tree, treeFlags, chkFlags);
21500 }
21501
21502 //------------------------------------------------------------------------------
21503 // fgDebugCheckFlagsHelper : Check if all bits that are set in chkFlags are also set in treeFlags.
21504 //
21505 //
21506 // Arguments:
21507 //    tree  - Tree whose flags are being checked
21508 //    treeFlags - Actual flags on the tree
21509 //    chkFlags - Expected flags
21510 //
21511 // Note:
21512 //    Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled.
21513
21514 void Compiler::fgDebugCheckFlagsHelper(GenTree* tree, unsigned treeFlags, unsigned chkFlags)
21515 {
21516     if (chkFlags & ~treeFlags)
21517     {
21518         // Print the tree so we can see it in the log.
21519         printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
21520         GenTree::gtDispFlags(chkFlags & ~treeFlags, GTF_DEBUG_NONE);
21521         printf("\n");
21522         gtDispTree(tree);
21523
21524         noway_assert(!"Missing flags on tree");
21525
21526         // Print the tree again so we can see it right after we hook up the debugger.
21527         printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
21528         GenTree::gtDispFlags(chkFlags & ~treeFlags, GTF_DEBUG_NONE);
21529         printf("\n");
21530         gtDispTree(tree);
21531     }
21532     else if (treeFlags & ~chkFlags)
21533     {
21534         // TODO: We are currently only checking extra GTF_EXCEPT and GTF_ASG flags.
21535         if ((treeFlags & ~chkFlags & ~GTF_GLOB_REF & ~GTF_ORDER_SIDEEFF & ~GTF_CALL) != 0)
21536         {
21537             // Print the tree so we can see it in the log.
21538             printf("Extra flags on parent tree [%X]: ", tree);
21539             GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE);
21540             printf("\n");
21541             gtDispTree(tree);
21542
21543             noway_assert(!"Extra flags on tree");
21544
21545             // Print the tree again so we can see it right after we hook up the debugger.
21546             printf("Extra flags on parent tree [%X]: ", tree);
21547             GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE);
21548             printf("\n");
21549             gtDispTree(tree);
21550         }
21551     }
21552 }
21553
21554 // DEBUG routine to check correctness of the internal gtNext, gtPrev threading of a statement.
21555 // This threading is only valid when fgStmtListThreaded is true.
21556 // This calls an alternate method for FGOrderLinear.
21557 void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node)
21558 {
21559     // LIR blocks are checked using BasicBlock::CheckLIR().
21560     if (block->IsLIR())
21561     {
21562         LIR::AsRange(block).CheckLIR(this);
21563         // TODO: return?
21564     }
21565
21566     GenTreeStmt* stmt = node->AsStmt();
21567
21568     assert(fgStmtListThreaded);
21569
21570     noway_assert(stmt->gtStmtList);
21571
21572     // The first node's gtPrev must be nullptr (the gtPrev list is not circular).
21573     // The last node's gtNext must be nullptr (the gtNext list is not circular). This is tested if the loop below
21574     // terminates.
21575     assert(stmt->gtStmtList->gtPrev == nullptr);
21576
21577     for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext)
21578     {
21579         if (tree->gtPrev)
21580         {
21581             noway_assert(tree->gtPrev->gtNext == tree);
21582         }
21583         else
21584         {
21585             noway_assert(tree == stmt->gtStmtList);
21586         }
21587
21588         if (tree->gtNext)
21589         {
21590             noway_assert(tree->gtNext->gtPrev == tree);
21591         }
21592         else
21593         {
21594             noway_assert(tree == stmt->gtStmtExpr);
21595         }
21596
21597         /* Cross-check gtPrev,gtNext with gtOp for simple trees */
21598
21599         GenTree* expectedPrevTree = nullptr;
21600
21601         if (tree->OperIsLeaf())
21602         {
21603             if (tree->gtOper == GT_CATCH_ARG)
21604             {
21605                 // The GT_CATCH_ARG should always have GTF_ORDER_SIDEEFF set
21606                 noway_assert(tree->gtFlags & GTF_ORDER_SIDEEFF);
21607                 // The GT_CATCH_ARG has to be the first thing evaluated
21608                 noway_assert(stmt == block->FirstNonPhiDef());
21609                 noway_assert(stmt->gtStmtList->gtOper == GT_CATCH_ARG);
21610                 // The root of the tree should have GTF_ORDER_SIDEEFF set
21611                 noway_assert(stmt->gtStmtExpr->gtFlags & GTF_ORDER_SIDEEFF);
21612             }
21613         }
21614
21615         if (tree->OperIsUnary() && tree->gtOp.gtOp1)
21616         {
21617             expectedPrevTree = tree->gtOp.gtOp1;
21618         }
21619         else if (tree->OperIsBinary() && tree->gtOp.gtOp1)
21620         {
21621             switch (tree->gtOper)
21622             {
21623                 case GT_QMARK:
21624                     expectedPrevTree =
21625                         tree->gtOp.gtOp2->AsColon()->ThenNode(); // "then" operand of the GT_COLON (generated second).
21626                     break;
21627
21628                 case GT_COLON:
21629                     expectedPrevTree = tree->AsColon()->ElseNode(); // "else" branch result (generated first).
21630                     break;
21631
21632                 default:
21633                     if (tree->gtOp.gtOp2)
21634                     {
21635                         if (tree->gtFlags & GTF_REVERSE_OPS)
21636                         {
21637                             expectedPrevTree = tree->gtOp.gtOp1;
21638                         }
21639                         else
21640                         {
21641                             expectedPrevTree = tree->gtOp.gtOp2;
21642                         }
21643                     }
21644                     else
21645                     {
21646                         expectedPrevTree = tree->gtOp.gtOp1;
21647                     }
21648                     break;
21649             }
21650         }
21651
21652         noway_assert(expectedPrevTree == nullptr ||     // No expectations about the prev node
21653                      tree->gtPrev == expectedPrevTree); // The "normal" case
21654     }
21655 }
21656
21657 /*****************************************************************************
21658  *
21659  * A DEBUG routine to check the correctness of the links between GT_STMT nodes
21660  * and ordinary nodes within a statement.
21661  *
21662  ****************************************************************************/
21663
21664 void Compiler::fgDebugCheckLinks(bool morphTrees)
21665 {
21666     // This used to be only on for stress, and there was a comment stating that
21667     // it was "quite an expensive operation" but I did not find that to be true.
21668     // Set DO_SANITY_DEBUG_CHECKS to false to revert to that behavior.
21669     const bool DO_SANITY_DEBUG_CHECKS = true;
21670
21671     if (!DO_SANITY_DEBUG_CHECKS && !compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))
21672     {
21673         return;
21674     }
21675
21676     fgDebugCheckBlockLinks();
21677
21678     /* For each basic block check the bbTreeList links */
21679     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
21680     {
21681         if (block->IsLIR())
21682         {
21683             LIR::AsRange(block).CheckLIR(this);
21684         }
21685         else
21686         {
21687             fgDebugCheckStmtsList(block, morphTrees);
21688         }
21689     }
21690
21691     fgDebugCheckNodesUniqueness();
21692 }
21693
21694 //------------------------------------------------------------------------------
21695 // fgDebugCheckStmtsList : Perfoms the set of checks:
21696 //    - all statements in the block are linked correctly
21697 //    - check statements flags
21698 //    - check nodes gtNext and gtPrev values, if the node list is threaded
21699 //
21700 // Arguments:
21701 //    block  - the block to check statements in
21702 //    morphTrees - try to morph trees in the checker
21703 //
21704 // Note:
21705 //    Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled.
21706
21707 void Compiler::fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees)
21708 {
21709     for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
21710     {
21711         /* Verify that bbTreeList is threaded correctly */
21712         /* Note that for the GT_STMT list, the gtPrev list is circular. The gtNext list is not: gtNext of the
21713         * last GT_STMT in a block is nullptr. */
21714
21715         noway_assert(stmt->gtPrev);
21716
21717         if (stmt == block->bbTreeList)
21718         {
21719             noway_assert(stmt->gtPrev->gtNext == nullptr);
21720         }
21721         else
21722         {
21723             noway_assert(stmt->gtPrev->gtNext == stmt);
21724         }
21725
21726         if (stmt->gtNext)
21727         {
21728             noway_assert(stmt->gtNext->gtPrev == stmt);
21729         }
21730         else
21731         {
21732             noway_assert(block->lastStmt() == stmt);
21733         }
21734
21735         /* For each statement check that the exception flags are properly set */
21736
21737         noway_assert(stmt->gtStmtExpr);
21738
21739         if (verbose && 0)
21740         {
21741             gtDispTree(stmt->gtStmtExpr);
21742         }
21743
21744         fgDebugCheckFlags(stmt->gtStmtExpr);
21745
21746         // Not only will this stress fgMorphBlockStmt(), but we also get all the checks
21747         // done by fgMorphTree()
21748
21749         if (morphTrees)
21750         {
21751             // If 'stmt' is removed from the block, start a new check for the current block,
21752             // break the current check.
21753             if (fgMorphBlockStmt(block, stmt DEBUGARG("test morphing")))
21754             {
21755                 fgDebugCheckStmtsList(block, morphTrees);
21756                 break;
21757             }
21758         }
21759
21760         /* For each GT_STMT node check that the nodes are threaded correcly - gtStmtList */
21761
21762         if (fgStmtListThreaded)
21763         {
21764             fgDebugCheckNodeLinks(block, stmt);
21765         }
21766     }
21767 }
21768
21769 // ensure that bbNext and bbPrev are consistent
21770 void Compiler::fgDebugCheckBlockLinks()
21771 {
21772     assert(fgFirstBB->bbPrev == nullptr);
21773
21774     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
21775     {
21776         if (block->bbNext)
21777         {
21778             assert(block->bbNext->bbPrev == block);
21779         }
21780         else
21781         {
21782             assert(block == fgLastBB);
21783         }
21784
21785         if (block->bbPrev)
21786         {
21787             assert(block->bbPrev->bbNext == block);
21788         }
21789         else
21790         {
21791             assert(block == fgFirstBB);
21792         }
21793
21794         // If this is a switch, check that the tables are consistent.
21795         // Note that we don't call GetSwitchDescMap(), because it has the side-effect
21796         // of allocating it if it is not present.
21797         if (block->bbJumpKind == BBJ_SWITCH && m_switchDescMap != nullptr)
21798         {
21799             SwitchUniqueSuccSet uniqueSuccSet;
21800             if (m_switchDescMap->Lookup(block, &uniqueSuccSet))
21801             {
21802                 // Create a set with all the successors. Don't use BlockSet, so we don't need to worry
21803                 // about the BlockSet epoch.
21804                 BitVecTraits bitVecTraits(fgBBNumMax + 1, this);
21805                 BitVec       succBlocks(BitVecOps::MakeEmpty(&bitVecTraits));
21806                 BasicBlock** jumpTable = block->bbJumpSwt->bbsDstTab;
21807                 unsigned     jumpCount = block->bbJumpSwt->bbsCount;
21808                 for (unsigned i = 0; i < jumpCount; i++)
21809                 {
21810                     BitVecOps::AddElemD(&bitVecTraits, succBlocks, jumpTable[i]->bbNum);
21811                 }
21812                 // Now we should have a set of unique successors that matches what's in the switchMap.
21813                 // First, check the number of entries, then make sure all the blocks in uniqueSuccSet
21814                 // are in the BlockSet.
21815                 unsigned count = BitVecOps::Count(&bitVecTraits, succBlocks);
21816                 assert(uniqueSuccSet.numDistinctSuccs == count);
21817                 for (unsigned i = 0; i < uniqueSuccSet.numDistinctSuccs; i++)
21818                 {
21819                     assert(BitVecOps::IsMember(&bitVecTraits, succBlocks, uniqueSuccSet.nonDuplicates[i]->bbNum));
21820                 }
21821             }
21822         }
21823     }
21824 }
21825
21826 // UniquenessCheckWalker keeps data that is neccesary to check
21827 // that each tree has it is own unique id and they do not repeat.
21828 class UniquenessCheckWalker
21829 {
21830 public:
21831     UniquenessCheckWalker(Compiler* comp)
21832         : comp(comp), nodesVecTraits(comp->compGenTreeID, comp), uniqueNodes(BitVecOps::MakeEmpty(&nodesVecTraits))
21833     {
21834     }
21835
21836     //------------------------------------------------------------------------
21837     // fgMarkTreeId: Visit all subtrees in the tree and check gtTreeIDs.
21838     //
21839     // Arguments:
21840     //    pTree     - Pointer to the tree to walk
21841     //    fgWalkPre - the UniquenessCheckWalker instance
21842     //
21843     static Compiler::fgWalkResult MarkTreeId(GenTree** pTree, Compiler::fgWalkData* fgWalkPre)
21844     {
21845         UniquenessCheckWalker* walker   = static_cast<UniquenessCheckWalker*>(fgWalkPre->pCallbackData);
21846         unsigned               gtTreeID = (*pTree)->gtTreeID;
21847         walker->CheckTreeId(gtTreeID);
21848         return Compiler::WALK_CONTINUE;
21849     }
21850
21851     //------------------------------------------------------------------------
21852     // CheckTreeId: Check that this tree was not visit before and memorize it as visited.
21853     //
21854     // Arguments:
21855     //    gtTreeID - identificator of GenTree.
21856     //
21857     void CheckTreeId(unsigned gtTreeID)
21858     {
21859         assert(!BitVecOps::IsMember(&nodesVecTraits, uniqueNodes, gtTreeID));
21860         BitVecOps::AddElemD(&nodesVecTraits, uniqueNodes, gtTreeID);
21861     }
21862
21863 private:
21864     Compiler*    comp;
21865     BitVecTraits nodesVecTraits;
21866     BitVec       uniqueNodes;
21867 };
21868
21869 //------------------------------------------------------------------------------
21870 // fgDebugCheckNodesUniqueness: Check that each tree in the method has its own unique gtTreeId.
21871 //
21872 void Compiler::fgDebugCheckNodesUniqueness()
21873 {
21874     UniquenessCheckWalker walker(this);
21875
21876     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
21877     {
21878         if (block->IsLIR())
21879         {
21880             for (GenTree* i : LIR::AsRange(block))
21881             {
21882                 walker.CheckTreeId(i->gtTreeID);
21883             }
21884         }
21885         else
21886         {
21887             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
21888             {
21889                 GenTree* root = stmt->gtStmtExpr;
21890                 fgWalkTreePre(&root, UniquenessCheckWalker::MarkTreeId, &walker);
21891             }
21892         }
21893     }
21894 }
21895
21896 /*****************************************************************************/
21897 #endif // DEBUG
21898 /*****************************************************************************/
21899
21900 //------------------------------------------------------------------------
21901 // fgCheckForInlineDepthAndRecursion: compute depth of the candidate, and
21902 // check for recursion.
21903 //
21904 // Return Value:
21905 //    The depth of the inline candidate. The root method is a depth 0, top-level
21906 //    candidates at depth 1, etc.
21907 //
21908 // Notes:
21909 //    We generally disallow recursive inlines by policy. However, they are
21910 //    supported by the underlying machinery.
21911 //
21912 //    Likewise the depth limit is a policy consideration, and serves mostly
21913 //    as a safeguard to prevent runaway inlining of small methods.
21914 //
21915 unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo)
21916 {
21917     BYTE*          candidateCode = inlineInfo->inlineCandidateInfo->methInfo.ILCode;
21918     InlineContext* inlineContext = inlineInfo->iciStmt->gtInlineContext;
21919     InlineResult*  inlineResult  = inlineInfo->inlineResult;
21920
21921     // There should be a context for all candidates.
21922     assert(inlineContext != nullptr);
21923     int depth = 0;
21924
21925     for (; inlineContext != nullptr; inlineContext = inlineContext->GetParent())
21926     {
21927
21928         depth++;
21929
21930         if (inlineContext->GetCode() == candidateCode)
21931         {
21932             // This inline candidate has the same IL code buffer as an already
21933             // inlined method does.
21934             inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_RECURSIVE);
21935             break;
21936         }
21937
21938         if (depth > InlineStrategy::IMPLEMENTATION_MAX_INLINE_DEPTH)
21939         {
21940             break;
21941         }
21942     }
21943
21944     inlineResult->NoteInt(InlineObservation::CALLSITE_DEPTH, depth);
21945     return depth;
21946 }
21947
21948 /*****************************************************************************
21949  *
21950  *  Inlining phase
21951  */
21952
21953 void Compiler::fgInline()
21954 {
21955     if (!opts.OptEnabled(CLFLG_INLINING))
21956     {
21957         return;
21958     }
21959
21960 #ifdef DEBUG
21961     if (verbose)
21962     {
21963         printf("*************** In fgInline()\n");
21964     }
21965 #endif // DEBUG
21966
21967     BasicBlock* block = fgFirstBB;
21968     noway_assert(block != nullptr);
21969
21970     // Set the root inline context on all statements
21971     InlineContext* rootContext = m_inlineStrategy->GetRootContext();
21972
21973     for (; block != nullptr; block = block->bbNext)
21974     {
21975         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
21976         {
21977             stmt->gtInlineContext = rootContext;
21978         }
21979     }
21980
21981     // Reset block back to start for inlining
21982     block = fgFirstBB;
21983
21984     do
21985     {
21986         /* Make the current basic block address available globally */
21987
21988         compCurBB = block;
21989
21990         GenTreeStmt* stmt;
21991         GenTree*     expr;
21992
21993         for (stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
21994         {
21995             expr = stmt->gtStmtExpr;
21996
21997             // See if we can expand the inline candidate
21998             if ((expr->gtOper == GT_CALL) && ((expr->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0))
21999             {
22000                 GenTreeCall* call = expr->AsCall();
22001                 InlineResult inlineResult(this, call, stmt, "fgInline");
22002
22003                 fgMorphStmt = stmt;
22004
22005                 fgMorphCallInline(call, &inlineResult);
22006
22007                 if (stmt->gtStmtExpr->IsNothingNode())
22008                 {
22009                     fgRemoveStmt(block, stmt);
22010                     continue;
22011                 }
22012             }
22013             else
22014             {
22015 #ifdef DEBUG
22016                 // Look for non-candidates.
22017                 fgWalkTreePre(&stmt->gtStmtExpr, fgFindNonInlineCandidate, stmt);
22018 #endif
22019             }
22020
22021             // See if we need to replace the return value place holder.
22022             // Also, see if this update enables further devirtualization.
22023             fgWalkTreePre(&stmt->gtStmtExpr, fgUpdateInlineReturnExpressionPlaceHolder, (void*)this);
22024
22025             // See if stmt is of the form GT_COMMA(call, nop)
22026             // If yes, we can get rid of GT_COMMA.
22027             if (expr->OperGet() == GT_COMMA && expr->gtOp.gtOp1->OperGet() == GT_CALL &&
22028                 expr->gtOp.gtOp2->OperGet() == GT_NOP)
22029             {
22030                 stmt->gtStmtExpr = expr->gtOp.gtOp1;
22031             }
22032         }
22033
22034         block = block->bbNext;
22035
22036     } while (block);
22037
22038 #ifdef DEBUG
22039
22040     // Check that we should not have any inline candidate or return value place holder left.
22041
22042     block = fgFirstBB;
22043     noway_assert(block);
22044
22045     do
22046     {
22047         GenTreeStmt* stmt;
22048
22049         for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
22050         {
22051             // Call Compiler::fgDebugCheckInlineCandidates on each node
22052             fgWalkTreePre(&stmt->gtStmtExpr, fgDebugCheckInlineCandidates);
22053         }
22054
22055         block = block->bbNext;
22056
22057     } while (block);
22058
22059     fgVerifyHandlerTab();
22060
22061     if (verbose)
22062     {
22063         printf("*************** After fgInline()\n");
22064         fgDispBasicBlocks(true);
22065         fgDispHandlerTab();
22066     }
22067
22068     if (verbose || fgPrintInlinedMethods)
22069     {
22070         printf("**************** Inline Tree\n");
22071         m_inlineStrategy->Dump();
22072     }
22073
22074 #endif // DEBUG
22075 }
22076
22077 #ifdef DEBUG
22078
22079 //------------------------------------------------------------------------
22080 // fgFindNonInlineCandidate: tree walk helper to ensure that a tree node
22081 // that is not an inline candidate is noted as a failed inline.
22082 //
22083 // Arguments:
22084 //    pTree - pointer to pointer tree node being walked
22085 //    data  - contextual data for the walk
22086 //
22087 // Return Value:
22088 //    walk result
22089 //
22090 // Note:
22091 //    Invokes fgNoteNonInlineCandidate on the nodes it finds.
22092
22093 Compiler::fgWalkResult Compiler::fgFindNonInlineCandidate(GenTree** pTree, fgWalkData* data)
22094 {
22095     GenTree* tree = *pTree;
22096     if (tree->gtOper == GT_CALL)
22097     {
22098         Compiler*    compiler = data->compiler;
22099         GenTreeStmt* stmt     = (GenTreeStmt*)data->pCallbackData;
22100         GenTreeCall* call     = tree->AsCall();
22101
22102         compiler->fgNoteNonInlineCandidate(stmt, call);
22103     }
22104     return WALK_CONTINUE;
22105 }
22106
22107 //------------------------------------------------------------------------
22108 // fgNoteNonInlineCandidate: account for inlining failures in calls
22109 // not marked as inline candidates.
22110 //
22111 // Arguments:
22112 //    stmt  - statement containing the call
22113 //    call  - the call itself
22114 //
22115 // Notes:
22116 //    Used in debug only to try and place descriptions of inline failures
22117 //    into the proper context in the inline tree.
22118
22119 void Compiler::fgNoteNonInlineCandidate(GenTreeStmt* stmt, GenTreeCall* call)
22120 {
22121     InlineResult      inlineResult(this, call, nullptr, "fgNotInlineCandidate");
22122     InlineObservation currentObservation = InlineObservation::CALLSITE_NOT_CANDIDATE;
22123
22124     // Try and recover the reason left behind when the jit decided
22125     // this call was not a candidate.
22126     InlineObservation priorObservation = call->gtInlineObservation;
22127
22128     if (InlIsValidObservation(priorObservation))
22129     {
22130         currentObservation = priorObservation;
22131     }
22132
22133     // Propagate the prior failure observation to this result.
22134     inlineResult.NotePriorFailure(currentObservation);
22135     inlineResult.SetReported();
22136
22137     if (call->gtCallType == CT_USER_FUNC)
22138     {
22139         // Create InlineContext for the failure
22140         m_inlineStrategy->NewFailure(stmt, &inlineResult);
22141     }
22142 }
22143
22144 #endif
22145
22146 #if FEATURE_MULTIREG_RET
22147
22148 /*********************************************************************************
22149  *
22150  * tree - The node which needs to be converted to a struct pointer.
22151  *
22152  *  Return the pointer by either __replacing__ the tree node with a suitable pointer
22153  *  type or __without replacing__ and just returning a subtree or by __modifying__
22154  *  a subtree.
22155  */
22156 GenTree* Compiler::fgGetStructAsStructPtr(GenTree* tree)
22157 {
22158     noway_assert((tree->gtOper == GT_LCL_VAR) || (tree->gtOper == GT_FIELD) || (tree->gtOper == GT_IND) ||
22159                  (tree->gtOper == GT_BLK) || (tree->gtOper == GT_OBJ) || tree->OperIsSIMD() ||
22160                  // tree->gtOper == GT_CALL     || cannot get address of call.
22161                  // tree->gtOper == GT_MKREFANY || inlining should've been aborted due to mkrefany opcode.
22162                  // tree->gtOper == GT_RET_EXPR || cannot happen after fgUpdateInlineReturnExpressionPlaceHolder
22163                  (tree->gtOper == GT_COMMA));
22164
22165     switch (tree->OperGet())
22166     {
22167         case GT_BLK:
22168         case GT_OBJ:
22169         case GT_IND:
22170             return tree->gtOp.gtOp1;
22171
22172         case GT_COMMA:
22173             tree->gtOp.gtOp2 = fgGetStructAsStructPtr(tree->gtOp.gtOp2);
22174             tree->gtType     = TYP_BYREF;
22175             return tree;
22176
22177         default:
22178             return gtNewOperNode(GT_ADDR, TYP_BYREF, tree);
22179     }
22180 }
22181
22182 /***************************************************************************************************
22183  * child     - The inlinee of the retExpr node.
22184  * retClsHnd - The struct class handle of the type of the inlinee.
22185  *
22186  * Assign the inlinee to a tmp, if it is a call, just assign it to a lclVar, else we can
22187  * use a copyblock to do the assignment.
22188  */
22189 GenTree* Compiler::fgAssignStructInlineeToVar(GenTree* child, CORINFO_CLASS_HANDLE retClsHnd)
22190 {
22191     assert(child->gtOper != GT_RET_EXPR && child->gtOper != GT_MKREFANY);
22192
22193     unsigned tmpNum = lvaGrabTemp(false DEBUGARG("RetBuf for struct inline return candidates."));
22194     lvaSetStruct(tmpNum, retClsHnd, false);
22195     var_types structType = lvaTable[tmpNum].lvType;
22196
22197     GenTree* dst = gtNewLclvNode(tmpNum, structType);
22198
22199     // If we have a call, we'd like it to be: V00 = call(), but first check if
22200     // we have a ", , , call()" -- this is very defensive as we may never get
22201     // an inlinee that is made of commas. If the inlinee is not a call, then
22202     // we use a copy block to do the assignment.
22203     GenTree* src       = child;
22204     GenTree* lastComma = nullptr;
22205     while (src->gtOper == GT_COMMA)
22206     {
22207         lastComma = src;
22208         src       = src->gtOp.gtOp2;
22209     }
22210
22211     GenTree* newInlinee = nullptr;
22212     if (src->gtOper == GT_CALL)
22213     {
22214         // If inlinee was just a call, new inlinee is v05 = call()
22215         newInlinee = gtNewAssignNode(dst, src);
22216
22217         // When returning a multi-register value in a local var, make sure the variable is
22218         // marked as lvIsMultiRegRet, so it does not get promoted.
22219         if (src->AsCall()->HasMultiRegRetVal())
22220         {
22221             lvaTable[tmpNum].lvIsMultiRegRet = true;
22222         }
22223
22224         // If inlinee was comma, but a deeper call, new inlinee is (, , , v05 = call())
22225         if (child->gtOper == GT_COMMA)
22226         {
22227             lastComma->gtOp.gtOp2 = newInlinee;
22228             newInlinee            = child;
22229         }
22230     }
22231     else
22232     {
22233         // Inlinee is not a call, so just create a copy block to the tmp.
22234         src              = child;
22235         GenTree* dstAddr = fgGetStructAsStructPtr(dst);
22236         GenTree* srcAddr = fgGetStructAsStructPtr(src);
22237         newInlinee       = gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false);
22238     }
22239
22240     GenTree* production = gtNewLclvNode(tmpNum, structType);
22241     return gtNewOperNode(GT_COMMA, structType, newInlinee, production);
22242 }
22243
22244 /***************************************************************************************************
22245  * tree      - The tree pointer that has one of its child nodes as retExpr.
22246  * child     - The inlinee child.
22247  * retClsHnd - The struct class handle of the type of the inlinee.
22248  *
22249  * V04 = call() assignments are okay as we codegen it. Everything else needs to be a copy block or
22250  * would need a temp. For example, a cast(ldobj) will then be, cast(v05 = ldobj, v05); But it is
22251  * a very rare (or impossible) scenario that we'd have a retExpr transform into a ldobj other than
22252  * a lclVar/call. So it is not worthwhile to do pattern matching optimizations like addr(ldobj(op1))
22253  * can just be op1.
22254  */
22255 void Compiler::fgAttachStructInlineeToAsg(GenTree* tree, GenTree* child, CORINFO_CLASS_HANDLE retClsHnd)
22256 {
22257     // We are okay to have:
22258     // 1. V02 = call();
22259     // 2. copyBlk(dstAddr, srcAddr);
22260     assert(tree->gtOper == GT_ASG);
22261
22262     // We have an assignment, we codegen only V05 = call().
22263     if (child->gtOper == GT_CALL && tree->gtOp.gtOp1->gtOper == GT_LCL_VAR)
22264     {
22265         // If it is a multireg return on x64/ux, the local variable should be marked as lvIsMultiRegRet
22266         if (child->AsCall()->HasMultiRegRetVal())
22267         {
22268             unsigned lclNum                  = tree->gtOp.gtOp1->gtLclVarCommon.gtLclNum;
22269             lvaTable[lclNum].lvIsMultiRegRet = true;
22270         }
22271         return;
22272     }
22273
22274     GenTree* dstAddr = fgGetStructAsStructPtr(tree->gtOp.gtOp1);
22275     GenTree* srcAddr = fgGetStructAsStructPtr(
22276         (child->gtOper == GT_CALL)
22277             ? fgAssignStructInlineeToVar(child, retClsHnd) // Assign to a variable if it is a call.
22278             : child);                                      // Just get the address, if not a call.
22279
22280     tree->ReplaceWith(gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false), this);
22281 }
22282
22283 #endif // FEATURE_MULTIREG_RET
22284
22285 //------------------------------------------------------------------------
22286 // fgUpdateInlineReturnExpressionPlaceHolder: callback to replace the
22287 // inline return expression placeholder.
22288 //
22289 // Arguments:
22290 //    pTree -- pointer to tree to examine for updates
22291 //    data  -- context data for the tree walk
22292 //
22293 // Returns:
22294 //    fgWalkResult indicating the walk should continue; that
22295 //    is we wish to fully explore the tree.
22296 //
22297 // Notes:
22298 //    Looks for GT_RET_EXPR nodes that arose from tree splitting done
22299 //    during importation for inline candidates, and replaces them.
22300 //
22301 //    For successful inlines, substitutes the return value expression
22302 //    from the inline body for the GT_RET_EXPR.
22303 //
22304 //    For failed inlines, rejoins the original call into the tree from
22305 //    whence it was split during importation.
22306 //
22307 //    The code doesn't actually know if the corresponding inline
22308 //    succeeded or not; it relies on the fact that gtInlineCandidate
22309 //    initially points back at the call and is modified in place to
22310 //    the inlinee return expression if the inline is successful (see
22311 //    tail end of fgInsertInlineeBlocks for the update of iciCall).
22312 //
22313 //    If the parent of the GT_RET_EXPR is a virtual call,
22314 //    devirtualization is attempted. This should only succeed in the
22315 //    successful inline case, when the inlinee's return value
22316 //    expression provides a better type than the return type of the
22317 //    method. Note for failed inlines, the devirtualizer can only go
22318 //    by the return type, and any devirtualization that type enabled
22319 //    would have already happened during importation.
22320 //
22321 //    If the return type is a struct type and we're on a platform
22322 //    where structs can be returned in multiple registers, ensure the
22323 //    call has a suitable parent.
22324
22325 Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTree** pTree, fgWalkData* data)
22326 {
22327     GenTree*             tree      = *pTree;
22328     Compiler*            comp      = data->compiler;
22329     CORINFO_CLASS_HANDLE retClsHnd = NO_CLASS_HANDLE;
22330
22331     if (tree->gtOper == GT_RET_EXPR)
22332     {
22333         // We are going to copy the tree from the inlinee,
22334         // so record the handle now.
22335         //
22336         if (varTypeIsStruct(tree))
22337         {
22338             retClsHnd = tree->gtRetExpr.gtRetClsHnd;
22339         }
22340
22341         do
22342         {
22343             // Obtained the expanded inline candidate
22344             GenTree* inlineCandidate = tree->gtRetExpr.gtInlineCandidate;
22345
22346 #ifdef DEBUG
22347             if (comp->verbose)
22348             {
22349                 printf("\nReplacing the return expression placeholder ");
22350                 printTreeID(tree);
22351                 printf(" with ");
22352                 printTreeID(inlineCandidate);
22353                 printf("\n");
22354                 // Dump out the old return expression placeholder it will be overwritten by the ReplaceWith below
22355                 comp->gtDispTree(tree);
22356             }
22357 #endif // DEBUG
22358
22359             tree->ReplaceWith(inlineCandidate, comp);
22360
22361 #ifdef DEBUG
22362             if (comp->verbose)
22363             {
22364                 printf("\nInserting the inline return expression\n");
22365                 comp->gtDispTree(tree);
22366                 printf("\n");
22367             }
22368 #endif // DEBUG
22369         } while (tree->gtOper == GT_RET_EXPR);
22370
22371         // Now see if this return value expression feeds the 'this'
22372         // object at a virtual call site.
22373         //
22374         // Note for void returns where the inline failed, the
22375         // GT_RET_EXPR may be top-level.
22376         //
22377         // May miss cases where there are intermediaries between call
22378         // and this, eg commas.
22379         GenTree* parentTree = data->parent;
22380
22381         if ((parentTree != nullptr) && (parentTree->gtOper == GT_CALL))
22382         {
22383             GenTreeCall* call  = parentTree->AsCall();
22384             bool tryLateDevirt = call->IsVirtual() && (call->gtCallObjp == tree) && (call->gtCallType == CT_USER_FUNC);
22385
22386 #ifdef DEBUG
22387             tryLateDevirt = tryLateDevirt && (JitConfig.JitEnableLateDevirtualization() == 1);
22388 #endif // DEBUG
22389
22390             if (tryLateDevirt)
22391             {
22392 #ifdef DEBUG
22393                 if (comp->verbose)
22394                 {
22395                     printf("**** Late devirt opportunity\n");
22396                     comp->gtDispTree(call);
22397                 }
22398 #endif // DEBUG
22399
22400                 CORINFO_METHOD_HANDLE  method      = call->gtCallMethHnd;
22401                 unsigned               methodFlags = 0;
22402                 CORINFO_CONTEXT_HANDLE context     = nullptr;
22403                 comp->impDevirtualizeCall(call, &method, &methodFlags, &context, nullptr);
22404             }
22405         }
22406     }
22407
22408 #if FEATURE_MULTIREG_RET
22409
22410     // Did we record a struct return class handle above?
22411     //
22412     if (retClsHnd != NO_CLASS_HANDLE)
22413     {
22414         // Is this a type that is returned in multiple registers?
22415         // if so we need to force into into a form we accept.
22416         // i.e. LclVar = call()
22417         //
22418         if (comp->IsMultiRegReturnedType(retClsHnd))
22419         {
22420             GenTree* parent = data->parent;
22421             // See assert below, we only look one level above for an asg parent.
22422             if (parent->gtOper == GT_ASG)
22423             {
22424                 // Either lhs is a call V05 = call(); or lhs is addr, and asg becomes a copyBlk.
22425                 comp->fgAttachStructInlineeToAsg(parent, tree, retClsHnd);
22426             }
22427             else
22428             {
22429                 // Just assign the inlinee to a variable to keep it simple.
22430                 tree->ReplaceWith(comp->fgAssignStructInlineeToVar(tree, retClsHnd), comp);
22431             }
22432         }
22433     }
22434
22435 #if defined(DEBUG)
22436
22437     // Make sure we don't have a tree like so: V05 = (, , , retExpr);
22438     // Since we only look one level above for the parent for '=' and
22439     // do not check if there is a series of COMMAs. See above.
22440     // Importer and FlowGraph will not generate such a tree, so just
22441     // leaving an assert in here. This can be fixed by looking ahead
22442     // when we visit GT_ASG similar to fgAttachStructInlineeToAsg.
22443     //
22444     if ((tree->gtOper == GT_ASG) && (tree->gtOp.gtOp2->gtOper == GT_COMMA))
22445     {
22446         GenTree* comma;
22447         for (comma = tree->gtOp.gtOp2; comma->gtOper == GT_COMMA; comma = comma->gtOp.gtOp2)
22448         {
22449             // empty
22450         }
22451
22452         noway_assert(!varTypeIsStruct(comma) || comma->gtOper != GT_RET_EXPR ||
22453                      !comp->IsMultiRegReturnedType(comma->gtRetExpr.gtRetClsHnd));
22454     }
22455
22456 #endif // defined(DEBUG)
22457 #endif // FEATURE_MULTIREG_RET
22458
22459     return WALK_CONTINUE;
22460 }
22461
22462 #ifdef DEBUG
22463
22464 /*****************************************************************************
22465  * Callback to make sure there is no more GT_RET_EXPR and GTF_CALL_INLINE_CANDIDATE nodes.
22466  */
22467
22468 /* static */
22469 Compiler::fgWalkResult Compiler::fgDebugCheckInlineCandidates(GenTree** pTree, fgWalkData* data)
22470 {
22471     GenTree* tree = *pTree;
22472     if (tree->gtOper == GT_CALL)
22473     {
22474         assert((tree->gtFlags & GTF_CALL_INLINE_CANDIDATE) == 0);
22475     }
22476     else
22477     {
22478         assert(tree->gtOper != GT_RET_EXPR);
22479     }
22480
22481     return WALK_CONTINUE;
22482 }
22483
22484 #endif // DEBUG
22485
22486 void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineResult)
22487 {
22488     noway_assert(call->gtOper == GT_CALL);
22489     noway_assert((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0);
22490     noway_assert(opts.OptEnabled(CLFLG_INLINING));
22491
22492     // This is the InlineInfo struct representing a method to be inlined.
22493     InlineInfo inlineInfo;
22494     memset(&inlineInfo, 0, sizeof(inlineInfo));
22495     CORINFO_METHOD_HANDLE fncHandle = call->gtCallMethHnd;
22496
22497     inlineInfo.fncHandle              = fncHandle;
22498     inlineInfo.iciCall                = call;
22499     inlineInfo.iciStmt                = fgMorphStmt;
22500     inlineInfo.iciBlock               = compCurBB;
22501     inlineInfo.thisDereferencedFirst  = false;
22502     inlineInfo.retExpr                = nullptr;
22503     inlineInfo.retExprClassHnd        = nullptr;
22504     inlineInfo.retExprClassHndIsExact = false;
22505     inlineInfo.inlineResult           = inlineResult;
22506 #ifdef FEATURE_SIMD
22507     inlineInfo.hasSIMDTypeArgLocalOrReturn = false;
22508 #endif // FEATURE_SIMD
22509
22510     InlineCandidateInfo* inlineCandidateInfo = call->gtInlineCandidateInfo;
22511     noway_assert(inlineCandidateInfo);
22512     // Store the link to inlineCandidateInfo into inlineInfo
22513     inlineInfo.inlineCandidateInfo = inlineCandidateInfo;
22514
22515     unsigned inlineDepth = fgCheckInlineDepthAndRecursion(&inlineInfo);
22516
22517     if (inlineResult->IsFailure())
22518     {
22519 #ifdef DEBUG
22520         if (verbose)
22521         {
22522             printf("Recursive or deep inline recursion detected. Will not expand this INLINECANDIDATE \n");
22523         }
22524 #endif // DEBUG
22525         return;
22526     }
22527
22528     // Set the trap to catch all errors (including recoverable ones from the EE)
22529     struct Param
22530     {
22531         Compiler*             pThis;
22532         GenTree*              call;
22533         CORINFO_METHOD_HANDLE fncHandle;
22534         InlineCandidateInfo*  inlineCandidateInfo;
22535         InlineInfo*           inlineInfo;
22536     } param;
22537     memset(&param, 0, sizeof(param));
22538
22539     param.pThis               = this;
22540     param.call                = call;
22541     param.fncHandle           = fncHandle;
22542     param.inlineCandidateInfo = inlineCandidateInfo;
22543     param.inlineInfo          = &inlineInfo;
22544     bool success              = eeRunWithErrorTrap<Param>(
22545         [](Param* pParam) {
22546             // Init the local var info of the inlinee
22547             pParam->pThis->impInlineInitVars(pParam->inlineInfo);
22548
22549             if (pParam->inlineInfo->inlineResult->IsCandidate())
22550             {
22551                 /* Clear the temp table */
22552                 memset(pParam->inlineInfo->lclTmpNum, -1, sizeof(pParam->inlineInfo->lclTmpNum));
22553
22554                 //
22555                 // Prepare the call to jitNativeCode
22556                 //
22557
22558                 pParam->inlineInfo->InlinerCompiler = pParam->pThis;
22559                 if (pParam->pThis->impInlineInfo == nullptr)
22560                 {
22561                     pParam->inlineInfo->InlineRoot = pParam->pThis;
22562                 }
22563                 else
22564                 {
22565                     pParam->inlineInfo->InlineRoot = pParam->pThis->impInlineInfo->InlineRoot;
22566                 }
22567                 pParam->inlineInfo->argCnt                   = pParam->inlineCandidateInfo->methInfo.args.totalILArgs();
22568                 pParam->inlineInfo->tokenLookupContextHandle = pParam->inlineCandidateInfo->exactContextHnd;
22569
22570                 JITLOG_THIS(pParam->pThis,
22571                             (LL_INFO100000, "INLINER: inlineInfo.tokenLookupContextHandle for %s set to 0x%p:\n",
22572                              pParam->pThis->eeGetMethodFullName(pParam->fncHandle),
22573                              pParam->pThis->dspPtr(pParam->inlineInfo->tokenLookupContextHandle)));
22574
22575                 JitFlags compileFlagsForInlinee = *pParam->pThis->opts.jitFlags;
22576
22577                 // The following flags are lost when inlining.
22578                 // (This is checked in Compiler::compInitOptions().)
22579                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_BBOPT);
22580                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_BBINSTR);
22581                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_PROF_ENTERLEAVE);
22582                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_EnC);
22583                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_INFO);
22584
22585                 compileFlagsForInlinee.Set(JitFlags::JIT_FLAG_SKIP_VERIFICATION);
22586
22587 #ifdef DEBUG
22588                 if (pParam->pThis->verbose)
22589                 {
22590                     printf("\nInvoking compiler for the inlinee method %s :\n",
22591                            pParam->pThis->eeGetMethodFullName(pParam->fncHandle));
22592                 }
22593 #endif // DEBUG
22594
22595                 int result =
22596                     jitNativeCode(pParam->fncHandle, pParam->inlineCandidateInfo->methInfo.scope,
22597                                   pParam->pThis->info.compCompHnd, &pParam->inlineCandidateInfo->methInfo,
22598                                   (void**)pParam->inlineInfo, nullptr, &compileFlagsForInlinee, pParam->inlineInfo);
22599
22600                 if (result != CORJIT_OK)
22601                 {
22602                     // If we haven't yet determined why this inline fails, use
22603                     // a catch-all something bad happened observation.
22604                     InlineResult* innerInlineResult = pParam->inlineInfo->inlineResult;
22605
22606                     if (!innerInlineResult->IsFailure())
22607                     {
22608                         innerInlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_FAILURE);
22609                     }
22610                 }
22611             }
22612         },
22613         &param);
22614     if (!success)
22615     {
22616 #ifdef DEBUG
22617         if (verbose)
22618         {
22619             printf("\nInlining failed due to an exception during invoking the compiler for the inlinee method %s.\n",
22620                    eeGetMethodFullName(fncHandle));
22621         }
22622 #endif // DEBUG
22623
22624         // If we haven't yet determined why this inline fails, use
22625         // a catch-all something bad happened observation.
22626         if (!inlineResult->IsFailure())
22627         {
22628             inlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_ERROR);
22629         }
22630     }
22631
22632     if (inlineResult->IsFailure())
22633     {
22634         return;
22635     }
22636
22637 #ifdef DEBUG
22638     if (0 && verbose)
22639     {
22640         printf("\nDone invoking compiler for the inlinee method %s\n", eeGetMethodFullName(fncHandle));
22641     }
22642 #endif // DEBUG
22643
22644     // If there is non-NULL return, but we haven't set the pInlineInfo->retExpr,
22645     // That means we haven't imported any BB that contains CEE_RET opcode.
22646     // (This could happen for example for a BBJ_THROW block fall through a BBJ_RETURN block which
22647     // causes the BBJ_RETURN block not to be imported at all.)
22648     // Fail the inlining attempt
22649     if (inlineCandidateInfo->fncRetType != TYP_VOID && inlineInfo.retExpr == nullptr)
22650     {
22651 #ifdef DEBUG
22652         if (verbose)
22653         {
22654             printf("\nInlining failed because pInlineInfo->retExpr is not set in the inlinee method %s.\n",
22655                    eeGetMethodFullName(fncHandle));
22656         }
22657 #endif // DEBUG
22658         inlineResult->NoteFatal(InlineObservation::CALLEE_LACKS_RETURN);
22659         return;
22660     }
22661
22662     if (inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_SPECULATIVE)
22663     {
22664         // we defer the call to initClass() until inlining is completed in case it fails. If inlining succeeds,
22665         // we will call initClass().
22666         if (!(info.compCompHnd->initClass(nullptr /* field */, fncHandle /* method */,
22667                                           inlineCandidateInfo->exactContextHnd /* context */) &
22668               CORINFO_INITCLASS_INITIALIZED))
22669         {
22670             inlineResult->NoteFatal(InlineObservation::CALLEE_CLASS_INIT_FAILURE);
22671             return;
22672         }
22673     }
22674
22675     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
22676     // The inlining attempt cannot be failed starting from this point.
22677     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
22678
22679     // We've successfully obtain the list of inlinee's basic blocks.
22680     // Let's insert it to inliner's basic block list.
22681     fgInsertInlineeBlocks(&inlineInfo);
22682
22683 #ifdef DEBUG
22684
22685     if (verbose || fgPrintInlinedMethods)
22686     {
22687         printf("Successfully inlined %s (%d IL bytes) (depth %d) [%s]\n", eeGetMethodFullName(fncHandle),
22688                inlineCandidateInfo->methInfo.ILCodeSize, inlineDepth, inlineResult->ReasonString());
22689     }
22690
22691     if (verbose)
22692     {
22693         printf("--------------------------------------------------------------------------------------------\n");
22694     }
22695 #endif // DEBUG
22696
22697 #if defined(DEBUG)
22698     impInlinedCodeSize += inlineCandidateInfo->methInfo.ILCodeSize;
22699 #endif
22700
22701     // We inlined...
22702     inlineResult->NoteSuccess();
22703 }
22704
22705 //------------------------------------------------------------------------
22706 // fgInsertInlineeBlocks: incorporate statements for an inline into the
22707 // root method.
22708 //
22709 // Arguments:
22710 //    inlineInfo -- info for the inline
22711 //
22712 // Notes:
22713 //    The inlining attempt cannot be failed once this method is called.
22714 //
22715 //    Adds all inlinee statements, plus any glue statements needed
22716 //    either before or after the inlined call.
22717 //
22718 //    Updates flow graph and assigns weights to inlinee
22719 //    blocks. Currently does not attempt to read IBC data for the
22720 //    inlinee.
22721 //
22722 //    Updates relevant root method status flags (eg optMethodFlags) to
22723 //    include information from the inlinee.
22724 //
22725 //    Marks newly added statements with an appropriate inline context.
22726
22727 void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo)
22728 {
22729     GenTreeCall* iciCall  = pInlineInfo->iciCall;
22730     GenTreeStmt* iciStmt  = pInlineInfo->iciStmt;
22731     BasicBlock*  iciBlock = pInlineInfo->iciBlock;
22732     BasicBlock*  block;
22733
22734     // We can write better assert here. For example, we can check that
22735     // iciBlock contains iciStmt, which in turn contains iciCall.
22736     noway_assert(iciBlock->bbTreeList != nullptr);
22737     noway_assert(iciStmt->gtStmtExpr != nullptr);
22738     noway_assert(iciCall->gtOper == GT_CALL);
22739
22740 #ifdef DEBUG
22741
22742     GenTree* currentDumpStmt = nullptr;
22743
22744     if (verbose)
22745     {
22746         printf("\n\n----------- Statements (and blocks) added due to the inlining of call ");
22747         printTreeID(iciCall);
22748         printf(" -----------\n");
22749     }
22750
22751 #endif // DEBUG
22752
22753     // Create a new inline context and mark the inlined statements with it
22754     InlineContext* calleeContext = m_inlineStrategy->NewSuccess(pInlineInfo);
22755
22756     for (block = InlineeCompiler->fgFirstBB; block != nullptr; block = block->bbNext)
22757     {
22758         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
22759         {
22760             stmt->gtInlineContext = calleeContext;
22761         }
22762     }
22763
22764     // Prepend statements
22765     GenTree* stmtAfter = fgInlinePrependStatements(pInlineInfo);
22766
22767 #ifdef DEBUG
22768     if (verbose)
22769     {
22770         currentDumpStmt = stmtAfter;
22771         printf("\nInlinee method body:");
22772     }
22773 #endif // DEBUG
22774
22775     BasicBlock* topBlock    = iciBlock;
22776     BasicBlock* bottomBlock = nullptr;
22777
22778     if (InlineeCompiler->fgBBcount == 1)
22779     {
22780         // When fgBBCount is 1 we will always have a non-NULL fgFirstBB
22781         //
22782         PREFAST_ASSUME(InlineeCompiler->fgFirstBB != nullptr);
22783
22784         // DDB 91389: Don't throw away the (only) inlinee block
22785         // when its return type is not BBJ_RETURN.
22786         // In other words, we need its BBJ_ to perform the right thing.
22787         if (InlineeCompiler->fgFirstBB->bbJumpKind == BBJ_RETURN)
22788         {
22789             // Inlinee contains just one BB. So just insert its statement list to topBlock.
22790             if (InlineeCompiler->fgFirstBB->bbTreeList)
22791             {
22792                 stmtAfter = fgInsertStmtListAfter(iciBlock, stmtAfter, InlineeCompiler->fgFirstBB->bbTreeList);
22793
22794                 // Copy inlinee bbFlags to caller bbFlags.
22795                 const unsigned __int64 inlineeBlockFlags = InlineeCompiler->fgFirstBB->bbFlags;
22796                 noway_assert((inlineeBlockFlags & BBF_HAS_JMP) == 0);
22797                 noway_assert((inlineeBlockFlags & BBF_KEEP_BBJ_ALWAYS) == 0);
22798                 iciBlock->bbFlags |= inlineeBlockFlags;
22799             }
22800
22801 #ifdef DEBUG
22802             if (verbose)
22803             {
22804                 noway_assert(currentDumpStmt);
22805
22806                 if (currentDumpStmt != stmtAfter)
22807                 {
22808                     do
22809                     {
22810                         currentDumpStmt = currentDumpStmt->gtNext;
22811
22812                         printf("\n");
22813
22814                         noway_assert(currentDumpStmt->gtOper == GT_STMT);
22815
22816                         gtDispTree(currentDumpStmt);
22817                         printf("\n");
22818
22819                     } while (currentDumpStmt != stmtAfter);
22820                 }
22821             }
22822 #endif // DEBUG
22823
22824             // Append statements to null out gc ref locals, if necessary.
22825             fgInlineAppendStatements(pInlineInfo, iciBlock, stmtAfter);
22826
22827             goto _Done;
22828         }
22829     }
22830
22831     //
22832     // ======= Inserting inlinee's basic blocks ===============
22833     //
22834
22835     bottomBlock             = fgNewBBafter(topBlock->bbJumpKind, topBlock, true);
22836     bottomBlock->bbRefs     = 1;
22837     bottomBlock->bbJumpDest = topBlock->bbJumpDest;
22838     bottomBlock->inheritWeight(topBlock);
22839
22840     topBlock->bbJumpKind = BBJ_NONE;
22841
22842     // Update block flags
22843     {
22844         const unsigned __int64 originalFlags = topBlock->bbFlags;
22845         noway_assert((originalFlags & BBF_SPLIT_NONEXIST) == 0);
22846         topBlock->bbFlags &= ~(BBF_SPLIT_LOST);
22847         bottomBlock->bbFlags |= originalFlags & BBF_SPLIT_GAINED;
22848     }
22849
22850     //
22851     // Split statements between topBlock and bottomBlock
22852     //
22853     GenTree* topBlock_Begin;
22854     GenTree* topBlock_End;
22855     GenTree* bottomBlock_Begin;
22856     GenTree* bottomBlock_End;
22857
22858     topBlock_Begin    = nullptr;
22859     topBlock_End      = nullptr;
22860     bottomBlock_Begin = nullptr;
22861     bottomBlock_End   = nullptr;
22862
22863     //
22864     // First figure out bottomBlock_Begin
22865     //
22866
22867     bottomBlock_Begin = stmtAfter->gtNext;
22868
22869     if (topBlock->bbTreeList == nullptr)
22870     {
22871         // topBlock is empty before the split.
22872         // In this case, both topBlock and bottomBlock should be empty
22873         noway_assert(bottomBlock_Begin == nullptr);
22874         topBlock->bbTreeList    = nullptr;
22875         bottomBlock->bbTreeList = nullptr;
22876     }
22877     else if (topBlock->bbTreeList == bottomBlock_Begin)
22878     {
22879         noway_assert(bottomBlock_Begin);
22880
22881         // topBlock contains at least one statement before the split.
22882         // And the split is before the first statement.
22883         // In this case, topBlock should be empty, and everything else should be moved to the bottonBlock.
22884         bottomBlock->bbTreeList = topBlock->bbTreeList;
22885         topBlock->bbTreeList    = nullptr;
22886     }
22887     else if (bottomBlock_Begin == nullptr)
22888     {
22889         noway_assert(topBlock->bbTreeList);
22890
22891         // topBlock contains at least one statement before the split.
22892         // And the split is at the end of the topBlock.
22893         // In this case, everything should be kept in the topBlock, and the bottomBlock should be empty
22894
22895         bottomBlock->bbTreeList = nullptr;
22896     }
22897     else
22898     {
22899         noway_assert(topBlock->bbTreeList);
22900         noway_assert(bottomBlock_Begin);
22901
22902         // This is the normal case where both blocks should contain at least one statement.
22903         topBlock_Begin = topBlock->bbTreeList;
22904         noway_assert(topBlock_Begin);
22905         topBlock_End = bottomBlock_Begin->gtPrev;
22906         noway_assert(topBlock_End);
22907         bottomBlock_End = topBlock->lastStmt();
22908         noway_assert(bottomBlock_End);
22909
22910         // Break the linkage between 2 blocks.
22911         topBlock_End->gtNext = nullptr;
22912
22913         // Fix up all the pointers.
22914         topBlock->bbTreeList         = topBlock_Begin;
22915         topBlock->bbTreeList->gtPrev = topBlock_End;
22916
22917         bottomBlock->bbTreeList         = bottomBlock_Begin;
22918         bottomBlock->bbTreeList->gtPrev = bottomBlock_End;
22919     }
22920
22921     //
22922     // Set the try and handler index and fix the jump types of inlinee's blocks.
22923     //
22924
22925     bool inheritWeight;
22926     inheritWeight = true; // The firstBB does inherit the weight from the iciBlock
22927
22928     for (block = InlineeCompiler->fgFirstBB; block != nullptr; block = block->bbNext)
22929     {
22930         noway_assert(!block->hasTryIndex());
22931         noway_assert(!block->hasHndIndex());
22932         block->copyEHRegion(iciBlock);
22933         block->bbFlags |= iciBlock->bbFlags & BBF_BACKWARD_JUMP;
22934
22935         if (iciStmt->gtStmtILoffsx != BAD_IL_OFFSET)
22936         {
22937             block->bbCodeOffs    = jitGetILoffs(iciStmt->gtStmtILoffsx);
22938             block->bbCodeOffsEnd = block->bbCodeOffs + 1; // TODO: is code size of 1 some magic number for inlining?
22939         }
22940         else
22941         {
22942             block->bbCodeOffs    = 0; // TODO: why not BAD_IL_OFFSET?
22943             block->bbCodeOffsEnd = 0;
22944             block->bbFlags |= BBF_INTERNAL;
22945         }
22946
22947         if (block->bbJumpKind == BBJ_RETURN)
22948         {
22949             inheritWeight = true; // A return block does inherit the weight from the iciBlock
22950             noway_assert((block->bbFlags & BBF_HAS_JMP) == 0);
22951             if (block->bbNext)
22952             {
22953                 block->bbJumpKind = BBJ_ALWAYS;
22954                 block->bbJumpDest = bottomBlock;
22955 #ifdef DEBUG
22956                 if (verbose)
22957                 {
22958                     printf("\nConvert bbJumpKind of BB%02u to BBJ_ALWAYS to bottomBlock BB%02u\n", block->bbNum,
22959                            bottomBlock->bbNum);
22960                 }
22961 #endif // DEBUG
22962             }
22963             else
22964             {
22965 #ifdef DEBUG
22966                 if (verbose)
22967                 {
22968                     printf("\nConvert bbJumpKind of BB%02u to BBJ_NONE\n", block->bbNum);
22969                 }
22970 #endif // DEBUG
22971                 block->bbJumpKind = BBJ_NONE;
22972             }
22973         }
22974         if (inheritWeight)
22975         {
22976             block->inheritWeight(iciBlock);
22977             inheritWeight = false;
22978         }
22979         else
22980         {
22981             block->modifyBBWeight(iciBlock->bbWeight / 2);
22982         }
22983     }
22984
22985     // Insert inlinee's blocks into inliner's block list.
22986     topBlock->setNext(InlineeCompiler->fgFirstBB);
22987     InlineeCompiler->fgLastBB->setNext(bottomBlock);
22988
22989     //
22990     // Add inlinee's block count to inliner's.
22991     //
22992     fgBBcount += InlineeCompiler->fgBBcount;
22993
22994     // Append statements to null out gc ref locals, if necessary.
22995     fgInlineAppendStatements(pInlineInfo, bottomBlock, nullptr);
22996
22997 #ifdef DEBUG
22998     if (verbose)
22999     {
23000         fgDispBasicBlocks(InlineeCompiler->fgFirstBB, InlineeCompiler->fgLastBB, true);
23001     }
23002 #endif // DEBUG
23003
23004 _Done:
23005
23006     //
23007     // At this point, we have successully inserted inlinee's code.
23008     //
23009
23010     //
23011     // Copy out some flags
23012     //
23013     compLongUsed |= InlineeCompiler->compLongUsed;
23014     compFloatingPointUsed |= InlineeCompiler->compFloatingPointUsed;
23015     compLocallocUsed |= InlineeCompiler->compLocallocUsed;
23016     compLocallocOptimized |= InlineeCompiler->compLocallocOptimized;
23017     compQmarkUsed |= InlineeCompiler->compQmarkUsed;
23018     compUnsafeCastUsed |= InlineeCompiler->compUnsafeCastUsed;
23019     compNeedsGSSecurityCookie |= InlineeCompiler->compNeedsGSSecurityCookie;
23020     compGSReorderStackLayout |= InlineeCompiler->compGSReorderStackLayout;
23021
23022 #ifdef FEATURE_SIMD
23023     if (InlineeCompiler->usesSIMDTypes())
23024     {
23025         setUsesSIMDTypes(true);
23026     }
23027 #endif // FEATURE_SIMD
23028
23029     // Update unmanaged call count
23030     info.compCallUnmanaged += InlineeCompiler->info.compCallUnmanaged;
23031
23032 // Update optMethodFlags
23033
23034 #ifdef DEBUG
23035     unsigned optMethodFlagsBefore = optMethodFlags;
23036 #endif
23037
23038     optMethodFlags |= InlineeCompiler->optMethodFlags;
23039
23040 #ifdef DEBUG
23041     if (optMethodFlags != optMethodFlagsBefore)
23042     {
23043         JITDUMP("INLINER: Updating optMethodFlags --  root:%0x callee:%0x new:%0x\n", optMethodFlagsBefore,
23044                 InlineeCompiler->optMethodFlags, optMethodFlags);
23045     }
23046 #endif
23047
23048     // If there is non-NULL return, replace the GT_CALL with its return value expression,
23049     // so later it will be picked up by the GT_RET_EXPR node.
23050     if ((pInlineInfo->inlineCandidateInfo->fncRetType != TYP_VOID) || (iciCall->gtReturnType == TYP_STRUCT))
23051     {
23052         noway_assert(pInlineInfo->retExpr);
23053 #ifdef DEBUG
23054         if (verbose)
23055         {
23056             printf("\nReturn expression for call at ");
23057             printTreeID(iciCall);
23058             printf(" is\n");
23059             gtDispTree(pInlineInfo->retExpr);
23060         }
23061 #endif // DEBUG
23062         // Replace the call with the return expression
23063         iciCall->ReplaceWith(pInlineInfo->retExpr, this);
23064     }
23065
23066     //
23067     // Detach the GT_CALL node from the original statement by hanging a "nothing" node under it,
23068     // so that fgMorphStmts can remove the statement once we return from here.
23069     //
23070     iciStmt->gtStmtExpr = gtNewNothingNode();
23071 }
23072
23073 //------------------------------------------------------------------------
23074 // fgInlinePrependStatements: prepend statements needed to match up
23075 // caller and inlined callee
23076 //
23077 // Arguments:
23078 //    inlineInfo -- info for the inline
23079 //
23080 // Return Value:
23081 //    The last statement that was added, or the original call if no
23082 //    statements were added.
23083 //
23084 // Notes:
23085 //    Statements prepended may include the following:
23086 //    * This pointer null check
23087 //    * Class initialization
23088 //    * Zeroing of must-init locals in the callee
23089 //    * Passing of call arguments via temps
23090 //
23091 //    Newly added statements are placed just after the original call
23092 //    and are are given the same inline context as the call any calls
23093 //    added here will appear to have been part of the immediate caller.
23094
23095 GenTree* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
23096 {
23097     BasicBlock*  block        = inlineInfo->iciBlock;
23098     GenTreeStmt* callStmt     = inlineInfo->iciStmt;
23099     IL_OFFSETX   callILOffset = callStmt->gtStmtILoffsx;
23100     GenTreeStmt* postStmt     = callStmt->gtNextStmt;
23101     GenTree*     afterStmt    = callStmt; // afterStmt is the place where the new statements should be inserted after.
23102     GenTree*     newStmt      = nullptr;
23103     GenTreeCall* call         = inlineInfo->iciCall->AsCall();
23104
23105     noway_assert(call->gtOper == GT_CALL);
23106
23107 #ifdef DEBUG
23108     if (0 && verbose)
23109     {
23110         printf("\nfgInlinePrependStatements for iciCall= ");
23111         printTreeID(call);
23112         printf(":\n");
23113     }
23114 #endif
23115
23116     // Prepend statements for any initialization / side effects
23117
23118     InlArgInfo*    inlArgInfo = inlineInfo->inlArgInfo;
23119     InlLclVarInfo* lclVarInfo = inlineInfo->lclVarInfo;
23120
23121     GenTree* tree;
23122
23123     // Create the null check statement (but not appending it to the statement list yet) for the 'this' pointer if
23124     // necessary.
23125     // The NULL check should be done after "argument setup statements".
23126     // The only reason we move it here is for calling "impInlineFetchArg(0,..." to reserve a temp
23127     // for the "this" pointer.
23128     // Note: Here we no longer do the optimization that was done by thisDereferencedFirst in the old inliner.
23129     // However the assetionProp logic will remove any unecessary null checks that we may have added
23130     //
23131     GenTree* nullcheck = nullptr;
23132
23133     if (call->gtFlags & GTF_CALL_NULLCHECK && !inlineInfo->thisDereferencedFirst)
23134     {
23135         // Call impInlineFetchArg to "reserve" a temp for the "this" pointer.
23136         nullcheck = gtNewOperNode(GT_IND, TYP_INT, impInlineFetchArg(0, inlArgInfo, lclVarInfo));
23137         nullcheck->gtFlags |= GTF_EXCEPT;
23138
23139         // The NULL-check statement will be inserted to the statement list after those statements
23140         // that assign arguments to temps and before the actual body of the inlinee method.
23141     }
23142
23143     /* Treat arguments that had to be assigned to temps */
23144     if (inlineInfo->argCnt)
23145     {
23146
23147 #ifdef DEBUG
23148         if (verbose)
23149         {
23150             printf("\nArguments setup:\n");
23151         }
23152 #endif // DEBUG
23153
23154         for (unsigned argNum = 0; argNum < inlineInfo->argCnt; argNum++)
23155         {
23156             const InlArgInfo& argInfo        = inlArgInfo[argNum];
23157             const bool        argIsSingleDef = !argInfo.argHasLdargaOp && !argInfo.argHasStargOp;
23158             GenTree* const    argNode        = inlArgInfo[argNum].argNode;
23159
23160             if (argInfo.argHasTmp)
23161             {
23162                 noway_assert(argInfo.argIsUsed);
23163
23164                 /* argBashTmpNode is non-NULL iff the argument's value was
23165                    referenced exactly once by the original IL. This offers an
23166                    oppportunity to avoid an intermediate temp and just insert
23167                    the original argument tree.
23168
23169                    However, if the temp node has been cloned somewhere while
23170                    importing (e.g. when handling isinst or dup), or if the IL
23171                    took the address of the argument, then argBashTmpNode will
23172                    be set (because the value was only explicitly retrieved
23173                    once) but the optimization cannot be applied.
23174                  */
23175
23176                 GenTree* argSingleUseNode = argInfo.argBashTmpNode;
23177
23178                 if ((argSingleUseNode != nullptr) && !(argSingleUseNode->gtFlags & GTF_VAR_CLONED) && argIsSingleDef)
23179                 {
23180                     // Change the temp in-place to the actual argument.
23181                     // We currently do not support this for struct arguments, so it must not be a GT_OBJ.
23182                     assert(argNode->gtOper != GT_OBJ);
23183                     argSingleUseNode->ReplaceWith(argNode, this);
23184                     continue;
23185                 }
23186                 else
23187                 {
23188                     // We're going to assign the argument value to the
23189                     // temp we use for it in the inline body.
23190                     const unsigned  tmpNum  = argInfo.argTmpNum;
23191                     const var_types argType = lclVarInfo[argNum].lclTypeInfo;
23192
23193                     // Create the temp assignment for this argument
23194                     CORINFO_CLASS_HANDLE structHnd = DUMMY_INIT(0);
23195
23196                     if (varTypeIsStruct(argType))
23197                     {
23198                         structHnd = gtGetStructHandleIfPresent(argNode);
23199                         noway_assert(structHnd != NO_CLASS_HANDLE);
23200                     }
23201
23202                     // Unsafe value cls check is not needed for
23203                     // argTmpNum here since in-linee compiler instance
23204                     // would have iterated over these and marked them
23205                     // accordingly.
23206                     impAssignTempGen(tmpNum, argNode, structHnd, (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset,
23207                                      block);
23208
23209                     // We used to refine the temp type here based on
23210                     // the actual arg, but we now do this up front, when
23211                     // creating the temp, over in impInlineFetchArg.
23212                     CLANG_FORMAT_COMMENT_ANCHOR;
23213
23214 #ifdef DEBUG
23215                     if (verbose)
23216                     {
23217                         gtDispTree(afterStmt);
23218                     }
23219 #endif // DEBUG
23220                 }
23221             }
23222             else if (argInfo.argIsByRefToStructLocal)
23223             {
23224                 // Do nothing. Arg was directly substituted as we read
23225                 // the inlinee.
23226             }
23227             else
23228             {
23229                 /* The argument is either not used or a const or lcl var */
23230
23231                 noway_assert(!argInfo.argIsUsed || argInfo.argIsInvariant || argInfo.argIsLclVar);
23232
23233                 /* Make sure we didnt change argNode's along the way, or else
23234                    subsequent uses of the arg would have worked with the bashed value */
23235                 if (argInfo.argIsInvariant)
23236                 {
23237                     assert(argNode->OperIsConst() || argNode->gtOper == GT_ADDR);
23238                 }
23239                 noway_assert((argInfo.argIsLclVar == 0) ==
23240                              (argNode->gtOper != GT_LCL_VAR || (argNode->gtFlags & GTF_GLOB_REF)));
23241
23242                 /* If the argument has side effects, append it */
23243
23244                 if (argInfo.argHasSideEff)
23245                 {
23246                     noway_assert(argInfo.argIsUsed == false);
23247                     newStmt     = nullptr;
23248                     bool append = true;
23249
23250                     if (argNode->gtOper == GT_OBJ || argNode->gtOper == GT_MKREFANY)
23251                     {
23252                         // Don't put GT_OBJ node under a GT_COMMA.
23253                         // Codegen can't deal with it.
23254                         // Just hang the address here in case there are side-effect.
23255                         newStmt = gtNewStmt(gtUnusedValNode(argNode->gtOp.gtOp1), callILOffset);
23256                     }
23257                     else
23258                     {
23259                         // In some special cases, unused args with side effects can
23260                         // trigger further changes.
23261                         //
23262                         // (1) If the arg is a static field access and the field access
23263                         // was produced by a call to EqualityComparer<T>.get_Default, the
23264                         // helper call to ensure the field has a value can be suppressed.
23265                         // This helper call is marked as a "Special DCE" helper during
23266                         // importation, over in fgGetStaticsCCtorHelper.
23267                         //
23268                         // (2) NYI. If, after tunneling through GT_RET_VALs, we find that
23269                         // the actual arg expression has no side effects, we can skip
23270                         // appending all together. This will help jit TP a bit.
23271                         //
23272                         // Chase through any GT_RET_EXPRs to find the actual argument
23273                         // expression.
23274                         GenTree* actualArgNode = argNode->gtRetExprVal();
23275
23276                         // For case (1)
23277                         //
23278                         // Look for the following tree shapes
23279                         // prejit: (IND (ADD (CONST, CALL(special dce helper...))))
23280                         // jit   : (COMMA (CALL(special dce helper...), (FIELD ...)))
23281                         if (actualArgNode->gtOper == GT_COMMA)
23282                         {
23283                             // Look for (COMMA (CALL(special dce helper...), (FIELD ...)))
23284                             GenTree* op1 = actualArgNode->gtOp.gtOp1;
23285                             GenTree* op2 = actualArgNode->gtOp.gtOp2;
23286                             if (op1->IsCall() && ((op1->gtCall.gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) &&
23287                                 (op2->gtOper == GT_FIELD) && ((op2->gtFlags & GTF_EXCEPT) == 0))
23288                             {
23289                                 JITDUMP("\nPerforming special dce on unused arg [%06u]:"
23290                                         " actual arg [%06u] helper call [%06u]\n",
23291                                         argNode->gtTreeID, actualArgNode->gtTreeID, op1->gtTreeID);
23292                                 // Drop the whole tree
23293                                 append = false;
23294                             }
23295                         }
23296                         else if (actualArgNode->gtOper == GT_IND)
23297                         {
23298                             // Look for (IND (ADD (CONST, CALL(special dce helper...))))
23299                             GenTree* addr = actualArgNode->gtOp.gtOp1;
23300
23301                             if (addr->gtOper == GT_ADD)
23302                             {
23303                                 GenTree* op1 = addr->gtOp.gtOp1;
23304                                 GenTree* op2 = addr->gtOp.gtOp2;
23305                                 if (op1->IsCall() &&
23306                                     ((op1->gtCall.gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) &&
23307                                     op2->IsCnsIntOrI())
23308                                 {
23309                                     // Drop the whole tree
23310                                     JITDUMP("\nPerforming special dce on unused arg [%06u]:"
23311                                             " actual arg [%06u] helper call [%06u]\n",
23312                                             argNode->gtTreeID, actualArgNode->gtTreeID, op1->gtTreeID);
23313                                     append = false;
23314                                 }
23315                             }
23316                         }
23317                     }
23318
23319                     if (!append)
23320                     {
23321                         assert(newStmt == nullptr);
23322                         JITDUMP("Arg tree side effects were discardable, not appending anything for arg\n");
23323                     }
23324                     else
23325                     {
23326                         // If we don't have something custom to append,
23327                         // just append the arg node as an unused value.
23328                         if (newStmt == nullptr)
23329                         {
23330                             newStmt = gtNewStmt(gtUnusedValNode(argNode), callILOffset);
23331                         }
23332
23333                         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
23334 #ifdef DEBUG
23335                         if (verbose)
23336                         {
23337                             gtDispTree(afterStmt);
23338                         }
23339 #endif // DEBUG
23340                     }
23341                 }
23342                 else if (argNode->IsBoxedValue())
23343                 {
23344                     // Try to clean up any unnecessary boxing side effects
23345                     // since the box itself will be ignored.
23346                     gtTryRemoveBoxUpstreamEffects(argNode);
23347                 }
23348             }
23349         }
23350     }
23351
23352     // Add the CCTOR check if asked for.
23353     // Note: We no longer do the optimization that is done before by staticAccessedFirstUsingHelper in the old inliner.
23354     //       Therefore we might prepend redundant call to HELPER.CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
23355     //       before the inlined method body, even if a static field of this type was accessed in the inlinee
23356     //       using a helper before any other observable side-effect.
23357
23358     if (inlineInfo->inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_USE_HELPER)
23359     {
23360         CORINFO_CONTEXT_HANDLE exactContext = inlineInfo->inlineCandidateInfo->exactContextHnd;
23361         CORINFO_CLASS_HANDLE   exactClass;
23362
23363         if (((SIZE_T)exactContext & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
23364         {
23365             exactClass = CORINFO_CLASS_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK);
23366         }
23367         else
23368         {
23369             exactClass = info.compCompHnd->getMethodClass(
23370                 CORINFO_METHOD_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK));
23371         }
23372
23373         tree      = fgGetSharedCCtor(exactClass);
23374         newStmt   = gtNewStmt(tree, callILOffset);
23375         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
23376     }
23377
23378     // Insert the nullcheck statement now.
23379     if (nullcheck)
23380     {
23381         newStmt   = gtNewStmt(nullcheck, callILOffset);
23382         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
23383     }
23384
23385     //
23386     // Now zero-init inlinee locals
23387     //
23388
23389     CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
23390
23391     unsigned lclCnt = InlineeMethodInfo->locals.numArgs;
23392
23393     // Does callee contain any zero-init local?
23394     if ((lclCnt != 0) && (InlineeMethodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0)
23395     {
23396
23397 #ifdef DEBUG
23398         if (verbose)
23399         {
23400             printf("\nZero init inlinee locals:\n");
23401         }
23402 #endif // DEBUG
23403
23404         for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++)
23405         {
23406             unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
23407
23408             // Is the local used at all?
23409             if (tmpNum != BAD_VAR_NUM)
23410             {
23411                 var_types lclTyp = (var_types)lvaTable[tmpNum].lvType;
23412                 noway_assert(lclTyp == lclVarInfo[lclNum + inlineInfo->argCnt].lclTypeInfo);
23413
23414                 if (!varTypeIsStruct(lclTyp))
23415                 {
23416                     // Unsafe value cls check is not needed here since in-linee compiler instance would have
23417                     // iterated over locals and marked accordingly.
23418                     impAssignTempGen(tmpNum, gtNewZeroConNode(genActualType(lclTyp)), NO_CLASS_HANDLE,
23419                                      (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset, block);
23420                 }
23421                 else
23422                 {
23423                     CORINFO_CLASS_HANDLE structType =
23424                         lclVarInfo[lclNum + inlineInfo->argCnt].lclVerTypeInfo.GetClassHandle();
23425
23426                     if (fgStructTempNeedsExplicitZeroInit(lvaTable + tmpNum, block))
23427                     {
23428                         tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp),              // Dest
23429                                               gtNewIconNode(0),                           // Value
23430                                               info.compCompHnd->getClassSize(structType), // Size
23431                                               false,                                      // isVolatile
23432                                               false);                                     // not copyBlock
23433
23434                         newStmt   = gtNewStmt(tree, callILOffset);
23435                         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
23436                     }
23437                 }
23438
23439 #ifdef DEBUG
23440                 if (verbose)
23441                 {
23442                     gtDispTree(afterStmt);
23443                 }
23444 #endif // DEBUG
23445             }
23446         }
23447     }
23448
23449     // Update any newly added statements with the appropriate context.
23450     InlineContext* context = callStmt->gtInlineContext;
23451     assert(context != nullptr);
23452     for (GenTreeStmt* addedStmt = callStmt->gtNextStmt; addedStmt != postStmt; addedStmt = addedStmt->gtNextStmt)
23453     {
23454         assert(addedStmt->gtInlineContext == nullptr);
23455         addedStmt->gtInlineContext = context;
23456     }
23457
23458     return afterStmt;
23459 }
23460
23461 //------------------------------------------------------------------------
23462 // fgInlineAppendStatements: Append statements that are needed
23463 // after the inlined call.
23464 //
23465 // Arguments:
23466 //    inlineInfo - information about the inline
23467 //    block      - basic block for the new statements
23468 //    stmtAfter  - (optional) insertion point for mid-block cases
23469 //
23470 // Notes:
23471 //    If the call we're inlining is in tail position then
23472 //    we skip nulling the locals, since it can interfere
23473 //    with tail calls introduced by the local.
23474
23475 void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTree* stmtAfter)
23476 {
23477     // If this inlinee was passed a runtime lookup generic context and
23478     // ignores it, we can decrement the "generic context was used" ref
23479     // count, because we created a new lookup tree and incremented the
23480     // count when we imported the type parameter argument to pass to
23481     // the inlinee. See corresponding logic in impImportCall that
23482     // checks the sig for CORINFO_CALLCONV_PARAMTYPE.
23483     //
23484     // Does this method require a context (type) parameter?
23485     if ((inlineInfo->inlineCandidateInfo->methInfo.args.callConv & CORINFO_CALLCONV_PARAMTYPE) != 0)
23486     {
23487         // Did the computation of that parameter require the
23488         // caller to perform a runtime lookup?
23489         if (inlineInfo->inlineCandidateInfo->exactContextNeedsRuntimeLookup)
23490         {
23491             // Fetch the temp for the generic context as it would
23492             // appear in the inlinee's body.
23493             const unsigned typeCtxtArg = inlineInfo->typeContextArg;
23494             const unsigned tmpNum      = inlineInfo->lclTmpNum[typeCtxtArg];
23495
23496             // Was it used in the inline body?
23497             if (tmpNum == BAD_VAR_NUM)
23498             {
23499                 // No -- so the associated runtime lookup is not needed
23500                 // and also no longer provides evidence that the generic
23501                 // context should be kept alive.
23502                 JITDUMP("Inlinee ignores runtime lookup generics context\n");
23503                 assert(lvaGenericsContextUseCount > 0);
23504                 lvaGenericsContextUseCount--;
23505             }
23506         }
23507     }
23508
23509     // Null out any gc ref locals
23510     if (!inlineInfo->HasGcRefLocals())
23511     {
23512         // No ref locals, nothing to do.
23513         JITDUMP("fgInlineAppendStatements: no gc ref inline locals.\n");
23514         return;
23515     }
23516
23517     if (inlineInfo->iciCall->IsImplicitTailCall())
23518     {
23519         JITDUMP("fgInlineAppendStatements: implicit tail call; skipping nulling.\n");
23520         return;
23521     }
23522
23523     JITDUMP("fgInlineAppendStatements: nulling out gc ref inlinee locals.\n");
23524
23525     GenTree*             callStmt          = inlineInfo->iciStmt;
23526     IL_OFFSETX           callILOffset      = callStmt->gtStmt.gtStmtILoffsx;
23527     CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
23528     const unsigned       lclCnt            = InlineeMethodInfo->locals.numArgs;
23529     InlLclVarInfo*       lclVarInfo        = inlineInfo->lclVarInfo;
23530     unsigned             gcRefLclCnt       = inlineInfo->numberOfGcRefLocals;
23531     const unsigned       argCnt            = inlineInfo->argCnt;
23532
23533     noway_assert(callStmt->gtOper == GT_STMT);
23534
23535     for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++)
23536     {
23537         // Is the local a gc ref type? Need to look at the
23538         // inline info for this since we will not have local
23539         // temps for unused inlinee locals.
23540         const var_types lclTyp = lclVarInfo[argCnt + lclNum].lclTypeInfo;
23541
23542         if (!varTypeIsGC(lclTyp))
23543         {
23544             // Nope, nothing to null out.
23545             continue;
23546         }
23547
23548         // Ensure we're examining just the right number of locals.
23549         assert(gcRefLclCnt > 0);
23550         gcRefLclCnt--;
23551
23552         // Fetch the temp for this inline local
23553         const unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
23554
23555         // Is the local used at all?
23556         if (tmpNum == BAD_VAR_NUM)
23557         {
23558             // Nope, nothing to null out.
23559             continue;
23560         }
23561
23562         // Local was used, make sure the type is consistent.
23563         assert(lvaTable[tmpNum].lvType == lclTyp);
23564
23565         // Does the local we're about to null out appear in the return
23566         // expression?  If so we somehow messed up and didn't properly
23567         // spill the return value. See impInlineFetchLocal.
23568         GenTree* retExpr = inlineInfo->retExpr;
23569         if (retExpr != nullptr)
23570         {
23571             const bool interferesWithReturn = gtHasRef(inlineInfo->retExpr, tmpNum, false);
23572             noway_assert(!interferesWithReturn);
23573         }
23574
23575         // Assign null to the local.
23576         GenTree* nullExpr = gtNewTempAssign(tmpNum, gtNewZeroConNode(lclTyp));
23577         GenTree* nullStmt = gtNewStmt(nullExpr, callILOffset);
23578
23579         if (stmtAfter == nullptr)
23580         {
23581             stmtAfter = fgInsertStmtAtBeg(block, nullStmt);
23582         }
23583         else
23584         {
23585             stmtAfter = fgInsertStmtAfter(block, stmtAfter, nullStmt);
23586         }
23587
23588 #ifdef DEBUG
23589         if (verbose)
23590         {
23591             gtDispTree(nullStmt);
23592         }
23593 #endif // DEBUG
23594     }
23595
23596     // There should not be any GC ref locals left to null out.
23597     assert(gcRefLclCnt == 0);
23598 }
23599
23600 /*****************************************************************************/
23601 /*static*/
23602 Compiler::fgWalkResult Compiler::fgChkThrowCB(GenTree** pTree, fgWalkData* data)
23603 {
23604     GenTree* tree = *pTree;
23605
23606     // If this tree doesn't have the EXCEPT flag set, then there is no
23607     // way any of the child nodes could throw, so we can stop recursing.
23608     if (!(tree->gtFlags & GTF_EXCEPT))
23609     {
23610         return Compiler::WALK_SKIP_SUBTREES;
23611     }
23612
23613     switch (tree->gtOper)
23614     {
23615         case GT_MUL:
23616         case GT_ADD:
23617         case GT_SUB:
23618 #ifdef LEGACY_BACKEND
23619         case GT_ASG_ADD:
23620         case GT_ASG_SUB:
23621 #endif
23622         case GT_CAST:
23623             if (tree->gtOverflow())
23624             {
23625                 return Compiler::WALK_ABORT;
23626             }
23627             break;
23628
23629         case GT_INDEX:
23630         case GT_INDEX_ADDR:
23631             // These two call CORINFO_HELP_RNGCHKFAIL for Debug code
23632             if (tree->gtFlags & GTF_INX_RNGCHK)
23633             {
23634                 return Compiler::WALK_ABORT;
23635             }
23636             break;
23637
23638         case GT_ARR_BOUNDS_CHECK:
23639             return Compiler::WALK_ABORT;
23640
23641         default:
23642             break;
23643     }
23644
23645     return Compiler::WALK_CONTINUE;
23646 }
23647
23648 /*****************************************************************************/
23649 /*static*/
23650 Compiler::fgWalkResult Compiler::fgChkLocAllocCB(GenTree** pTree, fgWalkData* data)
23651 {
23652     GenTree* tree = *pTree;
23653
23654     if (tree->gtOper == GT_LCLHEAP)
23655     {
23656         return Compiler::WALK_ABORT;
23657     }
23658
23659     return Compiler::WALK_CONTINUE;
23660 }
23661
23662 /*****************************************************************************/
23663 /*static*/
23664 Compiler::fgWalkResult Compiler::fgChkQmarkCB(GenTree** pTree, fgWalkData* data)
23665 {
23666     GenTree* tree = *pTree;
23667
23668     if (tree->gtOper == GT_QMARK)
23669     {
23670         return Compiler::WALK_ABORT;
23671     }
23672
23673     return Compiler::WALK_CONTINUE;
23674 }
23675
23676 void Compiler::fgLclFldAssign(unsigned lclNum)
23677 {
23678     assert(varTypeIsStruct(lvaTable[lclNum].lvType));
23679     if (lvaTable[lclNum].lvPromoted && lvaTable[lclNum].lvFieldCnt > 1)
23680     {
23681         lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField));
23682     }
23683 }
23684
23685 //------------------------------------------------------------------------
23686 // fgRemoveEmptyFinally: Remove try/finallys where the finally is empty
23687 //
23688 // Notes:
23689 //    Removes all try/finallys in the method with empty finallys.
23690 //    These typically arise from inlining empty Dispose methods.
23691 //
23692 //    Converts callfinally to a jump to the finally continuation.
23693 //    Removes the finally, and reparents all blocks in the try to the
23694 //    enclosing try or method region.
23695 //
23696 //    Currently limited to trivially empty finallys: those with one basic
23697 //    block containing only single RETFILT statement. It is possible but
23698 //    not likely that more complex-looking finallys will eventually become
23699 //    empty (from say subsequent optimization). An SPMI run with
23700 //    just the "detection" part of this phase run after optimization
23701 //    found only one example where a new empty finally was detected.
23702
23703 void Compiler::fgRemoveEmptyFinally()
23704 {
23705     JITDUMP("\n*************** In fgRemoveEmptyFinally()\n");
23706
23707 #if FEATURE_EH_FUNCLETS
23708     // We need to do this transformation before funclets are created.
23709     assert(!fgFuncletsCreated);
23710 #endif // FEATURE_EH_FUNCLETS
23711
23712     // Assume we don't need to update the bbPreds lists.
23713     assert(!fgComputePredsDone);
23714
23715     if (compHndBBtabCount == 0)
23716     {
23717         JITDUMP("No EH in this method, nothing to remove.\n");
23718         return;
23719     }
23720
23721     if (opts.MinOpts())
23722     {
23723         JITDUMP("Method compiled with minOpts, no removal.\n");
23724         return;
23725     }
23726
23727     if (opts.compDbgCode)
23728     {
23729         JITDUMP("Method compiled with debug codegen, no removal.\n");
23730         return;
23731     }
23732
23733 #ifdef DEBUG
23734     if (verbose)
23735     {
23736         printf("\n*************** Before fgRemoveEmptyFinally()\n");
23737         fgDispBasicBlocks();
23738         fgDispHandlerTab();
23739         printf("\n");
23740     }
23741 #endif // DEBUG
23742
23743     // Look for finallys or faults that are empty.
23744     unsigned finallyCount = 0;
23745     unsigned emptyCount   = 0;
23746     unsigned XTnum        = 0;
23747     while (XTnum < compHndBBtabCount)
23748     {
23749         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
23750
23751         // Check if this is a try/finally.  We could also look for empty
23752         // try/fault but presumably those are rare.
23753         if (!HBtab->HasFinallyHandler())
23754         {
23755             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
23756             XTnum++;
23757             continue;
23758         }
23759
23760         finallyCount++;
23761
23762         // Look at blocks involved.
23763         BasicBlock* const firstBlock = HBtab->ebdHndBeg;
23764         BasicBlock* const lastBlock  = HBtab->ebdHndLast;
23765
23766         // Limit for now to finallys that are single blocks.
23767         if (firstBlock != lastBlock)
23768         {
23769             JITDUMP("EH#%u finally has multiple basic blocks; skipping.\n", XTnum);
23770             XTnum++;
23771             continue;
23772         }
23773
23774         // Limit for now to finallys that contain only a GT_RETFILT.
23775         bool isEmpty = true;
23776
23777         for (GenTreeStmt* stmt = firstBlock->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
23778         {
23779             GenTree* stmtExpr = stmt->gtStmtExpr;
23780
23781             if (stmtExpr->gtOper != GT_RETFILT)
23782             {
23783                 isEmpty = false;
23784                 break;
23785             }
23786         }
23787
23788         if (!isEmpty)
23789         {
23790             JITDUMP("EH#%u finally is not empty; skipping.\n", XTnum);
23791             XTnum++;
23792             continue;
23793         }
23794
23795         JITDUMP("EH#%u has empty finally, removing the region.\n", XTnum);
23796
23797         // Find all the call finallys that invoke this finally,
23798         // and modify them to jump to the return point.
23799         BasicBlock* firstCallFinallyRangeBlock = nullptr;
23800         BasicBlock* endCallFinallyRangeBlock   = nullptr;
23801         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
23802
23803         BasicBlock* currentBlock = firstCallFinallyRangeBlock;
23804
23805         while (currentBlock != endCallFinallyRangeBlock)
23806         {
23807             BasicBlock* nextBlock = currentBlock->bbNext;
23808
23809             if ((currentBlock->bbJumpKind == BBJ_CALLFINALLY) && (currentBlock->bbJumpDest == firstBlock))
23810             {
23811                 // Retarget the call finally to jump to the return
23812                 // point.
23813                 //
23814                 // We don't expect to see retless finallys here, since
23815                 // the finally is empty.
23816                 noway_assert(currentBlock->isBBCallAlwaysPair());
23817
23818                 BasicBlock* const leaveBlock          = currentBlock->bbNext;
23819                 BasicBlock* const postTryFinallyBlock = leaveBlock->bbJumpDest;
23820
23821                 noway_assert(leaveBlock->bbJumpKind == BBJ_ALWAYS);
23822
23823                 currentBlock->bbJumpDest = postTryFinallyBlock;
23824                 currentBlock->bbJumpKind = BBJ_ALWAYS;
23825
23826                 // Ref count updates.
23827                 fgAddRefPred(postTryFinallyBlock, currentBlock);
23828                 // fgRemoveRefPred(firstBlock, currentBlock);
23829
23830                 // Delete the leave block, which should be marked as
23831                 // keep always.
23832                 assert((leaveBlock->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
23833                 nextBlock = leaveBlock->bbNext;
23834
23835                 leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
23836                 fgRemoveBlock(leaveBlock, true);
23837
23838                 // Cleanup the postTryFinallyBlock
23839                 fgCleanupContinuation(postTryFinallyBlock);
23840
23841                 // Make sure iteration isn't going off the deep end.
23842                 assert(leaveBlock != endCallFinallyRangeBlock);
23843             }
23844
23845             currentBlock = nextBlock;
23846         }
23847
23848         // Handler block should now be unreferenced, since the only
23849         // explicit references to it were in call finallys.
23850         firstBlock->bbRefs = 0;
23851
23852         // Remove the handler block.
23853         const bool unreachable = true;
23854         firstBlock->bbFlags &= ~BBF_DONT_REMOVE;
23855         fgRemoveBlock(firstBlock, unreachable);
23856
23857         // Find enclosing try region for the try, if any, and update
23858         // the try region. Note the handler region (if any) won't
23859         // change.
23860         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
23861         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
23862         assert(firstTryBlock->getTryIndex() == XTnum);
23863
23864         for (BasicBlock* block = firstTryBlock; block != nullptr; block = block->bbNext)
23865         {
23866             // Look for blocks directly contained in this try, and
23867             // update the try region appropriately.
23868             //
23869             // Try region for blocks transitively contained (say in a
23870             // child try) will get updated by the subsequent call to
23871             // fgRemoveEHTableEntry.
23872             if (block->getTryIndex() == XTnum)
23873             {
23874                 if (firstBlock->hasTryIndex())
23875                 {
23876                     block->setTryIndex(firstBlock->getTryIndex());
23877                 }
23878                 else
23879                 {
23880                     block->clearTryIndex();
23881                 }
23882             }
23883
23884             if (block == firstTryBlock)
23885             {
23886                 assert((block->bbFlags & BBF_TRY_BEG) != 0);
23887                 block->bbFlags &= ~BBF_TRY_BEG;
23888             }
23889
23890             if (block == lastTryBlock)
23891             {
23892                 break;
23893             }
23894         }
23895
23896         // Remove the try-finally EH region. This will compact the EH table
23897         // so XTnum now points at the next entry.
23898         fgRemoveEHTableEntry(XTnum);
23899
23900         emptyCount++;
23901     }
23902
23903     if (emptyCount > 0)
23904     {
23905         JITDUMP("fgRemoveEmptyFinally() removed %u try-finally clauses from %u finallys\n", emptyCount, finallyCount);
23906         fgOptimizedFinally = true;
23907
23908 #ifdef DEBUG
23909         if (verbose)
23910         {
23911             printf("\n*************** After fgRemoveEmptyFinally()\n");
23912             fgDispBasicBlocks();
23913             fgDispHandlerTab();
23914             printf("\n");
23915         }
23916
23917         fgVerifyHandlerTab();
23918         fgDebugCheckBBlist(false, false);
23919
23920 #endif // DEBUG
23921     }
23922 }
23923
23924 //------------------------------------------------------------------------
23925 // fgRemoveEmptyTry: Optimize try/finallys where the try is empty
23926 //
23927 // Notes:
23928 //    In runtimes where thread abort is not possible, `try {} finally {S}`
23929 //    can be optimized to simply `S`. This method looks for such
23930 //    cases and removes the try-finally from the EH table, making
23931 //    suitable flow, block flag, statement, and region updates.
23932 //
23933 //    This optimization is not legal in runtimes that support thread
23934 //    abort because those runtimes ensure that a finally is completely
23935 //    executed before continuing to process the thread abort.  With
23936 //    this optimization, the code block `S` can lose special
23937 //    within-finally status and so complete execution is no longer
23938 //    guaranteed.
23939
23940 void Compiler::fgRemoveEmptyTry()
23941 {
23942     JITDUMP("\n*************** In fgRemoveEmptyTry()\n");
23943
23944 #if FEATURE_EH_FUNCLETS
23945     // We need to do this transformation before funclets are created.
23946     assert(!fgFuncletsCreated);
23947 #endif // FEATURE_EH_FUNCLETS
23948
23949     // Assume we don't need to update the bbPreds lists.
23950     assert(!fgComputePredsDone);
23951
23952 #ifdef FEATURE_CORECLR
23953     bool enableRemoveEmptyTry = true;
23954 #else
23955     // Code in a finally gets special treatment in the presence of
23956     // thread abort.
23957     bool enableRemoveEmptyTry = false;
23958 #endif // FEATURE_CORECLR
23959
23960 #ifdef DEBUG
23961     // Allow override to enable/disable.
23962     enableRemoveEmptyTry = (JitConfig.JitEnableRemoveEmptyTry() == 1);
23963 #endif // DEBUG
23964
23965     if (!enableRemoveEmptyTry)
23966     {
23967         JITDUMP("Empty try removal disabled.\n");
23968         return;
23969     }
23970
23971     if (compHndBBtabCount == 0)
23972     {
23973         JITDUMP("No EH in this method, nothing to remove.\n");
23974         return;
23975     }
23976
23977     if (opts.MinOpts())
23978     {
23979         JITDUMP("Method compiled with minOpts, no removal.\n");
23980         return;
23981     }
23982
23983     if (opts.compDbgCode)
23984     {
23985         JITDUMP("Method compiled with debug codegen, no removal.\n");
23986         return;
23987     }
23988
23989 #ifdef DEBUG
23990     if (verbose)
23991     {
23992         printf("\n*************** Before fgRemoveEmptyTry()\n");
23993         fgDispBasicBlocks();
23994         fgDispHandlerTab();
23995         printf("\n");
23996     }
23997 #endif // DEBUG
23998
23999     // Look for try-finallys where the try is empty.
24000     unsigned emptyCount = 0;
24001     unsigned XTnum      = 0;
24002     while (XTnum < compHndBBtabCount)
24003     {
24004         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
24005
24006         // Check if this is a try/finally.  We could also look for empty
24007         // try/fault but presumably those are rare.
24008         if (!HBtab->HasFinallyHandler())
24009         {
24010             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
24011             XTnum++;
24012             continue;
24013         }
24014
24015         // Examine the try region
24016         BasicBlock* const firstTryBlock     = HBtab->ebdTryBeg;
24017         BasicBlock* const lastTryBlock      = HBtab->ebdTryLast;
24018         BasicBlock* const firstHandlerBlock = HBtab->ebdHndBeg;
24019         BasicBlock* const lastHandlerBlock  = HBtab->ebdHndLast;
24020         BasicBlock* const endHandlerBlock   = lastHandlerBlock->bbNext;
24021
24022         assert(firstTryBlock->getTryIndex() == XTnum);
24023
24024         // Limit for now to trys that contain only a callfinally pair
24025         // or branch to same.
24026         if (!firstTryBlock->isEmpty())
24027         {
24028             JITDUMP("EH#%u first try block BB%02u not empty; skipping.\n", XTnum, firstTryBlock->bbNum);
24029             XTnum++;
24030             continue;
24031         }
24032
24033 #if FEATURE_EH_CALLFINALLY_THUNKS
24034
24035         // Look for blocks that are always jumps to a call finally
24036         // pair that targets the finally
24037         if (firstTryBlock->bbJumpKind != BBJ_ALWAYS)
24038         {
24039             JITDUMP("EH#%u first try block BB%02u not jump to a callfinally; skipping.\n", XTnum, firstTryBlock->bbNum);
24040             XTnum++;
24041             continue;
24042         }
24043
24044         BasicBlock* const callFinally = firstTryBlock->bbJumpDest;
24045
24046         // Look for call always pair. Note this will also disqualify
24047         // empty try removal in cases where the finally doesn't
24048         // return.
24049         if (!callFinally->isBBCallAlwaysPair() || (callFinally->bbJumpDest != firstHandlerBlock))
24050         {
24051             JITDUMP("EH#%u first try block BB%02u always jumps but not to a callfinally; skipping.\n", XTnum,
24052                     firstTryBlock->bbNum);
24053             XTnum++;
24054             continue;
24055         }
24056
24057         // Try itself must be a single block.
24058         if (firstTryBlock != lastTryBlock)
24059         {
24060             JITDUMP("EH#%u first try block BB%02u not only block in try; skipping.\n", XTnum,
24061                     firstTryBlock->bbNext->bbNum);
24062             XTnum++;
24063             continue;
24064         }
24065
24066 #else
24067         // Look for call always pair within the try itself. Note this
24068         // will also disqualify empty try removal in cases where the
24069         // finally doesn't return.
24070         if (!firstTryBlock->isBBCallAlwaysPair() || (firstTryBlock->bbJumpDest != firstHandlerBlock))
24071         {
24072             JITDUMP("EH#%u first try block BB%02u not a callfinally; skipping.\n", XTnum, firstTryBlock->bbNum);
24073             XTnum++;
24074             continue;
24075         }
24076
24077         BasicBlock* const callFinally = firstTryBlock;
24078
24079         // Try must be a callalways pair of blocks.
24080         if (firstTryBlock->bbNext != lastTryBlock)
24081         {
24082             JITDUMP("EH#%u block BB%02u not last block in try; skipping.\n", XTnum, firstTryBlock->bbNext->bbNum);
24083             XTnum++;
24084             continue;
24085         }
24086
24087 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24088
24089         JITDUMP("EH#%u has empty try, removing the try region and promoting the finally.\n", XTnum);
24090
24091         // There should be just one callfinally that invokes this
24092         // finally, the one we found above. Verify this.
24093         BasicBlock* firstCallFinallyRangeBlock = nullptr;
24094         BasicBlock* endCallFinallyRangeBlock   = nullptr;
24095         bool        verifiedSingleCallfinally  = true;
24096         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
24097
24098         for (BasicBlock* block = firstCallFinallyRangeBlock; block != endCallFinallyRangeBlock; block = block->bbNext)
24099         {
24100             if ((block->bbJumpKind == BBJ_CALLFINALLY) && (block->bbJumpDest == firstHandlerBlock))
24101             {
24102                 assert(block->isBBCallAlwaysPair());
24103
24104                 if (block != callFinally)
24105                 {
24106                     JITDUMP("EH#%u found unexpected callfinally BB%02u; skipping.\n");
24107                     verifiedSingleCallfinally = false;
24108                     break;
24109                 }
24110
24111                 block = block->bbNext;
24112             }
24113         }
24114
24115         if (!verifiedSingleCallfinally)
24116         {
24117             JITDUMP("EH#%u -- unexpectedly -- has multiple callfinallys; skipping.\n");
24118             XTnum++;
24119             assert(verifiedSingleCallfinally);
24120             continue;
24121         }
24122
24123         // Time to optimize.
24124         //
24125         // (1) Convert the callfinally to a normal jump to the handler
24126         callFinally->bbJumpKind = BBJ_ALWAYS;
24127
24128         // Identify the leave block and the continuation
24129         BasicBlock* const leave        = callFinally->bbNext;
24130         BasicBlock* const continuation = leave->bbJumpDest;
24131
24132         // (2) Cleanup the leave so it can be deleted by subsequent opts
24133         assert((leave->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
24134         leave->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
24135
24136         // (3) Cleanup the continuation
24137         fgCleanupContinuation(continuation);
24138
24139         // (4) Find enclosing try region for the try, if any, and
24140         // update the try region for the blocks in the try. Note the
24141         // handler region (if any) won't change.
24142         //
24143         // Kind of overkill to loop here, but hey.
24144         for (BasicBlock* block = firstTryBlock; block != nullptr; block = block->bbNext)
24145         {
24146             // Look for blocks directly contained in this try, and
24147             // update the try region appropriately.
24148             //
24149             // The try region for blocks transitively contained (say in a
24150             // child try) will get updated by the subsequent call to
24151             // fgRemoveEHTableEntry.
24152             if (block->getTryIndex() == XTnum)
24153             {
24154                 if (firstHandlerBlock->hasTryIndex())
24155                 {
24156                     block->setTryIndex(firstHandlerBlock->getTryIndex());
24157                 }
24158                 else
24159                 {
24160                     block->clearTryIndex();
24161                 }
24162             }
24163
24164             if (block == firstTryBlock)
24165             {
24166                 assert((block->bbFlags & BBF_TRY_BEG) != 0);
24167                 block->bbFlags &= ~BBF_TRY_BEG;
24168             }
24169
24170             if (block == lastTryBlock)
24171             {
24172                 break;
24173             }
24174         }
24175
24176         // (5) Update the directly contained handler blocks' handler index.
24177         // Handler index of any nested blocks will update when we
24178         // remove the EH table entry.  Change handler exits to jump to
24179         // the continuation.  Clear catch type on handler entry.
24180         // Decrement nesting level of enclosed GT_END_LFINs.
24181         for (BasicBlock* block = firstHandlerBlock; block != endHandlerBlock; block = block->bbNext)
24182         {
24183             if (block == firstHandlerBlock)
24184             {
24185                 block->bbCatchTyp = BBCT_NONE;
24186             }
24187
24188             if (block->getHndIndex() == XTnum)
24189             {
24190                 if (firstTryBlock->hasHndIndex())
24191                 {
24192                     block->setHndIndex(firstTryBlock->getHndIndex());
24193                 }
24194                 else
24195                 {
24196                     block->clearHndIndex();
24197                 }
24198
24199                 if (block->bbJumpKind == BBJ_EHFINALLYRET)
24200                 {
24201                     GenTreeStmt* finallyRet     = block->lastStmt();
24202                     GenTree*     finallyRetExpr = finallyRet->gtStmtExpr;
24203                     assert(finallyRetExpr->gtOper == GT_RETFILT);
24204                     fgRemoveStmt(block, finallyRet);
24205                     block->bbJumpKind = BBJ_ALWAYS;
24206                     block->bbJumpDest = continuation;
24207                     fgAddRefPred(continuation, block);
24208                 }
24209             }
24210
24211 #if !FEATURE_EH_FUNCLETS
24212             // If we're in a non-funclet model, decrement the nesting
24213             // level of any GT_END_LFIN we find in the handler region,
24214             // since we're removing the enclosing handler.
24215             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
24216             {
24217                 GenTree* expr = stmt->gtStmtExpr;
24218                 if (expr->gtOper == GT_END_LFIN)
24219                 {
24220                     const unsigned nestLevel = expr->gtVal.gtVal1;
24221                     assert(nestLevel > 0);
24222                     expr->gtVal.gtVal1 = nestLevel - 1;
24223                 }
24224             }
24225 #endif // !FEATURE_EH_FUNCLETS
24226         }
24227
24228         // (6) Remove the try-finally EH region. This will compact the
24229         // EH table so XTnum now points at the next entry and will update
24230         // the EH region indices of any nested EH in the (former) handler.
24231         fgRemoveEHTableEntry(XTnum);
24232
24233         // Another one bites the dust...
24234         emptyCount++;
24235     }
24236
24237     if (emptyCount > 0)
24238     {
24239         JITDUMP("fgRemoveEmptyTry() optimized %u empty-try try-finally clauses\n", emptyCount);
24240         fgOptimizedFinally = true;
24241
24242 #ifdef DEBUG
24243         if (verbose)
24244         {
24245             printf("\n*************** After fgRemoveEmptyTry()\n");
24246             fgDispBasicBlocks();
24247             fgDispHandlerTab();
24248             printf("\n");
24249         }
24250
24251         fgVerifyHandlerTab();
24252         fgDebugCheckBBlist(false, false);
24253
24254 #endif // DEBUG
24255     }
24256 }
24257
24258 //------------------------------------------------------------------------
24259 // fgCloneFinally: Optimize normal exit path from a try/finally
24260 //
24261 // Notes:
24262 //    Handles finallys that are not enclosed by or enclosing other
24263 //    handler regions.
24264 //
24265 //    Converts the "normal exit" callfinally to a jump to a cloned copy
24266 //    of the finally, which in turn jumps to the finally continuation.
24267 //
24268 //    If all callfinallys for a given finally are converted to jump to
24269 //    the clone, the try-finally is modified into a try-fault,
24270 //    distingushable from organic try-faults by handler type
24271 //    EH_HANDLER_FAULT_WAS_FINALLY vs the organic EH_HANDLER_FAULT.
24272 //
24273 //    Does not yet handle thread abort. The open issues here are how
24274 //    to maintain the proper description of the cloned finally blocks
24275 //    as a handler (for thread abort purposes), how to prevent code
24276 //    motion in or out of these blocks, and how to report this cloned
24277 //    handler to the runtime. Some building blocks for thread abort
24278 //    exist (see below) but more work needed.
24279 //
24280 //    The first and last blocks of the cloned finally are marked with
24281 //    BBF_CLONED_FINALLY_BEGIN and BBF_CLONED_FINALLY_END. However
24282 //    these markers currently can get lost during subsequent
24283 //    optimizations.
24284
24285 void Compiler::fgCloneFinally()
24286 {
24287     JITDUMP("\n*************** In fgCloneFinally()\n");
24288
24289 #if FEATURE_EH_FUNCLETS
24290     // We need to do this transformation before funclets are created.
24291     assert(!fgFuncletsCreated);
24292 #endif // FEATURE_EH_FUNCLETS
24293
24294     // Assume we don't need to update the bbPreds lists.
24295     assert(!fgComputePredsDone);
24296
24297 #ifdef FEATURE_CORECLR
24298     bool enableCloning = true;
24299 #else
24300     // Finally cloning currently doesn't provide sufficient protection
24301     // for the cloned code in the presence of thread abort.
24302     bool enableCloning = false;
24303 #endif // FEATURE_CORECLR
24304
24305 #ifdef DEBUG
24306     // Allow override to enable/disable.
24307     enableCloning = (JitConfig.JitEnableFinallyCloning() == 1);
24308 #endif // DEBUG
24309
24310     if (!enableCloning)
24311     {
24312         JITDUMP("Finally cloning disabled.\n");
24313         return;
24314     }
24315
24316     if (compHndBBtabCount == 0)
24317     {
24318         JITDUMP("No EH in this method, no cloning.\n");
24319         return;
24320     }
24321
24322     if (opts.MinOpts())
24323     {
24324         JITDUMP("Method compiled with minOpts, no cloning.\n");
24325         return;
24326     }
24327
24328     if (opts.compDbgCode)
24329     {
24330         JITDUMP("Method compiled with debug codegen, no cloning.\n");
24331         return;
24332     }
24333
24334 #ifdef DEBUG
24335     if (verbose)
24336     {
24337         printf("\n*************** Before fgCloneFinally()\n");
24338         fgDispBasicBlocks();
24339         fgDispHandlerTab();
24340         printf("\n");
24341     }
24342
24343     // Verify try-finally exits look good before we start.
24344     fgDebugCheckTryFinallyExits();
24345
24346 #endif // DEBUG
24347
24348     // Look for finallys that are not contained within other handlers,
24349     // and which do not themselves contain EH.
24350     //
24351     // Note these cases potentially could be handled, but are less
24352     // obviously profitable and require modification of the handler
24353     // table.
24354     unsigned  XTnum      = 0;
24355     EHblkDsc* HBtab      = compHndBBtab;
24356     unsigned  cloneCount = 0;
24357     for (; XTnum < compHndBBtabCount; XTnum++, HBtab++)
24358     {
24359         // Check if this is a try/finally
24360         if (!HBtab->HasFinallyHandler())
24361         {
24362             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
24363             continue;
24364         }
24365
24366         // Check if enclosed by another handler.
24367         const unsigned enclosingHandlerRegion = ehGetEnclosingHndIndex(XTnum);
24368
24369         if (enclosingHandlerRegion != EHblkDsc::NO_ENCLOSING_INDEX)
24370         {
24371             JITDUMP("EH#%u is enclosed by handler EH#%u; skipping.\n", XTnum, enclosingHandlerRegion);
24372             continue;
24373         }
24374
24375         bool     containsEH                   = false;
24376         unsigned exampleEnclosedHandlerRegion = 0;
24377
24378         // Only need to look at lower numbered regions because the
24379         // handler table is ordered by nesting.
24380         for (unsigned i = 0; i < XTnum; i++)
24381         {
24382             if (ehGetEnclosingHndIndex(i) == XTnum)
24383             {
24384                 exampleEnclosedHandlerRegion = i;
24385                 containsEH                   = true;
24386                 break;
24387             }
24388         }
24389
24390         if (containsEH)
24391         {
24392             JITDUMP("Finally for EH#%u encloses handler EH#%u; skipping.\n", XTnum, exampleEnclosedHandlerRegion);
24393             continue;
24394         }
24395
24396         // Look at blocks involved.
24397         BasicBlock* const firstBlock = HBtab->ebdHndBeg;
24398         BasicBlock* const lastBlock  = HBtab->ebdHndLast;
24399         assert(firstBlock != nullptr);
24400         assert(lastBlock != nullptr);
24401         BasicBlock* nextBlock       = lastBlock->bbNext;
24402         unsigned    regionBBCount   = 0;
24403         unsigned    regionStmtCount = 0;
24404         bool        hasFinallyRet   = false;
24405         bool        isAllRare       = true;
24406         bool        hasSwitch       = false;
24407
24408         for (const BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
24409         {
24410             if (block->bbJumpKind == BBJ_SWITCH)
24411             {
24412                 hasSwitch = true;
24413                 break;
24414             }
24415
24416             regionBBCount++;
24417
24418             // Should we compute statement cost here, or is it
24419             // premature...? For now just count statements I guess.
24420             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
24421             {
24422                 regionStmtCount++;
24423             }
24424
24425             hasFinallyRet = hasFinallyRet || (block->bbJumpKind == BBJ_EHFINALLYRET);
24426             isAllRare     = isAllRare && block->isRunRarely();
24427         }
24428
24429         // Skip cloning if the finally has a switch.
24430         if (hasSwitch)
24431         {
24432             JITDUMP("Finally in EH#%u has a switch; skipping.\n", XTnum);
24433             continue;
24434         }
24435
24436         // Skip cloning if the finally must throw.
24437         if (!hasFinallyRet)
24438         {
24439             JITDUMP("Finally in EH#%u does not return; skipping.\n", XTnum);
24440             continue;
24441         }
24442
24443         // Skip cloning if the finally is rarely run code.
24444         if (isAllRare)
24445         {
24446             JITDUMP("Finally in EH#%u is run rarely; skipping.\n", XTnum);
24447             continue;
24448         }
24449
24450         // Empirical studies from CoreCLR and CoreFX show that less
24451         // that 1% of finally regions have more than 15
24452         // statements. So, to avoid potentially excessive code growth,
24453         // only clone finallys that have 15 or fewer statements.
24454         const unsigned stmtCountLimit = 15;
24455         if (regionStmtCount > stmtCountLimit)
24456         {
24457             JITDUMP("Finally in EH#%u has %u statements, limit is %u; skipping.\n", XTnum, regionStmtCount,
24458                     stmtCountLimit);
24459             continue;
24460         }
24461
24462         JITDUMP("EH#%u is a candidate for finally cloning:"
24463                 " %u blocks, %u statements\n",
24464                 XTnum, regionBBCount, regionStmtCount);
24465
24466         // Walk the try region backwards looking for the last block
24467         // that transfers control to a callfinally.
24468         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
24469         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
24470         assert(firstTryBlock->getTryIndex() == XTnum);
24471         assert(bbInTryRegions(XTnum, lastTryBlock));
24472         BasicBlock* const beforeTryBlock = firstTryBlock->bbPrev;
24473
24474         BasicBlock* normalCallFinallyBlock   = nullptr;
24475         BasicBlock* normalCallFinallyReturn  = nullptr;
24476         BasicBlock* cloneInsertAfter         = HBtab->ebdTryLast;
24477         bool        tryToRelocateCallFinally = false;
24478
24479         for (BasicBlock* block = lastTryBlock; block != beforeTryBlock; block = block->bbPrev)
24480         {
24481 #if FEATURE_EH_CALLFINALLY_THUNKS
24482             // Look for blocks that are always jumps to a call finally
24483             // pair that targets our finally.
24484             if (block->bbJumpKind != BBJ_ALWAYS)
24485             {
24486                 continue;
24487             }
24488
24489             BasicBlock* const jumpDest = block->bbJumpDest;
24490
24491             if (!jumpDest->isBBCallAlwaysPair() || (jumpDest->bbJumpDest != firstBlock))
24492             {
24493                 continue;
24494             }
24495 #else
24496             // Look for call finally pair directly within the try
24497             if (!block->isBBCallAlwaysPair() || (block->bbJumpDest != firstBlock))
24498             {
24499                 continue;
24500             }
24501
24502             BasicBlock* const jumpDest = block;
24503 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24504
24505             // Found our block.
24506             BasicBlock* const finallyReturnBlock  = jumpDest->bbNext;
24507             BasicBlock* const postTryFinallyBlock = finallyReturnBlock->bbJumpDest;
24508
24509             normalCallFinallyBlock  = jumpDest;
24510             normalCallFinallyReturn = postTryFinallyBlock;
24511
24512 #if FEATURE_EH_CALLFINALLY_THUNKS
24513             // When there are callfinally thunks, we don't expect to see the
24514             // callfinally within a handler region either.
24515             assert(!jumpDest->hasHndIndex());
24516
24517             // Update the clone insertion point to just after the
24518             // call always pair.
24519             cloneInsertAfter = finallyReturnBlock;
24520
24521             // We will consider moving the callfinally so we can fall
24522             // through from the try into the clone.
24523             tryToRelocateCallFinally = true;
24524
24525             JITDUMP("Chose path to clone: try block BB%02u jumps to callfinally at BB%02u;"
24526                     " the call returns to BB%02u which jumps to BB%02u\n",
24527                     block->bbNum, jumpDest->bbNum, finallyReturnBlock->bbNum, postTryFinallyBlock->bbNum);
24528 #else
24529             JITDUMP("Chose path to clone: try block BB%02u is a callfinally;"
24530                     " the call returns to BB%02u which jumps to BB%02u\n",
24531                     block->bbNum, finallyReturnBlock->bbNum, postTryFinallyBlock->bbNum);
24532 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24533
24534             break;
24535         }
24536
24537         // If there is no call to the finally, don't clone.
24538         if (normalCallFinallyBlock == nullptr)
24539         {
24540             JITDUMP("EH#%u: no calls from the try to the finally, skipping.\n", XTnum);
24541             continue;
24542         }
24543
24544         JITDUMP("Will update callfinally block BB%02u to jump to the clone;"
24545                 " clone will jump to BB%02u\n",
24546                 normalCallFinallyBlock->bbNum, normalCallFinallyReturn->bbNum);
24547
24548         // If there are multiple callfinallys and we're in the
24549         // callfinally thunk model, all the callfinallys are placed
24550         // just outside the try region. We'd like our chosen
24551         // callfinally to come first after the try, so we can fall out of the try
24552         // into the clone.
24553         BasicBlock* firstCallFinallyRangeBlock = nullptr;
24554         BasicBlock* endCallFinallyRangeBlock   = nullptr;
24555         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
24556
24557         if (tryToRelocateCallFinally)
24558         {
24559             BasicBlock* firstCallFinallyBlock = nullptr;
24560
24561             for (BasicBlock* block = firstCallFinallyRangeBlock; block != endCallFinallyRangeBlock;
24562                  block             = block->bbNext)
24563             {
24564                 if (block->isBBCallAlwaysPair())
24565                 {
24566                     if (block->bbJumpDest == firstBlock)
24567                     {
24568                         firstCallFinallyBlock = block;
24569                         break;
24570                     }
24571                 }
24572             }
24573
24574             // We better have found at least one call finally.
24575             assert(firstCallFinallyBlock != nullptr);
24576
24577             // If there is more than one callfinally, move the one we are
24578             // going to retarget to be first in the callfinally range.
24579             if (firstCallFinallyBlock != normalCallFinallyBlock)
24580             {
24581                 JITDUMP("Moving callfinally BB%02u to be first in line, before BB%02u\n", normalCallFinallyBlock->bbNum,
24582                         firstCallFinallyBlock->bbNum);
24583
24584                 BasicBlock* const firstToMove      = normalCallFinallyBlock;
24585                 BasicBlock* const lastToMove       = normalCallFinallyBlock->bbNext;
24586                 BasicBlock* const placeToMoveAfter = firstCallFinallyBlock->bbPrev;
24587
24588                 fgUnlinkRange(firstToMove, lastToMove);
24589                 fgMoveBlocksAfter(firstToMove, lastToMove, placeToMoveAfter);
24590
24591 #ifdef DEBUG
24592                 // Sanity checks
24593                 fgDebugCheckBBlist(false, false);
24594                 fgVerifyHandlerTab();
24595 #endif // DEBUG
24596
24597                 assert(nextBlock == lastBlock->bbNext);
24598
24599                 // Update where the callfinally range begins, since we might
24600                 // have altered this with callfinally rearrangement, and/or
24601                 // the range begin might have been pretty loose to begin with.
24602                 firstCallFinallyRangeBlock = normalCallFinallyBlock;
24603             }
24604         }
24605
24606         // Clone the finally and retarget the normal return path and
24607         // any other path that happens to share that same return
24608         // point. For instance a construct like:
24609         //
24610         //  try { } catch { } finally { }
24611         //
24612         // will have two call finally blocks, one for the normal exit
24613         // from the try, and the the other for the exit from the
24614         // catch. They'll both pass the same return point which is the
24615         // statement after the finally, so they can share the clone.
24616         //
24617         // Clone the finally body, and splice it into the flow graph
24618         // within in the parent region of the try.
24619         const unsigned  finallyTryIndex = firstBlock->bbTryIndex;
24620         BasicBlock*     insertAfter     = nullptr;
24621         BlockToBlockMap blockMap(getAllocator());
24622         bool            clonedOk     = true;
24623         unsigned        cloneBBCount = 0;
24624
24625         for (BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
24626         {
24627             BasicBlock* newBlock;
24628
24629             if (block == firstBlock)
24630             {
24631                 // Put first cloned finally block into the approprate
24632                 // region, somewhere within or after the range of
24633                 // callfinallys, depending on the EH implementation.
24634                 const unsigned    hndIndex = 0;
24635                 BasicBlock* const nearBlk  = cloneInsertAfter;
24636                 newBlock                   = fgNewBBinRegion(block->bbJumpKind, finallyTryIndex, hndIndex, nearBlk);
24637
24638                 // If the clone ends up just after the finally, adjust
24639                 // the stopping point for finally traversal.
24640                 if (newBlock->bbNext == nextBlock)
24641                 {
24642                     assert(newBlock->bbPrev == lastBlock);
24643                     nextBlock = newBlock;
24644                 }
24645             }
24646             else
24647             {
24648                 // Put subsequent blocks in the same region...
24649                 const bool extendRegion = true;
24650                 newBlock                = fgNewBBafter(block->bbJumpKind, insertAfter, extendRegion);
24651             }
24652
24653             cloneBBCount++;
24654             assert(cloneBBCount <= regionBBCount);
24655
24656             insertAfter = newBlock;
24657             blockMap.Set(block, newBlock);
24658
24659             clonedOk = BasicBlock::CloneBlockState(this, newBlock, block);
24660
24661             if (!clonedOk)
24662             {
24663                 break;
24664             }
24665
24666             // Update block flags. Note a block can be both first and last.
24667             if (block == firstBlock)
24668             {
24669                 // Mark the block as the start of the cloned finally.
24670                 newBlock->bbFlags |= BBF_CLONED_FINALLY_BEGIN;
24671             }
24672
24673             if (block == lastBlock)
24674             {
24675                 // Mark the block as the end of the cloned finally.
24676                 newBlock->bbFlags |= BBF_CLONED_FINALLY_END;
24677             }
24678
24679             // Make sure clone block state hasn't munged the try region.
24680             assert(newBlock->bbTryIndex == finallyTryIndex);
24681
24682             // Cloned handler block is no longer within the handler.
24683             newBlock->clearHndIndex();
24684
24685             // Jump dests are set in a post-pass; make sure CloneBlockState hasn't tried to set them.
24686             assert(newBlock->bbJumpDest == nullptr);
24687         }
24688
24689         if (!clonedOk)
24690         {
24691             // TODO: cleanup the partial clone?
24692             JITDUMP("Unable to clone the finally; skipping.\n");
24693             continue;
24694         }
24695
24696         // We should have cloned all the finally region blocks.
24697         assert(cloneBBCount == regionBBCount);
24698
24699         JITDUMP("Cloned finally blocks are: BB%2u ... BB%2u\n", blockMap[firstBlock]->bbNum,
24700                 blockMap[lastBlock]->bbNum);
24701
24702         // Redirect redirect any branches within the newly-cloned
24703         // finally, and any finally returns to jump to the return
24704         // point.
24705         for (BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
24706         {
24707             BasicBlock* newBlock = blockMap[block];
24708
24709             if (block->bbJumpKind == BBJ_EHFINALLYRET)
24710             {
24711                 GenTreeStmt* finallyRet     = newBlock->lastStmt();
24712                 GenTree*     finallyRetExpr = finallyRet->gtStmtExpr;
24713                 assert(finallyRetExpr->gtOper == GT_RETFILT);
24714                 fgRemoveStmt(newBlock, finallyRet);
24715                 newBlock->bbJumpKind = BBJ_ALWAYS;
24716                 newBlock->bbJumpDest = normalCallFinallyReturn;
24717
24718                 fgAddRefPred(normalCallFinallyReturn, newBlock);
24719             }
24720             else
24721             {
24722                 optCopyBlkDest(block, newBlock);
24723                 optRedirectBlock(newBlock, &blockMap);
24724             }
24725         }
24726
24727         // Modify the targeting call finallys to branch to the cloned
24728         // finally. Make a note if we see some calls that can't be
24729         // retargeted (since they want to return to other places).
24730         BasicBlock* const firstCloneBlock    = blockMap[firstBlock];
24731         bool              retargetedAllCalls = true;
24732         BasicBlock*       currentBlock       = firstCallFinallyRangeBlock;
24733
24734         while (currentBlock != endCallFinallyRangeBlock)
24735         {
24736             BasicBlock* nextBlockToScan = currentBlock->bbNext;
24737
24738             if (currentBlock->isBBCallAlwaysPair())
24739             {
24740                 if (currentBlock->bbJumpDest == firstBlock)
24741                 {
24742                     BasicBlock* const leaveBlock          = currentBlock->bbNext;
24743                     BasicBlock* const postTryFinallyBlock = leaveBlock->bbJumpDest;
24744
24745                     // Note we must retarget all callfinallies that have this
24746                     // continuation, or we can't clean up the continuation
24747                     // block properly below, since it will be reachable both
24748                     // by the cloned finally and by the called finally.
24749                     if (postTryFinallyBlock == normalCallFinallyReturn)
24750                     {
24751                         // This call returns to the expected spot, so
24752                         // retarget it to branch to the clone.
24753                         currentBlock->bbJumpDest = firstCloneBlock;
24754                         currentBlock->bbJumpKind = BBJ_ALWAYS;
24755
24756                         // Ref count updates.
24757                         fgAddRefPred(firstCloneBlock, currentBlock);
24758                         // fgRemoveRefPred(firstBlock, currentBlock);
24759
24760                         // Delete the leave block, which should be marked as
24761                         // keep always.
24762                         assert((leaveBlock->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
24763                         nextBlock = leaveBlock->bbNext;
24764
24765                         leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
24766                         fgRemoveBlock(leaveBlock, true);
24767
24768                         // Make sure iteration isn't going off the deep end.
24769                         assert(leaveBlock != endCallFinallyRangeBlock);
24770                     }
24771                     else
24772                     {
24773                         // We can't retarget this call since it
24774                         // returns somewhere else.
24775                         retargetedAllCalls = false;
24776                     }
24777                 }
24778             }
24779
24780             currentBlock = nextBlockToScan;
24781         }
24782
24783         // If we retargeted all calls, modify EH descriptor to be
24784         // try-fault instead of try-finally, and then non-cloned
24785         // finally catch type to be fault.
24786         if (retargetedAllCalls)
24787         {
24788             JITDUMP("All callfinallys retargeted; changing finally to fault.\n");
24789             HBtab->ebdHandlerType  = EH_HANDLER_FAULT_WAS_FINALLY;
24790             firstBlock->bbCatchTyp = BBCT_FAULT;
24791         }
24792         else
24793         {
24794             JITDUMP("Some callfinallys *not* retargeted, so region must remain as a finally.\n");
24795         }
24796
24797         // Modify first block of cloned finally to be a "normal" block.
24798         BasicBlock* firstClonedBlock = blockMap[firstBlock];
24799         firstClonedBlock->bbCatchTyp = BBCT_NONE;
24800
24801         // Cleanup the continuation
24802         fgCleanupContinuation(normalCallFinallyReturn);
24803
24804         // Todo -- mark cloned blocks as a cloned finally....
24805
24806         // Done!
24807         JITDUMP("\nDone with EH#%u\n\n", XTnum);
24808         cloneCount++;
24809     }
24810
24811     if (cloneCount > 0)
24812     {
24813         JITDUMP("fgCloneFinally() cloned %u finally handlers\n", cloneCount);
24814         fgOptimizedFinally = true;
24815
24816 #ifdef DEBUG
24817         if (verbose)
24818         {
24819             printf("\n*************** After fgCloneFinally()\n");
24820             fgDispBasicBlocks();
24821             fgDispHandlerTab();
24822             printf("\n");
24823         }
24824
24825         fgVerifyHandlerTab();
24826         fgDebugCheckBBlist(false, false);
24827         fgDebugCheckTryFinallyExits();
24828
24829 #endif // DEBUG
24830     }
24831 }
24832
24833 #ifdef DEBUG
24834
24835 //------------------------------------------------------------------------
24836 // fgDebugCheckTryFinallyExits: validate normal flow from try-finally
24837 // or try-fault-was-finally.
24838 //
24839 // Notes:
24840 //
24841 // Normal control flow exiting the try block of a try-finally must
24842 // pass through the finally. This checker attempts to verify that by
24843 // looking at the control flow graph.
24844 //
24845 // Each path that exits the try of a try-finally (including try-faults
24846 // that were optimized into try-finallys by fgCloneFinally) should
24847 // thus either execute a callfinally to the associated finally or else
24848 // jump to a block with the BBF_CLONED_FINALLY_BEGIN flag set.
24849 //
24850 // Depending on when this check is done, there may also be an empty
24851 // block along the path.
24852 //
24853 // Depending on the model for invoking finallys, the callfinallies may
24854 // lie within the try region (callfinally thunks) or in the enclosing
24855 // region.
24856
24857 void Compiler::fgDebugCheckTryFinallyExits()
24858 {
24859     unsigned  XTnum            = 0;
24860     EHblkDsc* HBtab            = compHndBBtab;
24861     unsigned  cloneCount       = 0;
24862     bool      allTryExitsValid = true;
24863     for (; XTnum < compHndBBtabCount; XTnum++, HBtab++)
24864     {
24865         const EHHandlerType handlerType = HBtab->ebdHandlerType;
24866         const bool          isFinally   = (handlerType == EH_HANDLER_FINALLY);
24867         const bool          wasFinally  = (handlerType == EH_HANDLER_FAULT_WAS_FINALLY);
24868
24869         // Screen out regions that are or were not finallys.
24870         if (!isFinally && !wasFinally)
24871         {
24872             continue;
24873         }
24874
24875         // Walk blocks of the try, looking for normal control flow to
24876         // an ancestor region.
24877
24878         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
24879         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
24880         assert(firstTryBlock->getTryIndex() <= XTnum);
24881         assert(lastTryBlock->getTryIndex() <= XTnum);
24882         BasicBlock* const afterTryBlock = lastTryBlock->bbNext;
24883         BasicBlock* const finallyBlock  = isFinally ? HBtab->ebdHndBeg : nullptr;
24884
24885         for (BasicBlock* block = firstTryBlock; block != afterTryBlock; block = block->bbNext)
24886         {
24887             // Only check the directly contained blocks.
24888             assert(block->hasTryIndex());
24889
24890             if (block->getTryIndex() != XTnum)
24891             {
24892                 continue;
24893             }
24894
24895             // Look at each of the normal control flow possibilities.
24896             const unsigned numSuccs = block->NumSucc();
24897
24898             for (unsigned i = 0; i < numSuccs; i++)
24899             {
24900                 BasicBlock* const succBlock = block->GetSucc(i);
24901
24902                 if (succBlock->hasTryIndex() && succBlock->getTryIndex() <= XTnum)
24903                 {
24904                     // Successor does not exit this try region.
24905                     continue;
24906                 }
24907
24908 #if FEATURE_EH_CALLFINALLY_THUNKS
24909
24910                 // When there are callfinally thunks, callfinallies
24911                 // logically "belong" to a child region and the exit
24912                 // path validity will be checked when looking at the
24913                 // try blocks in that region.
24914                 if (block->bbJumpKind == BBJ_CALLFINALLY)
24915                 {
24916                     continue;
24917                 }
24918
24919 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24920
24921                 // Now we know block lies directly within the try of a
24922                 // try-finally, and succBlock is in an enclosing
24923                 // region (possibly the method region). So this path
24924                 // represents flow out of the try and should be
24925                 // checked.
24926                 //
24927                 // There are various ways control can properly leave a
24928                 // try-finally (or try-fault-was-finally):
24929                 //
24930                 // (a1) via a jump to a callfinally (only for finallys, only for call finally thunks)
24931                 // (a2) via a callfinally (only for finallys, only for !call finally thunks)
24932                 // (b) via a jump to a begin finally clone block
24933                 // (c) via a jump to an empty block to (b)
24934                 // (d) via a fallthrough to an empty block to (b)
24935                 // (e) via the always half of a callfinally pair
24936                 // (f) via an always jump clonefinally exit
24937                 bool isCallToFinally = false;
24938
24939 #if FEATURE_EH_CALLFINALLY_THUNKS
24940                 if (succBlock->bbJumpKind == BBJ_CALLFINALLY)
24941                 {
24942                     // case (a1)
24943                     isCallToFinally = isFinally && (succBlock->bbJumpDest == finallyBlock);
24944                 }
24945 #else
24946                 if (block->bbJumpKind == BBJ_CALLFINALLY)
24947                 {
24948                     // case (a2)
24949                     isCallToFinally = isFinally && (block->bbJumpDest == finallyBlock);
24950                 }
24951 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24952
24953                 bool isJumpToClonedFinally = false;
24954
24955                 if (succBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24956                 {
24957                     // case (b)
24958                     isJumpToClonedFinally = true;
24959                 }
24960                 else if (succBlock->bbJumpKind == BBJ_ALWAYS)
24961                 {
24962                     if (succBlock->isEmpty())
24963                     {
24964                         // case (c)
24965                         BasicBlock* const succSuccBlock = succBlock->bbJumpDest;
24966
24967                         if (succSuccBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24968                         {
24969                             isJumpToClonedFinally = true;
24970                         }
24971                     }
24972                 }
24973                 else if (succBlock->bbJumpKind == BBJ_NONE)
24974                 {
24975                     if (succBlock->isEmpty())
24976                     {
24977                         BasicBlock* const succSuccBlock = succBlock->bbNext;
24978
24979                         // case (d)
24980                         if (succSuccBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24981                         {
24982                             isJumpToClonedFinally = true;
24983                         }
24984                     }
24985                 }
24986
24987                 bool isReturnFromFinally = false;
24988
24989                 // Case (e). Ideally we'd have something stronger to
24990                 // check here -- eg that we are returning from a call
24991                 // to the right finally -- but there are odd cases
24992                 // like orphaned second halves of callfinally pairs
24993                 // that we need to tolerate.
24994                 if (block->bbFlags & BBF_KEEP_BBJ_ALWAYS)
24995                 {
24996                     isReturnFromFinally = true;
24997                 }
24998
24999                 // Case (f)
25000                 if (block->bbFlags & BBF_CLONED_FINALLY_END)
25001                 {
25002                     isReturnFromFinally = true;
25003                 }
25004
25005                 const bool thisExitValid = isCallToFinally || isJumpToClonedFinally || isReturnFromFinally;
25006
25007                 if (!thisExitValid)
25008                 {
25009                     JITDUMP("fgCheckTryFinallyExitS: EH#%u exit via BB%02u -> BB%02u is invalid\n", XTnum, block->bbNum,
25010                             succBlock->bbNum);
25011                 }
25012
25013                 allTryExitsValid = allTryExitsValid & thisExitValid;
25014             }
25015         }
25016     }
25017
25018     if (!allTryExitsValid)
25019     {
25020         JITDUMP("fgCheckTryFinallyExits: method contains invalid try exit paths\n");
25021         assert(allTryExitsValid);
25022     }
25023 }
25024
25025 #endif // DEBUG
25026
25027 //------------------------------------------------------------------------
25028 // fgCleanupContinuation: cleanup a finally continuation after a
25029 // finally is removed or converted to normal control flow.
25030 //
25031 // Notes:
25032 //    The continuation is the block targeted by the second half of
25033 //    a callfinally/always pair.
25034 //
25035 //    Used by finally cloning, empty try removal, and empty
25036 //    finally removal.
25037 //
25038 //    BBF_FINALLY_TARGET bbFlag is left unchanged by this method
25039 //    since it cannot be incrementally updated. Proper updates happen
25040 //    when fgUpdateFinallyTargetFlags runs after all finally optimizations.
25041
25042 void Compiler::fgCleanupContinuation(BasicBlock* continuation)
25043 {
25044     // The continuation may be a finalStep block.
25045     // It is now a normal block, so clear the special keep
25046     // always flag.
25047     continuation->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
25048
25049 #if !FEATURE_EH_FUNCLETS
25050     // Remove the GT_END_LFIN from the continuation,
25051     // Note we only expect to see one such statement.
25052     bool foundEndLFin = false;
25053     for (GenTreeStmt* stmt = continuation->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
25054     {
25055         GenTree* expr = stmt->gtStmtExpr;
25056         if (expr->gtOper == GT_END_LFIN)
25057         {
25058             assert(!foundEndLFin);
25059             fgRemoveStmt(continuation, stmt);
25060             foundEndLFin = true;
25061         }
25062     }
25063     assert(foundEndLFin);
25064 #endif // !FEATURE_EH_FUNCLETS
25065 }
25066
25067 //------------------------------------------------------------------------
25068 // fgUpdateFinallyTargetFlags: recompute BBF_FINALLY_TARGET bits for all blocks
25069 // after finally optimizations have run.
25070
25071 void Compiler::fgUpdateFinallyTargetFlags()
25072 {
25073 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25074
25075     // Any fixup required?
25076     if (!fgOptimizedFinally)
25077     {
25078         JITDUMP("In fgUpdateFinallyTargetFlags - no finally opts, no fixup required\n");
25079         return;
25080     }
25081
25082     JITDUMP("In fgUpdateFinallyTargetFlags, updating finally target flag bits\n");
25083
25084     fgClearAllFinallyTargetBits();
25085     fgAddFinallyTargetFlags();
25086
25087 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25088 }
25089
25090 //------------------------------------------------------------------------
25091 // fgClearAllFinallyTargetBits: Clear all BBF_FINALLY_TARGET bits; these will need to be
25092 // recomputed later.
25093 //
25094 void Compiler::fgClearAllFinallyTargetBits()
25095 {
25096 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25097
25098     JITDUMP("*************** In fgClearAllFinallyTargetBits()\n");
25099
25100     // Note that we clear the flags even if there are no EH clauses (compHndBBtabCount == 0)
25101     // in case bits are left over from EH clauses being deleted.
25102
25103     // Walk all blocks, and reset the target bits.
25104     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25105     {
25106         block->bbFlags &= ~BBF_FINALLY_TARGET;
25107     }
25108
25109 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25110 }
25111
25112 //------------------------------------------------------------------------
25113 // fgAddFinallyTargetFlags: Add BBF_FINALLY_TARGET bits to all finally targets.
25114 //
25115 void Compiler::fgAddFinallyTargetFlags()
25116 {
25117 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25118
25119     JITDUMP("*************** In fgAddFinallyTargetFlags()\n");
25120
25121     if (compHndBBtabCount == 0)
25122     {
25123         JITDUMP("No EH in this method, no flags to set.\n");
25124         return;
25125     }
25126
25127     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25128     {
25129         if (block->isBBCallAlwaysPair())
25130         {
25131             BasicBlock* const leave        = block->bbNext;
25132             BasicBlock* const continuation = leave->bbJumpDest;
25133
25134             if ((continuation->bbFlags & BBF_FINALLY_TARGET) == 0)
25135             {
25136                 JITDUMP("Found callfinally BB%02u; setting finally target bit on BB%02u\n", block->bbNum,
25137                         continuation->bbNum);
25138
25139                 continuation->bbFlags |= BBF_FINALLY_TARGET;
25140             }
25141         }
25142     }
25143 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25144 }
25145
25146 //------------------------------------------------------------------------
25147 // fgMergeFinallyChains: tail merge finally invocations
25148 //
25149 // Notes:
25150 //
25151 //    Looks for common suffixes in chains of finally invocations
25152 //    (callfinallys) and merges them. These typically arise from
25153 //    try-finallys where there are multiple exit points in the try
25154 //    that have the same target.
25155
25156 void Compiler::fgMergeFinallyChains()
25157 {
25158     JITDUMP("\n*************** In fgMergeFinallyChains()\n");
25159
25160 #if FEATURE_EH_FUNCLETS
25161     // We need to do this transformation before funclets are created.
25162     assert(!fgFuncletsCreated);
25163 #endif // FEATURE_EH_FUNCLETS
25164
25165     // Assume we don't need to update the bbPreds lists.
25166     assert(!fgComputePredsDone);
25167
25168     if (compHndBBtabCount == 0)
25169     {
25170         JITDUMP("No EH in this method, nothing to merge.\n");
25171         return;
25172     }
25173
25174     if (opts.MinOpts())
25175     {
25176         JITDUMP("Method compiled with minOpts, no merging.\n");
25177         return;
25178     }
25179
25180     if (opts.compDbgCode)
25181     {
25182         JITDUMP("Method compiled with debug codegen, no merging.\n");
25183         return;
25184     }
25185
25186     bool enableMergeFinallyChains = true;
25187
25188 #if !FEATURE_EH_FUNCLETS
25189     // For non-funclet models (x86) the callfinallys may contain
25190     // statements and the continuations contain GT_END_LFINs.  So no
25191     // merging is possible until the GT_END_LFIN blocks can be merged
25192     // and merging is not safe unless the callfinally blocks are split.
25193     JITDUMP("EH using non-funclet model; merging not yet implemented.\n");
25194     enableMergeFinallyChains = false;
25195 #endif // !FEATURE_EH_FUNCLETS
25196
25197 #if !FEATURE_EH_CALLFINALLY_THUNKS
25198     // For non-thunk EH models (arm32) the callfinallys may contain
25199     // statements, and merging is not safe unless the callfinally
25200     // blocks are split.
25201     JITDUMP("EH using non-callfinally thunk model; merging not yet implemented.\n");
25202     enableMergeFinallyChains = false;
25203 #endif
25204
25205     if (!enableMergeFinallyChains)
25206     {
25207         JITDUMP("fgMergeFinallyChains disabled\n");
25208         return;
25209     }
25210
25211 #ifdef DEBUG
25212     if (verbose)
25213     {
25214         printf("\n*************** Before fgMergeFinallyChains()\n");
25215         fgDispBasicBlocks();
25216         fgDispHandlerTab();
25217         printf("\n");
25218     }
25219 #endif // DEBUG
25220
25221     // Look for finallys.
25222     bool hasFinally = false;
25223     for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
25224     {
25225         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
25226
25227         // Check if this is a try/finally.
25228         if (HBtab->HasFinallyHandler())
25229         {
25230             hasFinally = true;
25231             break;
25232         }
25233     }
25234
25235     if (!hasFinally)
25236     {
25237         JITDUMP("Method does not have any try-finallys; no merging.\n");
25238         return;
25239     }
25240
25241     // Process finallys from outside in, merging as we go. This gives
25242     // us the desired bottom-up tail merge order for callfinally
25243     // chains: outer merges may enable inner merges.
25244     bool            canMerge = false;
25245     bool            didMerge = false;
25246     BlockToBlockMap continuationMap(getAllocator());
25247
25248     // Note XTnum is signed here so we can count down.
25249     for (int XTnum = compHndBBtabCount - 1; XTnum >= 0; XTnum--)
25250     {
25251         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
25252
25253         // Screen out non-finallys
25254         if (!HBtab->HasFinallyHandler())
25255         {
25256             continue;
25257         }
25258
25259         JITDUMP("Examining callfinallys for EH#%d.\n", XTnum);
25260
25261         // Find all the callfinallys that invoke this finally.
25262         BasicBlock* firstCallFinallyRangeBlock = nullptr;
25263         BasicBlock* endCallFinallyRangeBlock   = nullptr;
25264         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
25265
25266         // Clear out any stale entries in the continuation map
25267         continuationMap.RemoveAll();
25268
25269         // Build a map from each continuation to the "canonical"
25270         // callfinally for that continuation.
25271         unsigned          callFinallyCount  = 0;
25272         BasicBlock* const beginHandlerBlock = HBtab->ebdHndBeg;
25273
25274         for (BasicBlock* currentBlock = firstCallFinallyRangeBlock; currentBlock != endCallFinallyRangeBlock;
25275              currentBlock             = currentBlock->bbNext)
25276         {
25277             // Ignore "retless" callfinallys (where the finally doesn't return).
25278             if (currentBlock->isBBCallAlwaysPair() && (currentBlock->bbJumpDest == beginHandlerBlock))
25279             {
25280                 // The callfinally must be empty, so that we can
25281                 // safely retarget anything that branches here to
25282                 // another callfinally with the same contiuation.
25283                 assert(currentBlock->isEmpty());
25284
25285                 // This callfinally invokes the finally for this try.
25286                 callFinallyCount++;
25287
25288                 // Locate the continuation
25289                 BasicBlock* const leaveBlock        = currentBlock->bbNext;
25290                 BasicBlock* const continuationBlock = leaveBlock->bbJumpDest;
25291
25292                 // If this is the first time we've seen this
25293                 // continuation, register this callfinally as the
25294                 // canonical one.
25295                 if (!continuationMap.Lookup(continuationBlock))
25296                 {
25297                     continuationMap.Set(continuationBlock, currentBlock);
25298                 }
25299             }
25300         }
25301
25302         // Now we've seen all the callfinallys and their continuations.
25303         JITDUMP("EH#%i has %u callfinallys, %u continuations\n", XTnum, callFinallyCount, continuationMap.GetCount());
25304
25305         // If there are more callfinallys than continuations, some of the
25306         // callfinallys must share a continuation, and we can merge them.
25307         const bool tryMerge = callFinallyCount > continuationMap.GetCount();
25308
25309         if (!tryMerge)
25310         {
25311             JITDUMP("EH#%i does not have any mergeable callfinallys\n", XTnum);
25312             continue;
25313         }
25314
25315         canMerge = true;
25316
25317         // Walk the callfinally region, looking for blocks that jump
25318         // to a callfinally that invokes this try's finally, and make
25319         // sure they all jump to the appropriate canonical
25320         // callfinally.
25321         for (BasicBlock* currentBlock = firstCallFinallyRangeBlock; currentBlock != endCallFinallyRangeBlock;
25322              currentBlock             = currentBlock->bbNext)
25323         {
25324             bool merged = fgRetargetBranchesToCanonicalCallFinally(currentBlock, beginHandlerBlock, continuationMap);
25325             didMerge    = didMerge || merged;
25326         }
25327     }
25328
25329     if (!canMerge)
25330     {
25331         JITDUMP("Method had try-finallys, but did not have any mergeable finally chains.\n");
25332     }
25333     else
25334     {
25335         if (didMerge)
25336         {
25337             JITDUMP("Method had mergeable try-finallys and some callfinally merges were performed.\n");
25338
25339 #if DEBUG
25340             if (verbose)
25341             {
25342                 printf("\n*************** After fgMergeFinallyChains()\n");
25343                 fgDispBasicBlocks();
25344                 fgDispHandlerTab();
25345                 printf("\n");
25346             }
25347
25348 #endif // DEBUG
25349         }
25350         else
25351         {
25352             // We may not end up doing any merges, because we are only
25353             // merging continuations for callfinallys that can
25354             // actually be invoked, and the importer may leave
25355             // unreachable callfinallys around (for instance, if it
25356             // is forced to re-import a leave).
25357             JITDUMP("Method had mergeable try-finallys but no callfinally merges were performed,\n"
25358                     "likely the non-canonical callfinallys were unreachable\n");
25359         }
25360     }
25361 }
25362
25363 //------------------------------------------------------------------------
25364 // fgRetargetBranchesToCanonicalCallFinally: find non-canonical callfinally
25365 // invocations and make them canonical.
25366 //
25367 // Arguments:
25368 //     block -- block to examine for call finally invocation
25369 //     handler -- start of the finally region for the try
25370 //     continuationMap -- map giving the canonical callfinally for
25371 //        each continuation
25372 //
25373 // Returns:
25374 //     true iff the block's branch was retargeted.
25375
25376 bool Compiler::fgRetargetBranchesToCanonicalCallFinally(BasicBlock*      block,
25377                                                         BasicBlock*      handler,
25378                                                         BlockToBlockMap& continuationMap)
25379 {
25380     // We expect callfinallys to be invoked by a BBJ_ALWAYS at this
25381     // stage in compilation.
25382     if (block->bbJumpKind != BBJ_ALWAYS)
25383     {
25384         // Possible paranoia assert here -- no flow successor of
25385         // this block should be a callfinally for this try.
25386         return false;
25387     }
25388
25389     // Screen out cases that are not callfinallys to the right
25390     // handler.
25391     BasicBlock* const callFinally = block->bbJumpDest;
25392
25393     if (!callFinally->isBBCallAlwaysPair())
25394     {
25395         return false;
25396     }
25397
25398     if (callFinally->bbJumpDest != handler)
25399     {
25400         return false;
25401     }
25402
25403     // Ok, this is a callfinally that invokes the right handler.
25404     // Get its continuation.
25405     BasicBlock* const leaveBlock        = callFinally->bbNext;
25406     BasicBlock* const continuationBlock = leaveBlock->bbJumpDest;
25407
25408     // Find the canonical callfinally for that continuation.
25409     BasicBlock* const canonicalCallFinally = continuationMap[continuationBlock];
25410     assert(canonicalCallFinally != nullptr);
25411
25412     // If the block already jumps to the canoncial call finally, no work needed.
25413     if (block->bbJumpDest == canonicalCallFinally)
25414     {
25415         JITDUMP("BB%02u already canonical\n", block->bbNum);
25416         return false;
25417     }
25418
25419     // Else, retarget it so that it does...
25420     JITDUMP("Redirecting branch in BB%02u from BB%02u to BB%02u.\n", block->bbNum, callFinally->bbNum,
25421             canonicalCallFinally->bbNum);
25422
25423     block->bbJumpDest = canonicalCallFinally;
25424     fgAddRefPred(canonicalCallFinally, block);
25425     assert(callFinally->bbRefs > 0);
25426     fgRemoveRefPred(callFinally, block);
25427
25428     return true;
25429 }
25430
25431 // FatCalliTransformer transforms calli that can use fat function pointer.
25432 // Fat function pointer is pointer with the second least significant bit set,
25433 // if the bit is set, the pointer (after clearing the bit) actually points to
25434 // a tuple <method pointer, instantiation argument pointer> where
25435 // instantiationArgument is a hidden first argument required by method pointer.
25436 //
25437 // Fat pointers are used in CoreRT as a replacement for instantiating stubs,
25438 // because CoreRT can't generate stubs in runtime.
25439 //
25440 // Jit is responsible for the checking the bit, do the regular call if it is not set
25441 // or load hidden argument, fix the pointer and make a call with the fixed pointer and
25442 // the instantiation argument.
25443 //
25444 // before:
25445 //   current block
25446 //   {
25447 //     previous statements
25448 //     transforming statement
25449 //     {
25450 //       call with GTF_CALL_M_FAT_POINTER_CHECK flag set in function ptr
25451 //     }
25452 //     subsequent statements
25453 //   }
25454 //
25455 // after:
25456 //   current block
25457 //   {
25458 //     previous statements
25459 //   } BBJ_NONE check block
25460 //   check block
25461 //   {
25462 //     jump to else if function ptr has GTF_CALL_M_FAT_POINTER_CHECK set.
25463 //   } BBJ_COND then block, else block
25464 //   then block
25465 //   {
25466 //     original statement
25467 //   } BBJ_ALWAYS remainder block
25468 //   else block
25469 //   {
25470 //     unset GTF_CALL_M_FAT_POINTER_CHECK
25471 //     load actual function pointer
25472 //     load instantiation argument
25473 //     create newArgList = (instantiation argument, original argList)
25474 //     call (actual function pointer, newArgList)
25475 //   } BBJ_NONE remainder block
25476 //   remainder block
25477 //   {
25478 //     subsequent statements
25479 //   }
25480 //
25481 class FatCalliTransformer
25482 {
25483 public:
25484     FatCalliTransformer(Compiler* compiler) : compiler(compiler)
25485     {
25486     }
25487
25488     //------------------------------------------------------------------------
25489     // Run: run transformation for each block.
25490     //
25491     void Run()
25492     {
25493         for (BasicBlock* block = compiler->fgFirstBB; block != nullptr; block = block->bbNext)
25494         {
25495             TransformBlock(block);
25496         }
25497     }
25498
25499 private:
25500     //------------------------------------------------------------------------
25501     // TransformBlock: look through statements and transform statements with fat pointer calls.
25502     //
25503     void TransformBlock(BasicBlock* block)
25504     {
25505         for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
25506         {
25507             if (ContainsFatCalli(stmt))
25508             {
25509                 StatementTransformer stmtTransformer(compiler, block, stmt);
25510                 stmtTransformer.Run();
25511             }
25512         }
25513     }
25514
25515     //------------------------------------------------------------------------
25516     // ContainsFatCalli: check does this statement contain fat pointer call.
25517     //
25518     // Checks fatPointerCandidate in form of call() or lclVar = call().
25519     //
25520     // Return Value:
25521     //    true if contains, false otherwise.
25522     //
25523     bool ContainsFatCalli(GenTreeStmt* stmt)
25524     {
25525         GenTree* fatPointerCandidate = stmt->gtStmtExpr;
25526         if (fatPointerCandidate->OperIsAssignment())
25527         {
25528             fatPointerCandidate = fatPointerCandidate->gtGetOp2();
25529         }
25530         return fatPointerCandidate->IsCall() && fatPointerCandidate->AsCall()->IsFatPointerCandidate();
25531     }
25532
25533     class StatementTransformer
25534     {
25535     public:
25536         StatementTransformer(Compiler* compiler, BasicBlock* block, GenTreeStmt* stmt)
25537             : compiler(compiler), currBlock(block), stmt(stmt)
25538         {
25539             remainderBlock  = nullptr;
25540             checkBlock      = nullptr;
25541             thenBlock       = nullptr;
25542             elseBlock       = nullptr;
25543             doesReturnValue = stmt->gtStmtExpr->OperIsAssignment();
25544             origCall        = GetCall(stmt);
25545             fptrAddress     = origCall->gtCallAddr;
25546             pointerType     = fptrAddress->TypeGet();
25547         }
25548
25549         //------------------------------------------------------------------------
25550         // Run: transform the statement as described above.
25551         //
25552         void Run()
25553         {
25554             ClearFatFlag();
25555             CreateRemainder();
25556             CreateCheck();
25557             CreateThen();
25558             CreateElse();
25559
25560             RemoveOldStatement();
25561             SetWeights();
25562             ChainFlow();
25563         }
25564
25565     private:
25566         //------------------------------------------------------------------------
25567         // GetCall: find a call in a statement.
25568         //
25569         // Arguments:
25570         //    callStmt - the statement with the call inside.
25571         //
25572         // Return Value:
25573         //    call tree node pointer.
25574         GenTreeCall* GetCall(GenTreeStmt* callStmt)
25575         {
25576             GenTree*     tree = callStmt->gtStmtExpr;
25577             GenTreeCall* call = nullptr;
25578             if (doesReturnValue)
25579             {
25580                 assert(tree->OperIsAssignment());
25581                 call = tree->gtGetOp2()->AsCall();
25582             }
25583             else
25584             {
25585                 call = tree->AsCall(); // call with void return type.
25586             }
25587             return call;
25588         }
25589
25590         //------------------------------------------------------------------------
25591         // ClearFatFlag: clear fat pointer candidate flag from the original call.
25592         //
25593         void ClearFatFlag()
25594         {
25595             origCall->ClearFatPointerCandidate();
25596         }
25597
25598         //------------------------------------------------------------------------
25599         // CreateRemainder: split current block at the fat call stmt and
25600         // insert statements after the call into remainderBlock.
25601         //
25602         void CreateRemainder()
25603         {
25604             remainderBlock          = compiler->fgSplitBlockAfterStatement(currBlock, stmt);
25605             unsigned propagateFlags = currBlock->bbFlags & BBF_GC_SAFE_POINT;
25606             remainderBlock->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL | propagateFlags;
25607         }
25608
25609         //------------------------------------------------------------------------
25610         // CreateCheck: create check block, that checks fat pointer bit set.
25611         //
25612         void CreateCheck()
25613         {
25614             checkBlock               = CreateAndInsertBasicBlock(BBJ_COND, currBlock);
25615             GenTree* fatPointerMask  = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, FAT_POINTER_MASK);
25616             GenTree* fptrAddressCopy = compiler->gtCloneExpr(fptrAddress);
25617             GenTree* fatPointerAnd   = compiler->gtNewOperNode(GT_AND, TYP_I_IMPL, fptrAddressCopy, fatPointerMask);
25618             GenTree* zero            = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, 0);
25619             GenTree* fatPointerCmp   = compiler->gtNewOperNode(GT_NE, TYP_INT, fatPointerAnd, zero);
25620             GenTree* jmpTree         = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, fatPointerCmp);
25621             GenTree* jmpStmt         = compiler->fgNewStmtFromTree(jmpTree, stmt->gtStmt.gtStmtILoffsx);
25622             compiler->fgInsertStmtAtEnd(checkBlock, jmpStmt);
25623         }
25624
25625         //------------------------------------------------------------------------
25626         // CreateCheck: create then block, that is executed if call address is not fat pointer.
25627         //
25628         void CreateThen()
25629         {
25630             thenBlock               = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock);
25631             GenTree* nonFatCallStmt = compiler->gtCloneExpr(stmt)->AsStmt();
25632             compiler->fgInsertStmtAtEnd(thenBlock, nonFatCallStmt);
25633         }
25634
25635         //------------------------------------------------------------------------
25636         // CreateCheck: create else block, that is executed if call address is fat pointer.
25637         //
25638         void CreateElse()
25639         {
25640             elseBlock = CreateAndInsertBasicBlock(BBJ_NONE, thenBlock);
25641
25642             GenTree* fixedFptrAddress  = GetFixedFptrAddress();
25643             GenTree* actualCallAddress = compiler->gtNewOperNode(GT_IND, pointerType, fixedFptrAddress);
25644             GenTree* hiddenArgument    = GetHiddenArgument(fixedFptrAddress);
25645
25646             GenTreeStmt* fatStmt = CreateFatCallStmt(actualCallAddress, hiddenArgument);
25647             compiler->fgInsertStmtAtEnd(elseBlock, fatStmt);
25648         }
25649
25650         //------------------------------------------------------------------------
25651         // CreateAndInsertBasicBlock: ask compiler to create new basic block.
25652         // and insert in into the basic block list.
25653         //
25654         // Arguments:
25655         //    jumpKind - jump kind for the new basic block
25656         //    insertAfter - basic block, after which compiler has to insert the new one.
25657         //
25658         // Return Value:
25659         //    new basic block.
25660         BasicBlock* CreateAndInsertBasicBlock(BBjumpKinds jumpKind, BasicBlock* insertAfter)
25661         {
25662             BasicBlock* block = compiler->fgNewBBafter(jumpKind, insertAfter, true);
25663             if ((insertAfter->bbFlags & BBF_INTERNAL) == 0)
25664             {
25665                 block->bbFlags &= ~BBF_INTERNAL;
25666                 block->bbFlags |= BBF_IMPORTED;
25667             }
25668             return block;
25669         }
25670
25671         //------------------------------------------------------------------------
25672         // GetFixedFptrAddress: clear fat pointer bit from fat pointer address.
25673         //
25674         // Return Value:
25675         //    address without fat pointer bit set.
25676         GenTree* GetFixedFptrAddress()
25677         {
25678             GenTree* fptrAddressCopy = compiler->gtCloneExpr(fptrAddress);
25679             GenTree* fatPointerMask  = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, FAT_POINTER_MASK);
25680             return compiler->gtNewOperNode(GT_SUB, pointerType, fptrAddressCopy, fatPointerMask);
25681         }
25682
25683         //------------------------------------------------------------------------
25684         // GetHiddenArgument: load hidden argument.
25685         //
25686         // Arguments:
25687         //    fixedFptrAddress - pointer to the tuple <methodPointer, instantiationArgumentPointer>
25688         //
25689         // Return Value:
25690         //    generic context hidden argument.
25691         GenTree* GetHiddenArgument(GenTree* fixedFptrAddress)
25692         {
25693             GenTree* fixedFptrAddressCopy = compiler->gtCloneExpr(fixedFptrAddress);
25694             GenTree* wordSize = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, genTypeSize(TYP_I_IMPL));
25695             GenTree* hiddenArgumentPtrPtr =
25696                 compiler->gtNewOperNode(GT_ADD, pointerType, fixedFptrAddressCopy, wordSize);
25697             GenTree* hiddenArgumentPtr = compiler->gtNewOperNode(GT_IND, pointerType, hiddenArgumentPtrPtr);
25698             return compiler->gtNewOperNode(GT_IND, fixedFptrAddressCopy->TypeGet(), hiddenArgumentPtr);
25699         }
25700
25701         //------------------------------------------------------------------------
25702         // CreateFatCallStmt: create call with fixed call address and hidden argument in the args list.
25703         //
25704         // Arguments:
25705         //    actualCallAddress - fixed call address
25706         //    hiddenArgument - generic context hidden argument
25707         //
25708         // Return Value:
25709         //    created call node.
25710         GenTreeStmt* CreateFatCallStmt(GenTree* actualCallAddress, GenTree* hiddenArgument)
25711         {
25712             GenTreeStmt* fatStmt = compiler->gtCloneExpr(stmt)->AsStmt();
25713             GenTree*     fatTree = fatStmt->gtStmtExpr;
25714             GenTreeCall* fatCall = GetCall(fatStmt);
25715             fatCall->gtCallAddr  = actualCallAddress;
25716             AddHiddenArgument(fatCall, hiddenArgument);
25717             return fatStmt;
25718         }
25719
25720         //------------------------------------------------------------------------
25721         // AddHiddenArgument: add hidden argument to the call argument list.
25722         //
25723         // Arguments:
25724         //    fatCall - fat call node
25725         //    hiddenArgument - generic context hidden argument
25726         //
25727         void AddHiddenArgument(GenTreeCall* fatCall, GenTree* hiddenArgument)
25728         {
25729             GenTreeArgList* oldArgs = fatCall->gtCallArgs;
25730             GenTreeArgList* newArgs;
25731 #if USER_ARGS_COME_LAST
25732             if (fatCall->HasRetBufArg())
25733             {
25734                 GenTree*        retBuffer = oldArgs->Current();
25735                 GenTreeArgList* rest      = oldArgs->Rest();
25736                 newArgs                   = compiler->gtNewListNode(hiddenArgument, rest);
25737                 newArgs                   = compiler->gtNewListNode(retBuffer, newArgs);
25738             }
25739             else
25740             {
25741                 newArgs = compiler->gtNewListNode(hiddenArgument, oldArgs);
25742             }
25743 #else
25744             newArgs = oldArgs;
25745             AddArgumentToTail(newArgs, hiddenArgument);
25746 #endif
25747             fatCall->gtCallArgs = newArgs;
25748         }
25749
25750         //------------------------------------------------------------------------
25751         // AddArgumentToTail: add hidden argument to the tail of the call argument list.
25752         //
25753         // Arguments:
25754         //    argList - fat call node
25755         //    hiddenArgument - generic context hidden argument
25756         //
25757         void AddArgumentToTail(GenTreeArgList* argList, GenTree* hiddenArgument)
25758         {
25759             GenTreeArgList* iterator = argList;
25760             while (iterator->Rest() != nullptr)
25761             {
25762                 iterator = iterator->Rest();
25763             }
25764             iterator->Rest() = compiler->gtNewArgList(hiddenArgument);
25765         }
25766
25767         //------------------------------------------------------------------------
25768         // RemoveOldStatement: remove original stmt from current block.
25769         //
25770         void RemoveOldStatement()
25771         {
25772             compiler->fgRemoveStmt(currBlock, stmt);
25773         }
25774
25775         //------------------------------------------------------------------------
25776         // SetWeights: set weights for new blocks.
25777         //
25778         void SetWeights()
25779         {
25780             remainderBlock->inheritWeight(currBlock);
25781             checkBlock->inheritWeight(currBlock);
25782             thenBlock->inheritWeightPercentage(currBlock, HIGH_PROBABILITY);
25783             elseBlock->inheritWeightPercentage(currBlock, 100 - HIGH_PROBABILITY);
25784         }
25785
25786         //------------------------------------------------------------------------
25787         // ChainFlow: link new blocks into correct cfg.
25788         //
25789         void ChainFlow()
25790         {
25791             assert(!compiler->fgComputePredsDone);
25792             checkBlock->bbJumpDest = elseBlock;
25793             thenBlock->bbJumpDest  = remainderBlock;
25794         }
25795
25796         Compiler*    compiler;
25797         BasicBlock*  currBlock;
25798         BasicBlock*  remainderBlock;
25799         BasicBlock*  checkBlock;
25800         BasicBlock*  thenBlock;
25801         BasicBlock*  elseBlock;
25802         GenTreeStmt* stmt;
25803         GenTreeCall* origCall;
25804         GenTree*     fptrAddress;
25805         var_types    pointerType;
25806         bool         doesReturnValue;
25807
25808         const int FAT_POINTER_MASK = 0x2;
25809         const int HIGH_PROBABILITY = 80;
25810     };
25811
25812     Compiler* compiler;
25813 };
25814
25815 #ifdef DEBUG
25816
25817 //------------------------------------------------------------------------
25818 // fgDebugCheckFatPointerCandidates: callback to make sure there are no more GTF_CALL_M_FAT_POINTER_CHECK calls.
25819 //
25820 Compiler::fgWalkResult Compiler::fgDebugCheckFatPointerCandidates(GenTree** pTree, fgWalkData* data)
25821 {
25822     GenTree* tree = *pTree;
25823     if (tree->IsCall())
25824     {
25825         assert(!tree->AsCall()->IsFatPointerCandidate());
25826     }
25827     return WALK_CONTINUE;
25828 }
25829
25830 //------------------------------------------------------------------------
25831 // CheckNoFatPointerCandidatesLeft: walk through blocks and check that there are no fat pointer candidates left.
25832 //
25833 void Compiler::CheckNoFatPointerCandidatesLeft()
25834 {
25835     assert(!doesMethodHaveFatPointer());
25836     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25837     {
25838         for (GenTreeStmt* stmt = fgFirstBB->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
25839         {
25840             fgWalkTreePre(&stmt->gtStmtExpr, fgDebugCheckFatPointerCandidates);
25841         }
25842     }
25843 }
25844 #endif
25845
25846 //------------------------------------------------------------------------
25847 // fgTransformFatCalli: find and transform fat calls.
25848 //
25849 void Compiler::fgTransformFatCalli()
25850 {
25851     assert(IsTargetAbi(CORINFO_CORERT_ABI));
25852     FatCalliTransformer fatCalliTransformer(this);
25853     fatCalliTransformer.Run();
25854     clearMethodHasFatPointer();
25855 #ifdef DEBUG
25856     CheckNoFatPointerCandidatesLeft();
25857 #endif
25858 }
25859
25860 //------------------------------------------------------------------------
25861 // fgMeasureIR: count and return the number of IR nodes in the function.
25862 //
25863 unsigned Compiler::fgMeasureIR()
25864 {
25865     unsigned nodeCount = 0;
25866
25867     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25868     {
25869         if (!block->IsLIR())
25870         {
25871             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt())
25872             {
25873                 fgWalkTreePre(&stmt->gtStmtExpr,
25874                               [](GenTree** slot, fgWalkData* data) -> Compiler::fgWalkResult {
25875                                   (*reinterpret_cast<unsigned*>(data->pCallbackData))++;
25876                                   return Compiler::WALK_CONTINUE;
25877                               },
25878                               &nodeCount);
25879             }
25880         }
25881         else
25882         {
25883             for (GenTree* node : LIR::AsRange(block))
25884             {
25885                 nodeCount++;
25886             }
25887         }
25888     }
25889
25890     return nodeCount;
25891 }
25892
25893 //------------------------------------------------------------------------
25894 // fgCompDominatedByExceptionalEntryBlocks: compute blocks that are
25895 // dominated by not normal entry.
25896 //
25897 void Compiler::fgCompDominatedByExceptionalEntryBlocks()
25898 {
25899     assert(fgEnterBlksSetValid);
25900     if (BlockSetOps::Count(this, fgEnterBlks) != 1) // There are exception entries.
25901     {
25902         for (unsigned i = 1; i <= fgBBNumMax; ++i)
25903         {
25904             BasicBlock* block = fgBBInvPostOrder[i];
25905             if (BlockSetOps::IsMember(this, fgEnterBlks, block->bbNum))
25906             {
25907                 if (fgFirstBB != block) // skip the normal entry.
25908                 {
25909                     block->SetDominatedByExceptionalEntryFlag();
25910                 }
25911             }
25912             else if (block->bbIDom->IsDominatedByExceptionalEntryFlag())
25913             {
25914                 block->SetDominatedByExceptionalEntryFlag();
25915             }
25916         }
25917     }
25918 }
25919
25920 //------------------------------------------------------------------------
25921 // fgNeedReturnSpillTemp: Answers does the inlinee need to spill all returns
25922 //  as a temp.
25923 //
25924 // Return Value:
25925 //    true if the inlinee has to spill return exprs.
25926 bool Compiler::fgNeedReturnSpillTemp()
25927 {
25928     assert(compIsForInlining());
25929     return (lvaInlineeReturnSpillTemp != BAD_VAR_NUM);
25930 }
25931
25932 //------------------------------------------------------------------------
25933 // fgUseThrowHelperBlocks: Determinate does compiler use throw helper blocks.
25934 //
25935 // Note:
25936 //   For debuggable code, codegen will generate the 'throw' code inline.
25937 // Return Value:
25938 //    true if 'throw' helper block should be created.
25939 bool Compiler::fgUseThrowHelperBlocks()
25940 {
25941     return !opts.compDbgCode;
25942 }