0fbd577bf13fc635b2b72095be760af0a4b2b822
[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 #include "lower.h"       // for LowerRange()
21
22 /*****************************************************************************/
23
24 void Compiler::fgInit()
25 {
26     impInit();
27
28     /* Initialization for fgWalkTreePre() and fgWalkTreePost() */
29
30     fgFirstBBScratch = nullptr;
31
32 #ifdef DEBUG
33     fgPrintInlinedMethods = JitConfig.JitPrintInlinedMethods() == 1;
34 #endif // DEBUG
35
36     /* We haven't yet computed the bbPreds lists */
37     fgComputePredsDone = false;
38
39     /* We haven't yet computed the bbCheapPreds lists */
40     fgCheapPredsValid = false;
41
42     /* We haven't yet computed the edge weight */
43     fgEdgeWeightsComputed    = false;
44     fgHaveValidEdgeWeights   = false;
45     fgSlopUsedInEdgeWeights  = false;
46     fgRangeUsedInEdgeWeights = true;
47     fgNeedsUpdateFlowGraph   = false;
48     fgCalledCount            = BB_ZERO_WEIGHT;
49
50     /* We haven't yet computed the dominator sets */
51     fgDomsComputed = false;
52
53 #ifdef DEBUG
54     fgReachabilitySetsValid = false;
55 #endif // DEBUG
56
57     /* We don't know yet which loops will always execute calls */
58     fgLoopCallMarked = false;
59
60     /* We haven't created GC Poll blocks yet. */
61     fgGCPollsCreated = false;
62
63     /* Initialize the basic block list */
64
65     fgFirstBB        = nullptr;
66     fgLastBB         = nullptr;
67     fgFirstColdBlock = nullptr;
68
69 #if FEATURE_EH_FUNCLETS
70     fgFirstFuncletBB  = nullptr;
71     fgFuncletsCreated = false;
72 #endif // FEATURE_EH_FUNCLETS
73
74     fgBBcount = 0;
75
76 #ifdef DEBUG
77     fgBBcountAtCodegen = 0;
78 #endif // DEBUG
79
80     fgBBNumMax        = 0;
81     fgEdgeCount       = 0;
82     fgDomBBcount      = 0;
83     fgBBVarSetsInited = false;
84     fgReturnCount     = 0;
85
86     // Initialize BlockSet data.
87     fgCurBBEpoch             = 0;
88     fgCurBBEpochSize         = 0;
89     fgBBSetCountInSizeTUnits = 0;
90
91     genReturnBB = nullptr;
92
93     /* We haven't reached the global morphing phase */
94     fgGlobalMorph = false;
95     fgModified    = false;
96
97 #ifdef DEBUG
98     fgSafeBasicBlockCreation = true;
99 #endif // DEBUG
100
101     fgLocalVarLivenessDone = false;
102
103     /* Statement list is not threaded yet */
104
105     fgStmtListThreaded = false;
106
107     // Initialize the logic for adding code. This is used to insert code such
108     // as the code that raises an exception when an array range check fails.
109
110     fgAddCodeList = nullptr;
111     fgAddCodeModf = false;
112
113     for (int i = 0; i < SCK_COUNT; i++)
114     {
115         fgExcptnTargetCache[i] = nullptr;
116     }
117
118     /* Keep track of the max count of pointer arguments */
119
120     fgPtrArgCntCur = 0;
121     fgPtrArgCntMax = 0;
122
123     /* This global flag is set whenever we remove a statement */
124     fgStmtRemoved = false;
125
126     /* This global flag is set whenever we add a throw block for a RngChk */
127     fgRngChkThrowAdded = false; /* reset flag for fgIsCodeAdded() */
128
129     fgIncrCount = 0;
130
131     /* We will record a list of all BBJ_RETURN blocks here */
132     fgReturnBlocks = nullptr;
133
134     /* This is set by fgComputeReachability */
135     fgEnterBlks = BlockSetOps::UninitVal();
136
137 #ifdef DEBUG
138     fgEnterBlksSetValid = false;
139 #endif // DEBUG
140
141 #if !FEATURE_EH_FUNCLETS
142     ehMaxHndNestingCount = 0;
143 #endif // !FEATURE_EH_FUNCLETS
144
145     /* Init the fgBigOffsetMorphingTemps to be BAD_VAR_NUM. */
146     for (int i = 0; i < TYP_COUNT; i++)
147     {
148         fgBigOffsetMorphingTemps[i] = BAD_VAR_NUM;
149     }
150
151     fgNoStructPromotion      = false;
152     fgNoStructParamPromotion = false;
153
154     optValnumCSE_phase = false; // referenced in fgMorphSmpOp()
155
156 #ifdef DEBUG
157     fgNormalizeEHDone = false;
158 #endif // DEBUG
159
160 #ifdef DEBUG
161     if (!compIsForInlining())
162     {
163         if ((JitConfig.JitNoStructPromotion() & 1) == 1)
164         {
165             fgNoStructPromotion = true;
166         }
167         if ((JitConfig.JitNoStructPromotion() & 2) == 2)
168         {
169             fgNoStructParamPromotion = true;
170         }
171     }
172 #endif // DEBUG
173
174     if (!compIsForInlining())
175     {
176         m_promotedStructDeathVars = nullptr;
177     }
178 #ifdef FEATURE_SIMD
179     fgPreviousCandidateSIMDFieldAsgStmt = nullptr;
180 #endif
181 }
182
183 bool Compiler::fgHaveProfileData()
184 {
185     if (compIsForInlining() || compIsForImportOnly())
186     {
187         return false;
188     }
189
190     return (fgProfileBuffer != nullptr);
191 }
192
193 bool Compiler::fgGetProfileWeightForBasicBlock(IL_OFFSET offset, unsigned* weightWB)
194 {
195     noway_assert(weightWB != nullptr);
196     unsigned weight = 0;
197
198 #ifdef DEBUG
199     unsigned hashSeed = fgStressBBProf();
200     if (hashSeed != 0)
201     {
202         unsigned hash = (info.compMethodHash() * hashSeed) ^ (offset * 1027);
203
204         // We need to especially stress the procedure splitting codepath.  Therefore
205         // one third the time we should return a weight of zero.
206         // Otherwise we should return some random weight (usually between 0 and 288).
207         // The below gives a weight of zero, 44% of the time
208
209         if (hash % 3 == 0)
210         {
211             weight = 0;
212         }
213         else if (hash % 11 == 0)
214         {
215             weight = (hash % 23) * (hash % 29) * (hash % 31);
216         }
217         else
218         {
219             weight = (hash % 17) * (hash % 19);
220         }
221
222         // The first block is never given a weight of zero
223         if ((offset == 0) && (weight == 0))
224         {
225             weight = 1 + (hash % 5);
226         }
227
228         *weightWB = weight;
229         return true;
230     }
231 #endif // DEBUG
232
233     if (fgHaveProfileData() == false)
234     {
235         return false;
236     }
237
238     noway_assert(!compIsForInlining());
239     for (unsigned i = 0; i < fgProfileBufferCount; i++)
240     {
241         if (fgProfileBuffer[i].ILOffset == offset)
242         {
243             weight = fgProfileBuffer[i].ExecutionCount;
244
245             *weightWB = weight;
246             return true;
247         }
248     }
249
250     *weightWB = 0;
251     return true;
252 }
253
254 void Compiler::fgInstrumentMethod()
255 {
256     noway_assert(!compIsForInlining());
257
258     // Count the number of basic blocks in the method
259
260     int         countOfBlocks = 0;
261     BasicBlock* block;
262     for (block = fgFirstBB; (block != nullptr); block = block->bbNext)
263     {
264         if (!(block->bbFlags & BBF_IMPORTED) || (block->bbFlags & BBF_INTERNAL))
265         {
266             continue;
267         }
268         countOfBlocks++;
269     }
270
271     // Allocate the profile buffer
272
273     ICorJitInfo::ProfileBuffer* bbProfileBufferStart;
274
275     HRESULT res = info.compCompHnd->allocBBProfileBuffer(countOfBlocks, &bbProfileBufferStart);
276
277     GenTree* stmt;
278
279     if (!SUCCEEDED(res))
280     {
281         // The E_NOTIMPL status is returned when we are profiling a generic method from a different assembly
282         if (res == E_NOTIMPL)
283         {
284             // In such cases we still want to add the method entry callback node
285
286             GenTreeArgList* args = gtNewArgList(gtNewIconEmbMethHndNode(info.compMethodHnd));
287             GenTree*        call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, args);
288
289             stmt = gtNewStmt(call);
290         }
291         else
292         {
293             noway_assert(!"Error:  failed to allocate bbProfileBuffer");
294             return;
295         }
296     }
297     else
298     {
299         // For each BasicBlock (non-Internal)
300         //  1. Assign the blocks bbCodeOffs to the ILOffset field of this blocks profile data.
301         //  2. Add an operation that increments the ExecutionCount field at the beginning of the block.
302
303         // Each (non-Internal) block has it own ProfileBuffer tuple [ILOffset, ExecutionCount]
304         // To start we initialize our current one with the first one that we allocated
305         //
306         ICorJitInfo::ProfileBuffer* bbCurrentBlockProfileBuffer = bbProfileBufferStart;
307
308         for (block = fgFirstBB; (block != nullptr); block = block->bbNext)
309         {
310             if (!(block->bbFlags & BBF_IMPORTED) || (block->bbFlags & BBF_INTERNAL))
311             {
312                 continue;
313             }
314
315             // Assign the current block's IL offset into the profile data
316             bbCurrentBlockProfileBuffer->ILOffset = block->bbCodeOffs;
317             assert(bbCurrentBlockProfileBuffer->ExecutionCount == 0); // This value should already be zero-ed out
318
319             size_t addrOfCurrentExecutionCount = (size_t)&bbCurrentBlockProfileBuffer->ExecutionCount;
320
321             // Read Basic-Block count value
322             GenTree* valueNode =
323                 gtNewIndOfIconHandleNode(TYP_INT, addrOfCurrentExecutionCount, GTF_ICON_BBC_PTR, false);
324
325             // Increment value by 1
326             GenTree* rhsNode = gtNewOperNode(GT_ADD, TYP_INT, valueNode, gtNewIconNode(1));
327
328             // Write new Basic-Block count value
329             GenTree* lhsNode = gtNewIndOfIconHandleNode(TYP_INT, addrOfCurrentExecutionCount, GTF_ICON_BBC_PTR, false);
330             GenTree* asgNode = gtNewAssignNode(lhsNode, rhsNode);
331
332             fgInsertStmtAtBeg(block, asgNode);
333
334             // Advance to the next ProfileBuffer tuple [ILOffset, ExecutionCount]
335             bbCurrentBlockProfileBuffer++;
336
337             // One less block
338             countOfBlocks--;
339         }
340         // Check that we allocated and initialized the same number of ProfileBuffer tuples
341         noway_assert(countOfBlocks == 0);
342
343         // Add the method entry callback node
344
345         GenTree* arg;
346
347 #ifdef FEATURE_READYTORUN_COMPILER
348         if (opts.IsReadyToRun())
349         {
350             mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd);
351
352             CORINFO_RESOLVED_TOKEN resolvedToken;
353             resolvedToken.tokenContext = MAKE_METHODCONTEXT(info.compMethodHnd);
354             resolvedToken.tokenScope   = info.compScopeHnd;
355             resolvedToken.token        = currentMethodToken;
356             resolvedToken.tokenType    = CORINFO_TOKENKIND_Method;
357
358             info.compCompHnd->resolveToken(&resolvedToken);
359
360             arg = impTokenToHandle(&resolvedToken);
361         }
362         else
363 #endif
364         {
365             arg = gtNewIconEmbMethHndNode(info.compMethodHnd);
366         }
367
368         GenTreeArgList* args = gtNewArgList(arg);
369         GenTree*        call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, args);
370
371         // Get the address of the first blocks ExecutionCount
372         size_t addrOfFirstExecutionCount = (size_t)&bbProfileBufferStart->ExecutionCount;
373
374         // Read Basic-Block count value
375         GenTree* valueNode = gtNewIndOfIconHandleNode(TYP_INT, addrOfFirstExecutionCount, GTF_ICON_BBC_PTR, false);
376
377         // Compare Basic-Block count value against zero
378         GenTree* relop = gtNewOperNode(GT_NE, TYP_INT, valueNode, gtNewIconNode(0, TYP_INT));
379         relop->gtFlags |= GTF_RELOP_QMARK; // TODO-Cleanup: [Simple]  Move this to gtNewQmarkNode
380         GenTree* colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), call);
381         GenTree* cond  = gtNewQmarkNode(TYP_VOID, relop, colon);
382         stmt           = gtNewStmt(cond);
383     }
384
385     fgEnsureFirstBBisScratch();
386
387     fgInsertStmtAtEnd(fgFirstBB, stmt);
388 }
389
390 /*****************************************************************************
391  *
392  *  Create a basic block and append it to the current BB list.
393  */
394
395 BasicBlock* Compiler::fgNewBasicBlock(BBjumpKinds jumpKind)
396 {
397     // This method must not be called after the exception table has been
398     // constructed, because it doesn't not provide support for patching
399     // the exception table.
400
401     noway_assert(compHndBBtabCount == 0);
402
403     BasicBlock* block;
404
405     /* Allocate the block descriptor */
406
407     block = bbNewBasicBlock(jumpKind);
408     noway_assert(block->bbJumpKind == jumpKind);
409
410     /* Append the block to the end of the global basic block list */
411
412     if (fgFirstBB)
413     {
414         fgLastBB->setNext(block);
415     }
416     else
417     {
418         fgFirstBB     = block;
419         block->bbPrev = nullptr;
420     }
421
422     fgLastBB = block;
423
424     return block;
425 }
426
427 /*****************************************************************************
428  *
429  *  Ensures that fgFirstBB is a scratch BasicBlock that we have added.
430  *  This can be used to add initialization code (without worrying
431  *  about other blocks jumping to it).
432  *
433  *  Callers have to be careful that they do not mess up the order of things
434  *  added to fgEnsureFirstBBisScratch in a way as to change semantics.
435  */
436
437 void Compiler::fgEnsureFirstBBisScratch()
438 {
439     // This method does not update predecessor lists and so must only be called before they are computed.
440     assert(!fgComputePredsDone);
441
442     // Have we already allocated a scratch block?
443
444     if (fgFirstBBisScratch())
445     {
446         return;
447     }
448
449     assert(fgFirstBBScratch == nullptr);
450
451     BasicBlock* block = bbNewBasicBlock(BBJ_NONE);
452
453     if (fgFirstBB != nullptr)
454     {
455         // If we have profile data the new block will inherit fgFirstBlock's weight
456         if (fgFirstBB->hasProfileWeight())
457         {
458             block->inheritWeight(fgFirstBB);
459         }
460
461         fgInsertBBbefore(fgFirstBB, block);
462     }
463     else
464     {
465         noway_assert(fgLastBB == nullptr);
466         fgFirstBB = block;
467         fgLastBB  = block;
468     }
469
470     noway_assert(fgLastBB != nullptr);
471
472     block->bbFlags |= (BBF_INTERNAL | BBF_IMPORTED);
473
474     fgFirstBBScratch = fgFirstBB;
475
476 #ifdef DEBUG
477     if (verbose)
478     {
479         printf("New scratch BB%02u\n", block->bbNum);
480     }
481 #endif
482 }
483
484 bool Compiler::fgFirstBBisScratch()
485 {
486     if (fgFirstBBScratch != nullptr)
487     {
488         assert(fgFirstBBScratch == fgFirstBB);
489         assert(fgFirstBBScratch->bbFlags & BBF_INTERNAL);
490         assert(fgFirstBBScratch->countOfInEdges() == 1);
491
492         // Normally, the first scratch block is a fall-through block. However, if the block after it was an empty
493         // BBJ_ALWAYS block, it might get removed, and the code that removes it will make the first scratch block
494         // a BBJ_ALWAYS block.
495         assert((fgFirstBBScratch->bbJumpKind == BBJ_NONE) || (fgFirstBBScratch->bbJumpKind == BBJ_ALWAYS));
496
497         return true;
498     }
499     else
500     {
501         return false;
502     }
503 }
504
505 bool Compiler::fgBBisScratch(BasicBlock* block)
506 {
507     return fgFirstBBisScratch() && (block == fgFirstBB);
508 }
509
510 #ifdef DEBUG
511 // Check to see if block contains a statement but don't spend more than a certain
512 // budget doing this per method compiled.
513 // If the budget is exceeded, return 'answerOnBoundExceeded' as the answer.
514 /* static */
515 bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, bool answerOnBoundExceeded /*= true*/)
516 {
517     const __int64 maxLinks = 1000000000;
518
519     assert(stmt->gtOper == GT_STMT);
520
521     __int64* numTraversed = &JitTls::GetCompiler()->compNumStatementLinksTraversed;
522
523     if (*numTraversed > maxLinks)
524     {
525         return answerOnBoundExceeded;
526     }
527
528     GenTree* curr = block->firstStmt();
529     do
530     {
531         (*numTraversed)++;
532         if (curr == stmt)
533         {
534             break;
535         }
536         curr = curr->gtNext;
537     } while (curr);
538     return curr != nullptr;
539 }
540 #endif // DEBUG
541
542 //------------------------------------------------------------------------
543 // fgInsertStmtAtBeg: Insert the given tree or statement at the start of the given basic block.
544 //
545 // Arguments:
546 //    block     - The block into which 'stmt' will be inserted.
547 //    stmt      - The statement to be inserted.
548 //
549 // Return Value:
550 //    Returns the new (potentially) GT_STMT node.
551 //
552 // Notes:
553 //    If 'stmt' is not already a statement, a new statement is created from it.
554 //    We always insert phi statements at the beginning.
555 //    In other cases, if there are any phi assignments and/or an assignment of
556 //    the GT_CATCH_ARG, we insert after those.
557
558 GenTree* Compiler::fgInsertStmtAtBeg(BasicBlock* block, GenTree* stmt)
559 {
560     if (stmt->gtOper != GT_STMT)
561     {
562         stmt = gtNewStmt(stmt);
563     }
564
565     GenTree* list = block->firstStmt();
566
567     if (!stmt->IsPhiDefnStmt())
568     {
569         GenTree* insertBeforeStmt = block->FirstNonPhiDefOrCatchArgAsg();
570         if (insertBeforeStmt != nullptr)
571         {
572             return fgInsertStmtBefore(block, insertBeforeStmt, stmt);
573         }
574         else if (list != nullptr)
575         {
576             return fgInsertStmtAtEnd(block, stmt);
577         }
578         // Otherwise, we will simply insert at the beginning, below.
579     }
580
581     /* The new tree will now be the first one of the block */
582
583     block->bbTreeList = stmt;
584     stmt->gtNext      = list;
585
586     /* Are there any statements in the block? */
587
588     if (list)
589     {
590         GenTree* last;
591
592         /* There is at least one statement already */
593
594         last = list->gtPrev;
595         noway_assert(last && last->gtNext == nullptr);
596
597         /* Insert the statement in front of the first one */
598
599         list->gtPrev = stmt;
600         stmt->gtPrev = last;
601     }
602     else
603     {
604         /* The block was completely empty */
605
606         stmt->gtPrev = stmt;
607     }
608
609     return stmt;
610 }
611
612 /*****************************************************************************
613  *
614  *  Insert the given tree or statement at the end of the given basic block.
615  *  Returns the (potentially) new GT_STMT node.
616  *  If the block can be a conditional block, use fgInsertStmtNearEnd.
617  */
618
619 GenTreeStmt* Compiler::fgInsertStmtAtEnd(BasicBlock* block, GenTree* node)
620 {
621     GenTree*     list = block->firstStmt();
622     GenTreeStmt* stmt;
623
624     if (node->gtOper != GT_STMT)
625     {
626         stmt = gtNewStmt(node);
627     }
628     else
629     {
630         stmt = node->AsStmt();
631     }
632
633     assert(stmt->gtNext == nullptr); // We don't set it, and it needs to be this after the insert
634
635     if (list)
636     {
637         GenTree* last;
638
639         /* There is at least one statement already */
640
641         last = list->gtPrev;
642         noway_assert(last && last->gtNext == nullptr);
643
644         /* Append the statement after the last one */
645
646         last->gtNext = stmt;
647         stmt->gtPrev = last;
648         list->gtPrev = stmt;
649     }
650     else
651     {
652         /* The block is completely empty */
653
654         block->bbTreeList = stmt;
655         stmt->gtPrev      = stmt;
656     }
657
658     return stmt;
659 }
660
661 /*****************************************************************************
662  *
663  *  Insert the given tree or statement at the end of the given basic block, but before
664  *  the GT_JTRUE, if present.
665  *  Returns the (potentially) new GT_STMT node.
666  */
667
668 GenTreeStmt* Compiler::fgInsertStmtNearEnd(BasicBlock* block, GenTree* node)
669 {
670     GenTreeStmt* stmt;
671
672     // This routine can only be used when in tree order.
673     assert(fgOrder == FGOrderTree);
674
675     if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN))
676     {
677         if (node->gtOper != GT_STMT)
678         {
679             stmt = gtNewStmt(node);
680         }
681         else
682         {
683             stmt = node->AsStmt();
684         }
685
686         GenTreeStmt* first = block->firstStmt();
687         noway_assert(first);
688         GenTreeStmt* last = block->lastStmt();
689         noway_assert(last && last->gtNext == nullptr);
690         GenTree* after = last->gtPrev;
691
692 #if DEBUG
693         if (block->bbJumpKind == BBJ_COND)
694         {
695             noway_assert(last->gtStmtExpr->gtOper == GT_JTRUE);
696         }
697         else if (block->bbJumpKind == BBJ_RETURN)
698         {
699             noway_assert((last->gtStmtExpr->gtOper == GT_RETURN) || (last->gtStmtExpr->gtOper == GT_JMP) ||
700                          // BBJ_RETURN blocks in functions returning void do not get a GT_RETURN node if they
701                          // have a .tail prefix (even if canTailCall returns false for these calls)
702                          // code:Compiler::impImportBlockCode (search for the RET: label)
703                          // Ditto for real tail calls (all code after them has been removed)
704                          ((last->gtStmtExpr->gtOper == GT_CALL) &&
705                           ((info.compRetType == TYP_VOID) || last->gtStmtExpr->AsCall()->IsTailCall())));
706         }
707         else
708         {
709             noway_assert(block->bbJumpKind == BBJ_SWITCH);
710             noway_assert(last->gtStmtExpr->gtOper == GT_SWITCH);
711         }
712 #endif // DEBUG
713
714         /* Append 'stmt' before 'last' */
715
716         stmt->gtNext = last;
717         last->gtPrev = stmt;
718
719         if (first == last)
720         {
721             /* There is only one stmt in the block */
722
723             block->bbTreeList = stmt;
724             stmt->gtPrev      = last;
725         }
726         else
727         {
728             noway_assert(after && (after->gtNext == last));
729
730             /* Append 'stmt' after 'after' */
731
732             after->gtNext = stmt;
733             stmt->gtPrev  = after;
734         }
735
736         return stmt;
737     }
738     else
739     {
740         return fgInsertStmtAtEnd(block, node);
741     }
742 }
743
744 /*****************************************************************************
745  *
746  *  Insert the given statement "stmt" after GT_STMT node "insertionPoint".
747  *  Returns the newly inserted GT_STMT node.
748  *  Note that the gtPrev list of statement nodes is circular, but the gtNext list is not.
749  */
750
751 GenTree* Compiler::fgInsertStmtAfter(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt)
752 {
753     assert(block->bbTreeList != nullptr);
754     noway_assert(insertionPoint->gtOper == GT_STMT);
755     noway_assert(stmt->gtOper == GT_STMT);
756     assert(fgBlockContainsStatementBounded(block, insertionPoint));
757     assert(!fgBlockContainsStatementBounded(block, stmt, false));
758
759     if (insertionPoint->gtNext == nullptr)
760     {
761         // Ok, we want to insert after the last statement of the block.
762         stmt->gtNext = nullptr;
763         stmt->gtPrev = insertionPoint;
764
765         insertionPoint->gtNext = stmt;
766
767         // Update the backward link of the first statement of the block
768         // to point to the new last statement.
769         assert(block->bbTreeList->gtPrev == insertionPoint);
770         block->bbTreeList->gtPrev = stmt;
771     }
772     else
773     {
774         stmt->gtNext = insertionPoint->gtNext;
775         stmt->gtPrev = insertionPoint;
776
777         insertionPoint->gtNext->gtPrev = stmt;
778         insertionPoint->gtNext         = stmt;
779     }
780
781     return stmt;
782 }
783
784 //  Insert the given tree or statement before GT_STMT node "insertionPoint".
785 //  Returns the newly inserted GT_STMT node.
786
787 GenTree* Compiler::fgInsertStmtBefore(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt)
788 {
789     assert(block->bbTreeList != nullptr);
790     noway_assert(insertionPoint->gtOper == GT_STMT);
791     noway_assert(stmt->gtOper == GT_STMT);
792     assert(fgBlockContainsStatementBounded(block, insertionPoint));
793     assert(!fgBlockContainsStatementBounded(block, stmt, false));
794
795     if (insertionPoint == block->bbTreeList)
796     {
797         // We're inserting before the first statement in the block.
798         GenTree* list = block->bbTreeList;
799         GenTree* last = list->gtPrev;
800
801         stmt->gtNext = list;
802         stmt->gtPrev = last;
803
804         block->bbTreeList = stmt;
805         list->gtPrev      = stmt;
806     }
807     else
808     {
809         stmt->gtNext = insertionPoint;
810         stmt->gtPrev = insertionPoint->gtPrev;
811
812         insertionPoint->gtPrev->gtNext = stmt;
813         insertionPoint->gtPrev         = stmt;
814     }
815
816     return stmt;
817 }
818
819 /*****************************************************************************
820  *
821  *  Insert the list of statements stmtList after the stmtAfter in block.
822  *  Return the last statement stmtList.
823  */
824
825 GenTree* Compiler::fgInsertStmtListAfter(BasicBlock* block,     // the block where stmtAfter is in.
826                                          GenTree*    stmtAfter, // the statement where stmtList should be inserted
827                                                                 // after.
828                                          GenTree* stmtList)
829 {
830     // Currently we can handle when stmtAfter and stmtList are non-NULL. This makes everything easy.
831     noway_assert(stmtAfter && stmtAfter->gtOper == GT_STMT);
832     noway_assert(stmtList && stmtList->gtOper == GT_STMT);
833
834     GenTree* stmtLast = stmtList->gtPrev; // Last statement in a non-empty list, circular in the gtPrev list.
835     noway_assert(stmtLast);
836     noway_assert(stmtLast->gtNext == nullptr);
837
838     GenTree* stmtNext = stmtAfter->gtNext;
839
840     if (!stmtNext)
841     {
842         stmtAfter->gtNext         = stmtList;
843         stmtList->gtPrev          = stmtAfter;
844         block->bbTreeList->gtPrev = stmtLast;
845         goto _Done;
846     }
847
848     stmtAfter->gtNext = stmtList;
849     stmtList->gtPrev  = stmtAfter;
850
851     stmtLast->gtNext = stmtNext;
852     stmtNext->gtPrev = stmtLast;
853
854 _Done:
855
856     noway_assert(block->bbTreeList == nullptr || block->bbTreeList->gtPrev->gtNext == nullptr);
857
858     return stmtLast;
859 }
860
861 /*
862     Removes a block from the return block list
863 */
864 void Compiler::fgRemoveReturnBlock(BasicBlock* block)
865 {
866     if (fgReturnBlocks == nullptr)
867     {
868         return;
869     }
870
871     if (fgReturnBlocks->block == block)
872     {
873         // It's the 1st entry, assign new head of list.
874         fgReturnBlocks = fgReturnBlocks->next;
875         return;
876     }
877
878     for (BasicBlockList* retBlocks = fgReturnBlocks; retBlocks->next != nullptr; retBlocks = retBlocks->next)
879     {
880         if (retBlocks->next->block == block)
881         {
882             // Found it; splice it out.
883             retBlocks->next = retBlocks->next->next;
884             return;
885         }
886     }
887 }
888
889 //------------------------------------------------------------------------
890 // fgGetPredForBlock: Find and return the predecessor edge corresponding to a given predecessor block.
891 //
892 // Arguments:
893 //    block -- The block with the predecessor list to operate on.
894 //    blockPred -- The predecessor block to find in the predecessor list.
895 //
896 // Return Value:
897 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
898 //    then returns nullptr.
899 //
900 // Assumptions:
901 //    -- This only works on the full predecessor lists, not the cheap preds lists.
902
903 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred)
904 {
905     assert(block);
906     assert(blockPred);
907     assert(!fgCheapPredsValid);
908
909     flowList* pred;
910
911     for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
912     {
913         if (blockPred == pred->flBlock)
914         {
915             return pred;
916         }
917     }
918
919     return nullptr;
920 }
921
922 //------------------------------------------------------------------------
923 // fgGetPredForBlock: Find and return the predecessor edge corresponding to a given predecessor block.
924 // Also returns the address of the pointer that points to this edge, to make it possible to remove this edge from the
925 // predecessor list without doing another linear search over the edge list.
926 //
927 // Arguments:
928 //    block -- The block with the predecessor list to operate on.
929 //    blockPred -- The predecessor block to find in the predecessor list.
930 //    ptrToPred -- Out parameter: set to the address of the pointer that points to the returned predecessor edge.
931 //
932 // Return Value:
933 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
934 //    then returns nullptr.
935 //
936 // Assumptions:
937 //    -- This only works on the full predecessor lists, not the cheap preds lists.
938
939 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, flowList*** ptrToPred)
940 {
941     assert(block);
942     assert(blockPred);
943     assert(ptrToPred);
944     assert(!fgCheapPredsValid);
945
946     flowList** predPrevAddr;
947     flowList*  pred;
948
949     for (predPrevAddr = &block->bbPreds, pred = *predPrevAddr; pred != nullptr;
950          predPrevAddr = &pred->flNext, pred = *predPrevAddr)
951     {
952         if (blockPred == pred->flBlock)
953         {
954             *ptrToPred = predPrevAddr;
955             return pred;
956         }
957     }
958
959     *ptrToPred = nullptr;
960     return nullptr;
961 }
962
963 //------------------------------------------------------------------------
964 // fgSpliceOutPred: Removes a predecessor edge for a block from the predecessor list.
965 //
966 // Arguments:
967 //    block -- The block with the predecessor list to operate on.
968 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
969 //
970 // Return Value:
971 //    The flowList edge that was removed.
972 //
973 // Assumptions:
974 //    -- "blockPred" must be a predecessor block of "block".
975 //    -- This simply splices out the flowList object. It doesn't update block ref counts, handle duplicate counts, etc.
976 //       For that, use fgRemoveRefPred() or fgRemoveAllRefPred().
977 //    -- This only works on the full predecessor lists, not the cheap preds lists.
978 //
979 // Notes:
980 //    -- This must walk the predecessor list to find the block in question. If the predecessor edge
981 //       is found using fgGetPredForBlock(), consider using the version that hands back the predecessor pointer
982 //       address instead, to avoid this search.
983 //    -- Marks fgModified = true, since the flow graph has changed.
984
985 flowList* Compiler::fgSpliceOutPred(BasicBlock* block, BasicBlock* blockPred)
986 {
987     assert(!fgCheapPredsValid);
988     noway_assert(block->bbPreds);
989
990     flowList* oldEdge = nullptr;
991
992     // Is this the first block in the pred list?
993     if (blockPred == block->bbPreds->flBlock)
994     {
995         oldEdge        = block->bbPreds;
996         block->bbPreds = block->bbPreds->flNext;
997     }
998     else
999     {
1000         flowList* pred;
1001         for (pred = block->bbPreds; (pred->flNext != nullptr) && (blockPred != pred->flNext->flBlock);
1002              pred = pred->flNext)
1003         {
1004             // empty
1005         }
1006         oldEdge = pred->flNext;
1007         if (oldEdge == nullptr)
1008         {
1009             noway_assert(!"Should always find the blockPred");
1010         }
1011         pred->flNext = pred->flNext->flNext;
1012     }
1013
1014     // Any changes to the flow graph invalidate the dominator sets.
1015     fgModified = true;
1016
1017     return oldEdge;
1018 }
1019
1020 //------------------------------------------------------------------------
1021 // fgAddRefPred: Increment block->bbRefs by one and add "blockPred" to the predecessor list of "block".
1022 //
1023 // Arguments:
1024 //    block -- A block to operate on.
1025 //    blockPred -- The predecessor block to add to the predecessor list.
1026 //    oldEdge -- Optional (default: nullptr). If non-nullptr, and a new edge is created (and the dup count
1027 //               of an existing edge is not just incremented), the edge weights are copied from this edge.
1028 //    initializingPreds -- Optional (default: false). Only set to "true" when the initial preds computation is
1029 //    happening.
1030 //
1031 // Return Value:
1032 //    The flow edge representing the predecessor.
1033 //
1034 // Assumptions:
1035 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1036 //
1037 // Notes:
1038 //    -- block->bbRefs is incremented by one to account for the reduction in incoming edges.
1039 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
1040 //       the preds themselves aren't touched.
1041 //    -- fgModified is set if a new flow edge is created (but not if an existing flow edge dup count is incremented),
1042 //       indicating that the flow graph shape has changed.
1043
1044 flowList* Compiler::fgAddRefPred(BasicBlock* block,
1045                                  BasicBlock* blockPred,
1046                                  flowList*   oldEdge /* = nullptr */,
1047                                  bool        initializingPreds /* = false */)
1048 {
1049     assert(block != nullptr);
1050     assert(blockPred != nullptr);
1051
1052     block->bbRefs++;
1053
1054     if (!fgComputePredsDone && !initializingPreds)
1055     {
1056         // Why is someone trying to update the preds list when the preds haven't been created?
1057         // Ignore them! This can happen when fgMorph is called before the preds list is created.
1058         return nullptr;
1059     }
1060
1061     assert(!fgCheapPredsValid);
1062
1063     flowList* flow;
1064
1065     // Keep the predecessor list in lowest to highest bbNum order. This allows us to discover the loops in
1066     // optFindNaturalLoops from innermost to outermost.
1067     //
1068     // TODO-Throughput: Inserting an edge for a block in sorted order requires searching every existing edge.
1069     // Thus, inserting all the edges for a block is quadratic in the number of edges. We need to either
1070     // not bother sorting for debuggable code, or sort in optFindNaturalLoops, or better, make the code in
1071     // optFindNaturalLoops not depend on order. This also requires ensuring that nobody else has taken a
1072     // dependency on this order. Note also that we don't allow duplicates in the list; we maintain a flDupCount
1073     // count of duplication. This also necessitates walking the flow list for every edge we add.
1074
1075     flowList** listp = &block->bbPreds;
1076     while ((*listp != nullptr) && ((*listp)->flBlock->bbNum < blockPred->bbNum))
1077     {
1078         listp = &(*listp)->flNext;
1079     }
1080
1081     if ((*listp != nullptr) && ((*listp)->flBlock == blockPred))
1082     {
1083         // The predecessor block already exists in the flow list; simply add to its duplicate count.
1084         flow = *listp;
1085         noway_assert(flow->flDupCount > 0);
1086         flow->flDupCount++;
1087     }
1088     else
1089     {
1090         flow = new (this, CMK_FlowList) flowList();
1091
1092 #if MEASURE_BLOCK_SIZE
1093         genFlowNodeCnt += 1;
1094         genFlowNodeSize += sizeof(flowList);
1095 #endif // MEASURE_BLOCK_SIZE
1096
1097         // Any changes to the flow graph invalidate the dominator sets.
1098         fgModified = true;
1099
1100         // Insert the new edge in the list in the correct ordered location.
1101         flow->flNext = *listp;
1102         *listp       = flow;
1103
1104         flow->flBlock    = blockPred;
1105         flow->flDupCount = 1;
1106
1107         if (fgHaveValidEdgeWeights)
1108         {
1109             // We are creating an edge from blockPred to block
1110             // and we have already computed the edge weights, so
1111             // we will try to setup this new edge with valid edge weights.
1112             //
1113             if (oldEdge != nullptr)
1114             {
1115                 // If our caller has given us the old edge weights
1116                 // then we will use them.
1117                 //
1118                 flow->flEdgeWeightMin = oldEdge->flEdgeWeightMin;
1119                 flow->flEdgeWeightMax = oldEdge->flEdgeWeightMax;
1120             }
1121             else
1122             {
1123                 // Set the max edge weight to be the minimum of block's or blockPred's weight
1124                 //
1125                 flow->flEdgeWeightMax = min(block->bbWeight, blockPred->bbWeight);
1126
1127                 // If we are inserting a conditional block the minimum weight is zero,
1128                 // otherwise it is the same as the edge's max weight.
1129                 if (blockPred->NumSucc() > 1)
1130                 {
1131                     flow->flEdgeWeightMin = BB_ZERO_WEIGHT;
1132                 }
1133                 else
1134                 {
1135                     flow->flEdgeWeightMin = flow->flEdgeWeightMax;
1136                 }
1137             }
1138         }
1139         else
1140         {
1141             flow->flEdgeWeightMin = BB_ZERO_WEIGHT;
1142             flow->flEdgeWeightMax = BB_MAX_WEIGHT;
1143         }
1144     }
1145     return flow;
1146 }
1147
1148 //------------------------------------------------------------------------
1149 // fgRemoveRefPred: Decrements the reference count of a predecessor edge from "blockPred" to "block",
1150 // removing the edge if it is no longer necessary.
1151 //
1152 // Arguments:
1153 //    block -- A block to operate on.
1154 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
1155 //
1156 // Return Value:
1157 //    If the flow edge was removed (the predecessor has a "dup count" of 1),
1158 //        returns the flow graph edge that was removed. This means "blockPred" is no longer a predecessor of "block".
1159 //    Otherwise, returns nullptr. This means that "blockPred" is still a predecessor of "block" (because "blockPred"
1160 //        is a switch with multiple cases jumping to "block", or a BBJ_COND with both conditional and fall-through
1161 //        paths leading to "block").
1162 //
1163 // Assumptions:
1164 //    -- "blockPred" must be a predecessor block of "block".
1165 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1166 //
1167 // Notes:
1168 //    -- block->bbRefs is decremented by one to account for the reduction in incoming edges.
1169 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
1170 //       the preds themselves aren't touched.
1171 //    -- fgModified is set if a flow edge is removed (but not if an existing flow edge dup count is decremented),
1172 //       indicating that the flow graph shape has changed.
1173
1174 flowList* Compiler::fgRemoveRefPred(BasicBlock* block, BasicBlock* blockPred)
1175 {
1176     noway_assert(block != nullptr);
1177     noway_assert(blockPred != nullptr);
1178
1179     noway_assert(block->countOfInEdges() > 0);
1180     block->bbRefs--;
1181
1182     // Do nothing if we haven't calculated the predecessor list yet.
1183     // Yes, this does happen.
1184     // For example the predecessor lists haven't been created yet when we do fgMorph.
1185     // But fgMorph calls fgFoldConditional, which in turn calls fgRemoveRefPred.
1186     if (!fgComputePredsDone)
1187     {
1188         return nullptr;
1189     }
1190
1191     assert(!fgCheapPredsValid);
1192
1193     flowList** ptrToPred;
1194     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
1195     noway_assert(pred);
1196     noway_assert(pred->flDupCount > 0);
1197
1198     pred->flDupCount--;
1199
1200     if (pred->flDupCount == 0)
1201     {
1202         // Splice out the predecessor edge since it's no longer necessary.
1203         *ptrToPred = pred->flNext;
1204
1205         // Any changes to the flow graph invalidate the dominator sets.
1206         fgModified = true;
1207
1208         return pred;
1209     }
1210     else
1211     {
1212         return nullptr;
1213     }
1214 }
1215
1216 //------------------------------------------------------------------------
1217 // fgRemoveAllRefPreds: Removes a predecessor edge from one block to another, no matter what the "dup count" is.
1218 //
1219 // Arguments:
1220 //    block -- A block to operate on.
1221 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
1222 //
1223 // Return Value:
1224 //    Returns the flow graph edge that was removed. The dup count on the edge is no longer valid.
1225 //
1226 // Assumptions:
1227 //    -- "blockPred" must be a predecessor block of "block".
1228 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1229 //
1230 // Notes:
1231 //    block->bbRefs is decremented to account for the reduction in incoming edges.
1232
1233 flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, BasicBlock* blockPred)
1234 {
1235     assert(block != nullptr);
1236     assert(blockPred != nullptr);
1237     assert(fgComputePredsDone);
1238     assert(!fgCheapPredsValid);
1239     assert(block->countOfInEdges() > 0);
1240
1241     flowList** ptrToPred;
1242     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
1243     assert(pred != nullptr);
1244     assert(pred->flDupCount > 0);
1245
1246     assert(block->bbRefs >= pred->flDupCount);
1247     block->bbRefs -= pred->flDupCount;
1248
1249     // Now splice out the predecessor edge.
1250     *ptrToPred = pred->flNext;
1251
1252     // Any changes to the flow graph invalidate the dominator sets.
1253     fgModified = true;
1254
1255     return pred;
1256 }
1257
1258 //------------------------------------------------------------------------
1259 // fgRemoveAllRefPreds: Remove a predecessor edge, given the address of a pointer to it in the
1260 // predecessor list, no matter what the "dup count" is.
1261 //
1262 // Arguments:
1263 //    block -- A block with the predecessor list to operate on.
1264 //    ptrToPred -- The address of a pointer to the predecessor to remove.
1265 //
1266 // Return Value:
1267 //    The removed predecessor edge. The dup count on the edge is no longer valid.
1268 //
1269 // Assumptions:
1270 //    -- The predecessor edge must be in the predecessor list for "block".
1271 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1272 //
1273 // Notes:
1274 //    block->bbRefs is decremented by the dup count of the predecessor edge, to account for the reduction in incoming
1275 //    edges.
1276
1277 flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, flowList** ptrToPred)
1278 {
1279     assert(block != nullptr);
1280     assert(ptrToPred != nullptr);
1281     assert(fgComputePredsDone);
1282     assert(!fgCheapPredsValid);
1283     assert(block->countOfInEdges() > 0);
1284
1285     flowList* pred = *ptrToPred;
1286     assert(pred != nullptr);
1287     assert(pred->flDupCount > 0);
1288
1289     assert(block->bbRefs >= pred->flDupCount);
1290     block->bbRefs -= pred->flDupCount;
1291
1292     // Now splice out the predecessor edge.
1293     *ptrToPred = pred->flNext;
1294
1295     // Any changes to the flow graph invalidate the dominator sets.
1296     fgModified = true;
1297
1298     return pred;
1299 }
1300
1301 /*
1302     Removes all the appearances of block as predecessor of others
1303 */
1304
1305 void Compiler::fgRemoveBlockAsPred(BasicBlock* block)
1306 {
1307     assert(!fgCheapPredsValid);
1308
1309     PREFIX_ASSUME(block != nullptr);
1310
1311     BasicBlock* bNext;
1312
1313     switch (block->bbJumpKind)
1314     {
1315         case BBJ_CALLFINALLY:
1316             if (!(block->bbFlags & BBF_RETLESS_CALL))
1317             {
1318                 assert(block->isBBCallAlwaysPair());
1319
1320                 /* The block after the BBJ_CALLFINALLY block is not reachable */
1321                 bNext = block->bbNext;
1322
1323                 /* bNext is an unreachable BBJ_ALWAYS block */
1324                 noway_assert(bNext->bbJumpKind == BBJ_ALWAYS);
1325
1326                 while (bNext->countOfInEdges() > 0)
1327                 {
1328                     fgRemoveRefPred(bNext, bNext->bbPreds->flBlock);
1329                 }
1330             }
1331
1332             __fallthrough;
1333
1334         case BBJ_COND:
1335         case BBJ_ALWAYS:
1336         case BBJ_EHCATCHRET:
1337
1338             /* Update the predecessor list for 'block->bbJumpDest' and 'block->bbNext' */
1339             fgRemoveRefPred(block->bbJumpDest, block);
1340
1341             if (block->bbJumpKind != BBJ_COND)
1342             {
1343                 break;
1344             }
1345
1346             /* If BBJ_COND fall through */
1347             __fallthrough;
1348
1349         case BBJ_NONE:
1350
1351             /* Update the predecessor list for 'block->bbNext' */
1352             fgRemoveRefPred(block->bbNext, block);
1353             break;
1354
1355         case BBJ_EHFILTERRET:
1356
1357             block->bbJumpDest->bbRefs++; // To compensate the bbRefs-- inside fgRemoveRefPred
1358             fgRemoveRefPred(block->bbJumpDest, block);
1359             break;
1360
1361         case BBJ_EHFINALLYRET:
1362         {
1363             /* Remove block as the predecessor of the bbNext of all
1364                BBJ_CALLFINALLY blocks calling this finally. No need
1365                to look for BBJ_CALLFINALLY for fault handlers. */
1366
1367             unsigned  hndIndex = block->getHndIndex();
1368             EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
1369
1370             if (ehDsc->HasFinallyHandler())
1371             {
1372                 BasicBlock* begBlk;
1373                 BasicBlock* endBlk;
1374                 ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
1375
1376                 BasicBlock* finBeg = ehDsc->ebdHndBeg;
1377
1378                 for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
1379                 {
1380                     if ((bcall->bbFlags & BBF_REMOVED) || bcall->bbJumpKind != BBJ_CALLFINALLY ||
1381                         bcall->bbJumpDest != finBeg)
1382                     {
1383                         continue;
1384                     }
1385
1386                     assert(bcall->isBBCallAlwaysPair());
1387                     fgRemoveRefPred(bcall->bbNext, block);
1388                 }
1389             }
1390         }
1391         break;
1392
1393         case BBJ_THROW:
1394         case BBJ_RETURN:
1395             break;
1396
1397         case BBJ_SWITCH:
1398         {
1399             unsigned     jumpCnt = block->bbJumpSwt->bbsCount;
1400             BasicBlock** jumpTab = block->bbJumpSwt->bbsDstTab;
1401
1402             do
1403             {
1404                 fgRemoveRefPred(*jumpTab, block);
1405             } while (++jumpTab, --jumpCnt);
1406
1407             break;
1408         }
1409
1410         default:
1411             noway_assert(!"Block doesn't have a valid bbJumpKind!!!!");
1412             break;
1413     }
1414 }
1415
1416 /*****************************************************************************
1417  * fgChangeSwitchBlock:
1418  *
1419  * We have a BBJ_SWITCH jump at 'oldSwitchBlock' and we want to move this
1420  * switch jump over to 'newSwitchBlock'.  All of the blocks that are jumped
1421  * to from jumpTab[] need to have their predecessor lists updated by removing
1422  * the 'oldSwitchBlock' and adding 'newSwitchBlock'.
1423  */
1424
1425 void Compiler::fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSwitchBlock)
1426 {
1427     noway_assert(oldSwitchBlock != nullptr);
1428     noway_assert(newSwitchBlock != nullptr);
1429     noway_assert(oldSwitchBlock->bbJumpKind == BBJ_SWITCH);
1430
1431     unsigned     jumpCnt = oldSwitchBlock->bbJumpSwt->bbsCount;
1432     BasicBlock** jumpTab = oldSwitchBlock->bbJumpSwt->bbsDstTab;
1433
1434     unsigned i;
1435
1436     // Walk the switch's jump table, updating the predecessor for each branch.
1437     for (i = 0; i < jumpCnt; i++)
1438     {
1439         BasicBlock* bJump = jumpTab[i];
1440         noway_assert(bJump != nullptr);
1441
1442         // Note that if there are duplicate branch targets in the switch jump table,
1443         // fgRemoveRefPred()/fgAddRefPred() will do the right thing: the second and
1444         // subsequent duplicates will simply subtract from and add to the duplicate
1445         // count (respectively).
1446
1447         //
1448         // Remove the old edge [oldSwitchBlock => bJump]
1449         //
1450         fgRemoveRefPred(bJump, oldSwitchBlock);
1451
1452         //
1453         // Create the new edge [newSwitchBlock => bJump]
1454         //
1455         fgAddRefPred(bJump, newSwitchBlock);
1456     }
1457
1458     if (m_switchDescMap != nullptr)
1459     {
1460         SwitchUniqueSuccSet uniqueSuccSet;
1461
1462         // If already computed and cached the unique descriptors for the old block, let's
1463         // update those for the new block.
1464         if (m_switchDescMap->Lookup(oldSwitchBlock, &uniqueSuccSet))
1465         {
1466             m_switchDescMap->Set(newSwitchBlock, uniqueSuccSet);
1467         }
1468         else
1469         {
1470             fgInvalidateSwitchDescMapEntry(newSwitchBlock);
1471         }
1472         fgInvalidateSwitchDescMapEntry(oldSwitchBlock);
1473     }
1474 }
1475
1476 /*****************************************************************************
1477  * fgReplaceSwitchJumpTarget:
1478  *
1479  * We have a BBJ_SWITCH at 'blockSwitch' and we want to replace all entries
1480  * in the jumpTab[] such that so that jumps that previously went to
1481  * 'oldTarget' now go to 'newTarget'.
1482  * We also must update the predecessor lists for 'oldTarget' and 'newPred'.
1483  */
1484
1485 void Compiler::fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* newTarget, BasicBlock* oldTarget)
1486 {
1487     noway_assert(blockSwitch != nullptr);
1488     noway_assert(newTarget != nullptr);
1489     noway_assert(oldTarget != nullptr);
1490     noway_assert(blockSwitch->bbJumpKind == BBJ_SWITCH);
1491
1492     // For the jump targets values that match oldTarget of our BBJ_SWITCH
1493     // replace predecessor 'blockSwitch' with 'newTarget'
1494     //
1495
1496     unsigned     jumpCnt = blockSwitch->bbJumpSwt->bbsCount;
1497     BasicBlock** jumpTab = blockSwitch->bbJumpSwt->bbsDstTab;
1498
1499     unsigned i = 0;
1500
1501     // Walk the switch's jump table looking for blocks to update the preds for
1502     while (i < jumpCnt)
1503     {
1504         if (jumpTab[i] == oldTarget) // We will update when jumpTab[i] matches
1505         {
1506             // Remove the old edge [oldTarget from blockSwitch]
1507             //
1508             fgRemoveAllRefPreds(oldTarget, blockSwitch);
1509
1510             //
1511             // Change the jumpTab entry to branch to the new location
1512             //
1513             jumpTab[i] = newTarget;
1514
1515             //
1516             // Create the new edge [newTarget from blockSwitch]
1517             //
1518             flowList* newEdge = fgAddRefPred(newTarget, blockSwitch);
1519
1520             // Now set the correct value of newEdge->flDupCount
1521             // and replace any other jumps in jumpTab[] that go to oldTarget.
1522             //
1523             i++;
1524             while (i < jumpCnt)
1525             {
1526                 if (jumpTab[i] == oldTarget)
1527                 {
1528                     //
1529                     // We also must update this entry in the jumpTab
1530                     //
1531                     jumpTab[i] = newTarget;
1532                     newTarget->bbRefs++;
1533
1534                     //
1535                     // Increment the flDupCount
1536                     //
1537                     newEdge->flDupCount++;
1538                 }
1539                 i++; // Check the next entry in jumpTab[]
1540             }
1541
1542             // Maintain, if necessary, the set of unique targets of "block."
1543             UpdateSwitchTableTarget(blockSwitch, oldTarget, newTarget);
1544
1545             // Make sure the new target has the proper bits set for being a branch target.
1546             newTarget->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
1547
1548             return; // We have replaced the jumps to oldTarget with newTarget
1549         }
1550         i++; // Check the next entry in jumpTab[] for a match
1551     }
1552     noway_assert(!"Did not find oldTarget in jumpTab[]");
1553 }
1554
1555 //------------------------------------------------------------------------
1556 // Compiler::fgReplaceJumpTarget: For a given block, replace the target 'oldTarget' with 'newTarget'.
1557 //
1558 // Arguments:
1559 //    block     - the block in which a jump target will be replaced.
1560 //    newTarget - the new branch target of the block.
1561 //    oldTarget - the old branch target of the block.
1562 //
1563 // Notes:
1564 // 1. Only branches are changed: BBJ_ALWAYS, the non-fallthrough path of BBJ_COND, BBJ_SWITCH, etc.
1565 //    We ignore other block types.
1566 // 2. Only the first target found is updated. If there are multiple ways for a block
1567 //    to reach 'oldTarget' (e.g., multiple arms of a switch), only the first one found is changed.
1568 // 3. The predecessor lists are not changed.
1569 // 4. The switch table "unique successor" cache is invalidated.
1570 //
1571 // This function is most useful early, before the full predecessor lists have been computed.
1572 //
1573 void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget)
1574 {
1575     assert(block != nullptr);
1576
1577     switch (block->bbJumpKind)
1578     {
1579         case BBJ_CALLFINALLY:
1580         case BBJ_COND:
1581         case BBJ_ALWAYS:
1582         case BBJ_EHCATCHRET:
1583         case BBJ_EHFILTERRET:
1584         case BBJ_LEAVE: // This function will be called before import, so we still have BBJ_LEAVE
1585
1586             if (block->bbJumpDest == oldTarget)
1587             {
1588                 block->bbJumpDest = newTarget;
1589             }
1590             break;
1591
1592         case BBJ_NONE:
1593         case BBJ_EHFINALLYRET:
1594         case BBJ_THROW:
1595         case BBJ_RETURN:
1596             break;
1597
1598         case BBJ_SWITCH:
1599             unsigned jumpCnt;
1600             jumpCnt = block->bbJumpSwt->bbsCount;
1601             BasicBlock** jumpTab;
1602             jumpTab = block->bbJumpSwt->bbsDstTab;
1603
1604             for (unsigned i = 0; i < jumpCnt; i++)
1605             {
1606                 if (jumpTab[i] == oldTarget)
1607                 {
1608                     jumpTab[i] = newTarget;
1609                     break;
1610                 }
1611             }
1612             break;
1613
1614         default:
1615             assert(!"Block doesn't have a valid bbJumpKind!!!!");
1616             unreached();
1617             break;
1618     }
1619 }
1620
1621 /*****************************************************************************
1622  * Updates the predecessor list for 'block' by replacing 'oldPred' with 'newPred'.
1623  * Note that a block can only appear once in the preds list (for normal preds, not
1624  * cheap preds): if a predecessor has multiple ways to get to this block, then
1625  * flDupCount will be >1, but the block will still appear exactly once. Thus, this
1626  * function assumes that all branches from the predecessor (practically, that all
1627  * switch cases that target this block) are changed to branch from the new predecessor,
1628  * with the same dup count.
1629  *
1630  * Note that the block bbRefs is not changed, since 'block' has the same number of
1631  * references as before, just from a different predecessor block.
1632  */
1633
1634 void Compiler::fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* newPred)
1635 {
1636     noway_assert(block != nullptr);
1637     noway_assert(oldPred != nullptr);
1638     noway_assert(newPred != nullptr);
1639     assert(!fgCheapPredsValid);
1640
1641     flowList* pred;
1642
1643     for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
1644     {
1645         if (oldPred == pred->flBlock)
1646         {
1647             pred->flBlock = newPred;
1648             break;
1649         }
1650     }
1651 }
1652
1653 /*****************************************************************************
1654  *
1655  *  Returns true if block b1 dominates block b2.
1656  */
1657
1658 bool Compiler::fgDominate(BasicBlock* b1, BasicBlock* b2)
1659 {
1660     noway_assert(fgDomsComputed);
1661     assert(!fgCheapPredsValid);
1662
1663     //
1664     // If the fgModified flag is false then we made some modifications to
1665     // the flow graph, like adding a new block or changing a conditional branch
1666     // into an unconditional branch.
1667     //
1668     // We can continue to use the dominator and reachable information to
1669     // unmark loops as long as we haven't renumbered the blocks or we aren't
1670     // asking for information about a new block
1671     //
1672
1673     if (b2->bbNum > fgDomBBcount)
1674     {
1675         if (b1 == b2)
1676         {
1677             return true;
1678         }
1679
1680         for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext)
1681         {
1682             if (!fgDominate(b1, pred->flBlock))
1683             {
1684                 return false;
1685             }
1686         }
1687
1688         return b2->bbPreds != nullptr;
1689     }
1690
1691     if (b1->bbNum > fgDomBBcount)
1692     {
1693         // if b1 is a loop preheader and Succ is its only successor, then all predecessors of
1694         // Succ either are b1 itself or are dominated by Succ. Under these conditions, b1
1695         // dominates b2 if and only if Succ dominates b2 (or if b2 == b1, but we already tested
1696         // for this case)
1697         if (b1->bbFlags & BBF_LOOP_PREHEADER)
1698         {
1699             noway_assert(b1->bbFlags & BBF_INTERNAL);
1700             noway_assert(b1->bbJumpKind == BBJ_NONE);
1701             return fgDominate(b1->bbNext, b2);
1702         }
1703
1704         // unknown dominators; err on the safe side and return false
1705         return false;
1706     }
1707
1708     /* Check if b1 dominates b2 */
1709     unsigned numA = b1->bbNum;
1710     noway_assert(numA <= fgDomBBcount);
1711     unsigned numB = b2->bbNum;
1712     noway_assert(numB <= fgDomBBcount);
1713
1714     // 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)
1715     // in the dominator tree. Turns out that can be translated as:
1716     //
1717     //   A dom B <-> preorder(A) <= preorder(B) && postorder(A) >= postorder(B)
1718     //
1719     // where the equality holds when you ask if A dominates itself.
1720     bool treeDom =
1721         fgDomTreePreOrder[numA] <= fgDomTreePreOrder[numB] && fgDomTreePostOrder[numA] >= fgDomTreePostOrder[numB];
1722
1723     return treeDom;
1724 }
1725
1726 /*****************************************************************************
1727  *
1728  *  Returns true if block b1 can reach block b2.
1729  */
1730
1731 bool Compiler::fgReachable(BasicBlock* b1, BasicBlock* b2)
1732 {
1733     noway_assert(fgDomsComputed);
1734     assert(!fgCheapPredsValid);
1735
1736     //
1737     // If the fgModified flag is false then we made some modifications to
1738     // the flow graph, like adding a new block or changing a conditional branch
1739     // into an unconditional branch.
1740     //
1741     // We can continue to use the dominator and reachable information to
1742     // unmark loops as long as we haven't renumbered the blocks or we aren't
1743     // asking for information about a new block
1744     //
1745
1746     if (b2->bbNum > fgDomBBcount)
1747     {
1748         if (b1 == b2)
1749         {
1750             return true;
1751         }
1752
1753         for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext)
1754         {
1755             if (fgReachable(b1, pred->flBlock))
1756             {
1757                 return true;
1758             }
1759         }
1760
1761         return false;
1762     }
1763
1764     if (b1->bbNum > fgDomBBcount)
1765     {
1766         noway_assert(b1->bbJumpKind == BBJ_NONE || b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND);
1767
1768         if (b1->bbFallsThrough() && fgReachable(b1->bbNext, b2))
1769         {
1770             return true;
1771         }
1772
1773         if (b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND)
1774         {
1775             return fgReachable(b1->bbJumpDest, b2);
1776         }
1777
1778         return false;
1779     }
1780
1781     /* Check if b1 can reach b2 */
1782     assert(fgReachabilitySetsValid);
1783     assert(BasicBlockBitSetTraits::GetSize(this) == fgDomBBcount + 1);
1784     return BlockSetOps::IsMember(this, b2->bbReach, b1->bbNum);
1785 }
1786
1787 /*****************************************************************************
1788  *  Update changed flow graph information.
1789  *
1790  *  If the flow graph has changed, we need to recompute various information if we want to use
1791  *  it again.
1792  */
1793
1794 void Compiler::fgUpdateChangedFlowGraph()
1795 {
1796     // We need to clear this so we don't hit an assert calling fgRenumberBlocks().
1797     fgDomsComputed = false;
1798
1799     JITDUMP("\nRenumbering the basic blocks for fgUpdateChangeFlowGraph\n");
1800     fgRenumberBlocks();
1801
1802     fgComputePreds();
1803     fgComputeEnterBlocksSet();
1804     fgComputeReachabilitySets();
1805     fgComputeDoms();
1806 }
1807
1808 /*****************************************************************************
1809  *  Compute the bbReach sets.
1810  *
1811  *  This can be called to recompute the bbReach sets after the flow graph changes, such as when the
1812  *  number of BasicBlocks change (and thus, the BlockSet epoch changes).
1813  *
1814  *  Finally, this also sets the BBF_GC_SAFE_POINT flag on blocks.
1815  *
1816  *  Assumes the predecessor lists are correct.
1817  *
1818  *  TODO-Throughput: This algorithm consumes O(n^2) because we're using dense bitsets to
1819  *  represent reachability. While this yields O(1) time queries, it bloats the memory usage
1820  *  for large code.  We can do better if we try to approach reachability by
1821  *  computing the strongly connected components of the flow graph.  That way we only need
1822  *  linear memory to label every block with its SCC.
1823  */
1824
1825 void Compiler::fgComputeReachabilitySets()
1826 {
1827     assert(fgComputePredsDone);
1828     assert(!fgCheapPredsValid);
1829
1830 #ifdef DEBUG
1831     fgReachabilitySetsValid = false;
1832 #endif // DEBUG
1833
1834     BasicBlock* block;
1835
1836     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1837     {
1838         // Initialize the per-block bbReach sets. It creates a new empty set,
1839         // because the block epoch could change since the previous initialization
1840         // and the old set could have wrong size.
1841         block->bbReach = BlockSetOps::MakeEmpty(this);
1842
1843         /* Mark block as reaching itself */
1844         BlockSetOps::AddElemD(this, block->bbReach, block->bbNum);
1845     }
1846
1847     /* Find the reachable blocks */
1848     // Also, set BBF_GC_SAFE_POINT.
1849
1850     bool     change;
1851     BlockSet newReach(BlockSetOps::MakeEmpty(this));
1852     do
1853     {
1854         change = false;
1855
1856         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1857         {
1858             BlockSetOps::Assign(this, newReach, block->bbReach);
1859
1860             bool predGcSafe = (block->bbPreds != nullptr); // Do all of our predecessor blocks have a GC safe bit?
1861
1862             for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
1863             {
1864                 BasicBlock* predBlock = pred->flBlock;
1865
1866                 /* Union the predecessor's reachability set into newReach */
1867                 BlockSetOps::UnionD(this, newReach, predBlock->bbReach);
1868
1869                 if (!(predBlock->bbFlags & BBF_GC_SAFE_POINT))
1870                 {
1871                     predGcSafe = false;
1872                 }
1873             }
1874
1875             if (predGcSafe)
1876             {
1877                 block->bbFlags |= BBF_GC_SAFE_POINT;
1878             }
1879
1880             if (!BlockSetOps::Equal(this, newReach, block->bbReach))
1881             {
1882                 BlockSetOps::Assign(this, block->bbReach, newReach);
1883                 change = true;
1884             }
1885         }
1886     } while (change);
1887
1888 #ifdef DEBUG
1889     if (verbose)
1890     {
1891         printf("\nAfter computing reachability sets:\n");
1892         fgDispReach();
1893     }
1894
1895     fgReachabilitySetsValid = true;
1896 #endif // DEBUG
1897 }
1898
1899 /*****************************************************************************
1900  *  Compute the entry blocks set.
1901  *
1902  *  Initialize fgEnterBlks to the set of blocks for which we don't have explicit control
1903  *  flow edges. These are the entry basic block and each of the EH handler blocks.
1904  *  For ARM, also include the BBJ_ALWAYS block of a BBJ_CALLFINALLY/BBJ_ALWAYS pair,
1905  *  to avoid creating "retless" calls, since we need the BBJ_ALWAYS for the purpose
1906  *  of unwinding, even if the call doesn't return (due to an explicit throw, for example).
1907  */
1908
1909 void Compiler::fgComputeEnterBlocksSet()
1910 {
1911 #ifdef DEBUG
1912     fgEnterBlksSetValid = false;
1913 #endif // DEBUG
1914
1915     fgEnterBlks = BlockSetOps::MakeEmpty(this);
1916
1917     /* Now set the entry basic block */
1918     BlockSetOps::AddElemD(this, fgEnterBlks, fgFirstBB->bbNum);
1919     assert(fgFirstBB->bbNum == 1);
1920
1921     if (compHndBBtabCount > 0)
1922     {
1923         /* Also 'or' in the handler basic blocks */
1924         EHblkDsc* HBtab;
1925         EHblkDsc* HBtabEnd;
1926         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
1927         {
1928             if (HBtab->HasFilter())
1929             {
1930                 BlockSetOps::AddElemD(this, fgEnterBlks, HBtab->ebdFilter->bbNum);
1931             }
1932             BlockSetOps::AddElemD(this, fgEnterBlks, HBtab->ebdHndBeg->bbNum);
1933         }
1934     }
1935
1936 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1937     // TODO-ARM-Cleanup: The ARM code here to prevent creating retless calls by adding the BBJ_ALWAYS
1938     // to the enter blocks is a bit of a compromise, because sometimes the blocks are already reachable,
1939     // and it messes up DFS ordering to have them marked as enter block. We should prevent the
1940     // creation of retless calls some other way.
1941     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
1942     {
1943         if (block->bbJumpKind == BBJ_CALLFINALLY)
1944         {
1945             assert(block->isBBCallAlwaysPair());
1946
1947             // Don't remove the BBJ_ALWAYS block that is only here for the unwinder. It might be dead
1948             // if the finally is no-return, so mark it as an entry point.
1949             BlockSetOps::AddElemD(this, fgEnterBlks, block->bbNext->bbNum);
1950         }
1951     }
1952 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1953
1954 #ifdef DEBUG
1955     if (verbose)
1956     {
1957         printf("Enter blocks: ");
1958         BlockSetOps::Iter iter(this, fgEnterBlks);
1959         unsigned          bbNum = 0;
1960         while (iter.NextElem(&bbNum))
1961         {
1962             printf("BB%02u ", bbNum);
1963         }
1964         printf("\n");
1965     }
1966 #endif // DEBUG
1967
1968 #ifdef DEBUG
1969     fgEnterBlksSetValid = true;
1970 #endif // DEBUG
1971 }
1972
1973 /*****************************************************************************
1974  *  Remove unreachable blocks.
1975  *
1976  *  Return true if any unreachable blocks were removed.
1977  */
1978
1979 bool Compiler::fgRemoveUnreachableBlocks()
1980 {
1981     assert(!fgCheapPredsValid);
1982     assert(fgReachabilitySetsValid);
1983
1984     bool        hasLoops             = false;
1985     bool        hasUnreachableBlocks = false;
1986     BasicBlock* block;
1987
1988     /* Record unreachable blocks */
1989     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1990     {
1991         /* Internal throw blocks are also reachable */
1992         if (fgIsThrowHlpBlk(block))
1993         {
1994             goto SKIP_BLOCK;
1995         }
1996         else if (block == genReturnBB)
1997         {
1998             // Don't remove statements for the genReturnBB block, as we might have special hookups there.
1999             // For example, <BUGNUM> in VSW 364383, </BUGNUM>
2000             // the profiler hookup needs to have the "void GT_RETURN" statement
2001             // to properly set the info.compProfilerCallback flag.
2002             goto SKIP_BLOCK;
2003         }
2004         else
2005         {
2006             // If any of the entry blocks can reach this block, then we skip it.
2007             if (!BlockSetOps::IsEmptyIntersection(this, fgEnterBlks, block->bbReach))
2008             {
2009                 goto SKIP_BLOCK;
2010             }
2011         }
2012
2013         // Remove all the code for the block
2014         fgUnreachableBlock(block);
2015
2016         // Make sure that the block was marked as removed */
2017         noway_assert(block->bbFlags & BBF_REMOVED);
2018
2019         // Some blocks mark the end of trys and catches
2020         // and can't be removed. We convert these into
2021         // empty blocks of type BBJ_THROW
2022
2023         if (block->bbFlags & BBF_DONT_REMOVE)
2024         {
2025             bool bIsBBCallAlwaysPair = block->isBBCallAlwaysPair();
2026
2027             /* Unmark the block as removed, */
2028             /* clear BBF_INTERNAL as well and set BBJ_IMPORTED */
2029
2030             block->bbFlags &= ~(BBF_REMOVED | BBF_INTERNAL | BBF_NEEDS_GCPOLL);
2031             block->bbFlags |= BBF_IMPORTED;
2032             block->bbJumpKind = BBJ_THROW;
2033             block->bbSetRunRarely();
2034
2035 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2036             // If this is a <BBJ_CALLFINALLY, BBJ_ALWAYS> pair, we have to clear BBF_FINALLY_TARGET flag on
2037             // the target node (of BBJ_ALWAYS) since BBJ_CALLFINALLY node is getting converted to a BBJ_THROW.
2038             if (bIsBBCallAlwaysPair)
2039             {
2040                 noway_assert(block->bbNext->bbJumpKind == BBJ_ALWAYS);
2041                 fgClearFinallyTargetBit(block->bbNext->bbJumpDest);
2042             }
2043 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2044         }
2045         else
2046         {
2047             /* We have to call fgRemoveBlock next */
2048             hasUnreachableBlocks = true;
2049         }
2050         continue;
2051
2052     SKIP_BLOCK:;
2053
2054         // if (block->isRunRarely())
2055         //    continue;
2056         if (block->bbJumpKind == BBJ_RETURN)
2057         {
2058             continue;
2059         }
2060
2061         /* Set BBF_LOOP_HEAD if we have backwards branches to this block */
2062
2063         unsigned blockNum = block->bbNum;
2064         for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
2065         {
2066             BasicBlock* predBlock = pred->flBlock;
2067             if (blockNum <= predBlock->bbNum)
2068             {
2069                 if (predBlock->bbJumpKind == BBJ_CALLFINALLY)
2070                 {
2071                     continue;
2072                 }
2073
2074                 /* If block can reach predBlock then we have a loop head */
2075                 if (BlockSetOps::IsMember(this, predBlock->bbReach, blockNum))
2076                 {
2077                     hasLoops = true;
2078
2079                     /* Set the BBF_LOOP_HEAD flag */
2080                     block->bbFlags |= BBF_LOOP_HEAD;
2081                     break;
2082                 }
2083             }
2084         }
2085     }
2086
2087     fgHasLoops = hasLoops;
2088
2089     if (hasUnreachableBlocks)
2090     {
2091         // Now remove the unreachable blocks
2092         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2093         {
2094             //  If we mark the block with BBF_REMOVED then
2095             //  we need to call fgRemovedBlock() on it
2096
2097             if (block->bbFlags & BBF_REMOVED)
2098             {
2099                 fgRemoveBlock(block, true);
2100
2101                 // When we have a BBJ_CALLFINALLY, BBJ_ALWAYS pair; fgRemoveBlock will remove
2102                 // both blocks, so we must advance 1 extra place in the block list
2103                 //
2104                 if (block->isBBCallAlwaysPair())
2105                 {
2106                     block = block->bbNext;
2107                 }
2108             }
2109         }
2110     }
2111
2112     return hasUnreachableBlocks;
2113 }
2114
2115 /*****************************************************************************
2116  *
2117  *  Function called to compute the dominator and reachable sets.
2118  *
2119  *  Assumes the predecessor lists are computed and correct.
2120  */
2121
2122 void Compiler::fgComputeReachability()
2123 {
2124 #ifdef DEBUG
2125     if (verbose)
2126     {
2127         printf("*************** In fgComputeReachability\n");
2128     }
2129
2130     fgVerifyHandlerTab();
2131
2132     // Make sure that the predecessor lists are accurate
2133     assert(fgComputePredsDone);
2134     fgDebugCheckBBlist();
2135 #endif // DEBUG
2136
2137     /* Create a list of all BBJ_RETURN blocks. The head of the list is 'fgReturnBlocks'. */
2138     fgReturnBlocks = nullptr;
2139
2140     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2141     {
2142         // If this is a BBJ_RETURN block, add it to our list of all BBJ_RETURN blocks. This list is only
2143         // used to find return blocks.
2144         if (block->bbJumpKind == BBJ_RETURN)
2145         {
2146             fgReturnBlocks = new (this, CMK_Reachability) BasicBlockList(block, fgReturnBlocks);
2147         }
2148     }
2149
2150     // Compute reachability and then delete blocks determined to be unreachable. If we delete blocks, we
2151     // need to loop, as that might have caused more blocks to become unreachable. This can happen in the
2152     // case where a call to a finally is unreachable and deleted (maybe the call to the finally is
2153     // preceded by a throw or an infinite loop), making the blocks following the finally unreachable.
2154     // However, all EH entry blocks are considered global entry blocks, causing the blocks following the
2155     // call to the finally to stay rooted, until a second round of reachability is done.
2156     // The dominator algorithm expects that all blocks can be reached from the fgEnterBlks set.
2157     unsigned passNum = 1;
2158     bool     changed;
2159     do
2160     {
2161         // Just to be paranoid, avoid infinite loops; fall back to minopts.
2162         if (passNum > 10)
2163         {
2164             noway_assert(!"Too many unreachable block removal loops");
2165         }
2166
2167         /* Walk the flow graph, reassign block numbers to keep them in ascending order */
2168         JITDUMP("\nRenumbering the basic blocks for fgComputeReachability pass #%u\n", passNum);
2169         passNum++;
2170         fgRenumberBlocks();
2171
2172         //
2173         // Compute fgEnterBlks
2174         //
2175
2176         fgComputeEnterBlocksSet();
2177
2178         //
2179         // Compute bbReach
2180         //
2181
2182         fgComputeReachabilitySets();
2183
2184         //
2185         // Use reachability information to delete unreachable blocks.
2186         // Also, determine if the flow graph has loops and set 'fgHasLoops' accordingly.
2187         // Set the BBF_LOOP_HEAD flag on the block target of backwards branches.
2188         //
2189
2190         changed = fgRemoveUnreachableBlocks();
2191
2192     } while (changed);
2193
2194 #ifdef DEBUG
2195     if (verbose)
2196     {
2197         printf("\nAfter computing reachability:\n");
2198         fgDispBasicBlocks(verboseTrees);
2199         printf("\n");
2200     }
2201
2202     fgVerifyHandlerTab();
2203     fgDebugCheckBBlist(true);
2204 #endif // DEBUG
2205
2206     //
2207     // Now, compute the dominators
2208     //
2209
2210     fgComputeDoms();
2211 }
2212
2213 /** In order to be able to compute dominance, we need to first get a DFS reverse post order sort on the basic flow graph
2214   * for the dominance algorithm to operate correctly.  The reason why we need the DFS sort is because
2215   * we will build the dominance sets using the partial order induced by the DFS sorting.  With this
2216   * precondition not holding true, the algorithm doesn't work properly.
2217   */
2218 void Compiler::fgDfsInvPostOrder()
2219 {
2220     // NOTE: This algorithm only pays attention to the actual blocks. It ignores the imaginary entry block.
2221
2222     // visited   :  Once we run the DFS post order sort recursive algorithm, we mark the nodes we visited to avoid
2223     //              backtracking.
2224     BlockSet visited(BlockSetOps::MakeEmpty(this));
2225
2226     // We begin by figuring out which basic blocks don't have incoming edges and mark them as
2227     // start nodes.  Later on we run the recursive algorithm for each node that we
2228     // mark in this step.
2229     BlockSet_ValRet_T startNodes = fgDomFindStartNodes();
2230
2231     // Make sure fgEnterBlks are still there in startNodes, even if they participate in a loop (i.e., there is
2232     // an incoming edge into the block).
2233     assert(fgEnterBlksSetValid);
2234
2235 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2236     //
2237     //    BlockSetOps::UnionD(this, startNodes, fgEnterBlks);
2238     //
2239     // This causes problems on ARM, because we for BBJ_CALLFINALLY/BBJ_ALWAYS pairs, we add the BBJ_ALWAYS
2240     // to the enter blocks set to prevent flow graph optimizations from removing it and creating retless call finallies
2241     // (BBF_RETLESS_CALL). This leads to an incorrect DFS ordering in some cases, because we start the recursive walk
2242     // from the BBJ_ALWAYS, which is reachable from other blocks. A better solution would be to change ARM to avoid
2243     // creating retless calls in a different way, not by adding BBJ_ALWAYS to fgEnterBlks.
2244     //
2245     // So, let us make sure at least fgFirstBB is still there, even if it participates in a loop.
2246     BlockSetOps::AddElemD(this, startNodes, 1);
2247     assert(fgFirstBB->bbNum == 1);
2248 #else
2249     BlockSetOps::UnionD(this, startNodes, fgEnterBlks);
2250 #endif
2251
2252     assert(BlockSetOps::IsMember(this, startNodes, fgFirstBB->bbNum));
2253
2254     // Call the flowgraph DFS traversal helper.
2255     unsigned postIndex = 1;
2256     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2257     {
2258         // If the block has no predecessors, and we haven't already visited it (because it's in fgEnterBlks but also
2259         // reachable from the first block), go ahead and traverse starting from this block.
2260         if (BlockSetOps::IsMember(this, startNodes, block->bbNum) &&
2261             !BlockSetOps::IsMember(this, visited, block->bbNum))
2262         {
2263             fgDfsInvPostOrderHelper(block, visited, &postIndex);
2264         }
2265     }
2266
2267     // After the DFS reverse postorder is completed, we must have visited all the basic blocks.
2268     noway_assert(postIndex == fgBBcount + 1);
2269     noway_assert(fgBBNumMax == fgBBcount);
2270
2271 #ifdef DEBUG
2272     if (0 && verbose)
2273     {
2274         printf("\nAfter doing a post order traversal of the BB graph, this is the ordering:\n");
2275         for (unsigned i = 1; i <= fgBBNumMax; ++i)
2276         {
2277             printf("%02u -> BB%02u\n", i, fgBBInvPostOrder[i]->bbNum);
2278         }
2279         printf("\n");
2280     }
2281 #endif // DEBUG
2282 }
2283
2284 BlockSet_ValRet_T Compiler::fgDomFindStartNodes()
2285 {
2286     unsigned    j;
2287     BasicBlock* block;
2288
2289     // startNodes ::  A set that represents which basic blocks in the flow graph don't have incoming edges.
2290     // We begin assuming everything is a start block and remove any block that is being referenced by another in its
2291     // successor list.
2292
2293     BlockSet startNodes(BlockSetOps::MakeFull(this));
2294
2295     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2296     {
2297         unsigned cSucc = block->NumSucc(this);
2298         for (j = 0; j < cSucc; ++j)
2299         {
2300             BasicBlock* succ = block->GetSucc(j, this);
2301             BlockSetOps::RemoveElemD(this, startNodes, succ->bbNum);
2302         }
2303     }
2304
2305 #ifdef DEBUG
2306     if (verbose)
2307     {
2308         printf("\nDominator computation start blocks (those blocks with no incoming edges):\n");
2309         BlockSetOps::Iter iter(this, startNodes);
2310         unsigned          bbNum = 0;
2311         while (iter.NextElem(&bbNum))
2312         {
2313             printf("BB%02u ", bbNum);
2314         }
2315         printf("\n");
2316     }
2317 #endif // DEBUG
2318
2319     return startNodes;
2320 }
2321
2322 //------------------------------------------------------------------------
2323 // fgDfsInvPostOrderHelper: Helper to assign post-order numbers to blocks.
2324 //
2325 // Arguments:
2326 //    block   - The starting entry block
2327 //    visited - The set of visited blocks
2328 //    count   - Pointer to the Dfs counter
2329 //
2330 // Notes:
2331 //    Compute a non-recursive DFS traversal of the flow graph using an
2332 //    evaluation stack to assign post-order numbers.
2333
2334 void Compiler::fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, unsigned* count)
2335 {
2336     // Assume we haven't visited this node yet (callers ensure this).
2337     assert(!BlockSetOps::IsMember(this, visited, block->bbNum));
2338
2339     // Allocate a local stack to hold the DFS traversal actions necessary
2340     // to compute pre/post-ordering of the control flowgraph.
2341     ArrayStack<DfsBlockEntry> stack(this);
2342
2343     // Push the first block on the stack to seed the traversal.
2344     stack.Push(DfsBlockEntry(DSS_Pre, block));
2345     // Flag the node we just visited to avoid backtracking.
2346     BlockSetOps::AddElemD(this, visited, block->bbNum);
2347
2348     // The search is terminated once all the actions have been processed.
2349     while (stack.Height() != 0)
2350     {
2351         DfsBlockEntry current      = stack.Pop();
2352         BasicBlock*   currentBlock = current.dfsBlock;
2353
2354         if (current.dfsStackState == DSS_Pre)
2355         {
2356             // This is a pre-visit that corresponds to the first time the
2357             // node is encountered in the spanning tree and receives pre-order
2358             // numberings. By pushing the post-action on the stack here we
2359             // are guaranteed to only process it after all of its successors
2360             // pre and post actions are processed.
2361             stack.Push(DfsBlockEntry(DSS_Post, currentBlock));
2362
2363             unsigned cSucc = currentBlock->NumSucc(this);
2364             for (unsigned j = 0; j < cSucc; ++j)
2365             {
2366                 BasicBlock* succ = currentBlock->GetSucc(j, this);
2367
2368                 // If this is a node we haven't seen before, go ahead and process
2369                 if (!BlockSetOps::IsMember(this, visited, succ->bbNum))
2370                 {
2371                     // Push a pre-visit action for this successor onto the stack and
2372                     // mark it as visited in case this block has multiple successors
2373                     // to the same node (multi-graph).
2374                     stack.Push(DfsBlockEntry(DSS_Pre, succ));
2375                     BlockSetOps::AddElemD(this, visited, succ->bbNum);
2376                 }
2377             }
2378         }
2379         else
2380         {
2381             // This is a post-visit that corresponds to the last time the
2382             // node is visited in the spanning tree and only happens after
2383             // all descendents in the spanning tree have had pre and post
2384             // actions applied.
2385
2386             assert(current.dfsStackState == DSS_Post);
2387
2388             unsigned invCount = fgBBcount - *count + 1;
2389             assert(1 <= invCount && invCount <= fgBBNumMax);
2390             fgBBInvPostOrder[invCount] = currentBlock;
2391             currentBlock->bbDfsNum     = invCount;
2392             ++(*count);
2393         }
2394     }
2395 }
2396
2397 void Compiler::fgComputeDoms()
2398 {
2399     assert(!fgCheapPredsValid);
2400
2401 #ifdef DEBUG
2402     if (verbose)
2403     {
2404         printf("*************** In fgComputeDoms\n");
2405     }
2406
2407     fgVerifyHandlerTab();
2408
2409     // Make sure that the predecessor lists are accurate.
2410     // Also check that the blocks are properly, densely numbered (so calling fgRenumberBlocks is not necessary).
2411     fgDebugCheckBBlist(true);
2412
2413     // Assert things related to the BlockSet epoch.
2414     assert(fgBBcount == fgBBNumMax);
2415     assert(BasicBlockBitSetTraits::GetSize(this) == fgBBNumMax + 1);
2416 #endif // DEBUG
2417
2418     BlockSet processedBlks(BlockSetOps::MakeEmpty(this));
2419
2420     fgBBInvPostOrder = new (this, CMK_DominatorMemory) BasicBlock*[fgBBNumMax + 1];
2421     memset(fgBBInvPostOrder, 0, sizeof(BasicBlock*) * (fgBBNumMax + 1));
2422
2423     fgDfsInvPostOrder();
2424     noway_assert(fgBBInvPostOrder[0] == nullptr);
2425
2426     // flRoot and bbRoot represent an imaginary unique entry point in the flow graph.
2427     // All the orphaned EH blocks and fgFirstBB will temporarily have its predecessors list
2428     // (with bbRoot as the only basic block in it) set as flRoot.
2429     // Later on, we clear their predecessors and let them to be nullptr again.
2430     // Since we number basic blocks starting at one, the imaginary entry block is conveniently numbered as zero.
2431     flowList   flRoot;
2432     BasicBlock bbRoot;
2433
2434     bbRoot.bbPreds  = nullptr;
2435     bbRoot.bbNum    = 0;
2436     bbRoot.bbIDom   = &bbRoot;
2437     bbRoot.bbDfsNum = 0;
2438     bbRoot.bbFlags  = 0;
2439     flRoot.flNext   = nullptr;
2440     flRoot.flBlock  = &bbRoot;
2441
2442     fgBBInvPostOrder[0] = &bbRoot;
2443
2444     // Mark both bbRoot and fgFirstBB processed
2445     BlockSetOps::AddElemD(this, processedBlks, 0); // bbRoot    == block #0
2446     BlockSetOps::AddElemD(this, processedBlks, 1); // fgFirstBB == block #1
2447     assert(fgFirstBB->bbNum == 1);
2448
2449     // Special case fgFirstBB to say its IDom is bbRoot.
2450     fgFirstBB->bbIDom = &bbRoot;
2451
2452     BasicBlock* block = nullptr;
2453
2454     for (block = fgFirstBB->bbNext; block != nullptr; block = block->bbNext)
2455     {
2456         // If any basic block has no predecessors then we flag it as processed and temporarily
2457         // mark its precedessor list to be flRoot.  This makes the flowgraph connected,
2458         // a precondition that is needed by the dominance algorithm to operate properly.
2459         if (block->bbPreds == nullptr)
2460         {
2461             block->bbPreds = &flRoot;
2462             block->bbIDom  = &bbRoot;
2463             BlockSetOps::AddElemD(this, processedBlks, block->bbNum);
2464         }
2465         else
2466         {
2467             block->bbIDom = nullptr;
2468         }
2469     }
2470
2471     // Mark the EH blocks as entry blocks and also flag them as processed.
2472     if (compHndBBtabCount > 0)
2473     {
2474         EHblkDsc* HBtab;
2475         EHblkDsc* HBtabEnd;
2476         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
2477         {
2478             if (HBtab->HasFilter())
2479             {
2480                 HBtab->ebdFilter->bbIDom = &bbRoot;
2481                 BlockSetOps::AddElemD(this, processedBlks, HBtab->ebdFilter->bbNum);
2482             }
2483             HBtab->ebdHndBeg->bbIDom = &bbRoot;
2484             BlockSetOps::AddElemD(this, processedBlks, HBtab->ebdHndBeg->bbNum);
2485         }
2486     }
2487
2488     // Now proceed to compute the immediate dominators for each basic block.
2489     bool changed = true;
2490     while (changed)
2491     {
2492         changed = false;
2493         for (unsigned i = 1; i <= fgBBNumMax;
2494              ++i) // Process each actual block; don't process the imaginary predecessor block.
2495         {
2496             flowList*   first   = nullptr;
2497             BasicBlock* newidom = nullptr;
2498             block               = fgBBInvPostOrder[i];
2499
2500             // If we have a block that has bbRoot as its bbIDom
2501             // it means we flag it as processed and as an entry block so
2502             // in this case we're all set.
2503             if (block->bbIDom == &bbRoot)
2504             {
2505                 continue;
2506             }
2507
2508             // Pick up the first processed predecesor of the current block.
2509             for (first = block->bbPreds; first != nullptr; first = first->flNext)
2510             {
2511                 if (BlockSetOps::IsMember(this, processedBlks, first->flBlock->bbNum))
2512                 {
2513                     break;
2514                 }
2515             }
2516             noway_assert(first != nullptr);
2517
2518             // We assume the first processed predecessor will be the
2519             // immediate dominator and then compute the forward flow analysis.
2520             newidom = first->flBlock;
2521             for (flowList* p = block->bbPreds; p != nullptr; p = p->flNext)
2522             {
2523                 if (p->flBlock == first->flBlock)
2524                 {
2525                     continue;
2526                 }
2527                 if (p->flBlock->bbIDom != nullptr)
2528                 {
2529                     // fgIntersectDom is basically the set intersection between
2530                     // the dominance sets of the new IDom and the current predecessor
2531                     // Since the nodes are ordered in DFS inverse post order and
2532                     // IDom induces a tree, fgIntersectDom actually computes
2533                     // the lowest common ancestor in the dominator tree.
2534                     newidom = fgIntersectDom(p->flBlock, newidom);
2535                 }
2536             }
2537
2538             // If the Immediate dominator changed, assign the new one
2539             // to the current working basic block.
2540             if (block->bbIDom != newidom)
2541             {
2542                 noway_assert(newidom != nullptr);
2543                 block->bbIDom = newidom;
2544                 changed       = true;
2545             }
2546             BlockSetOps::AddElemD(this, processedBlks, block->bbNum);
2547         }
2548     }
2549
2550     // As stated before, once we have computed immediate dominance we need to clear
2551     // all the basic blocks whose predecessor list was set to flRoot.  This
2552     // reverts that and leaves the blocks the same as before.
2553     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2554     {
2555         if (block->bbPreds == &flRoot)
2556         {
2557             block->bbPreds = nullptr;
2558         }
2559     }
2560
2561     fgCompDominatedByExceptionalEntryBlocks();
2562
2563 #ifdef DEBUG
2564     if (verbose)
2565     {
2566         fgDispDoms();
2567     }
2568 #endif
2569
2570     fgBuildDomTree();
2571
2572     fgModified   = false;
2573     fgDomBBcount = fgBBcount;
2574     assert(fgBBcount == fgBBNumMax);
2575     assert(BasicBlockBitSetTraits::GetSize(this) == fgDomBBcount + 1);
2576
2577     fgDomsComputed = true;
2578 }
2579
2580 void Compiler::fgBuildDomTree()
2581 {
2582     unsigned    i;
2583     BasicBlock* block;
2584
2585 #ifdef DEBUG
2586     if (verbose)
2587     {
2588         printf("\nInside fgBuildDomTree\n");
2589     }
2590 #endif // DEBUG
2591
2592     // domTree :: The dominance tree represented using adjacency lists. We use BasicBlockList to represent edges.
2593     // Indexed by basic block number.
2594     unsigned         bbArraySize = fgBBNumMax + 1;
2595     BasicBlockList** domTree     = new (this, CMK_DominatorMemory) BasicBlockList*[bbArraySize];
2596
2597     fgDomTreePreOrder  = new (this, CMK_DominatorMemory) unsigned[bbArraySize];
2598     fgDomTreePostOrder = new (this, CMK_DominatorMemory) unsigned[bbArraySize];
2599
2600     // Initialize all the data structures.
2601     for (i = 0; i < bbArraySize; ++i)
2602     {
2603         domTree[i]           = nullptr;
2604         fgDomTreePreOrder[i] = fgDomTreePostOrder[i] = 0;
2605     }
2606
2607     // Build the dominance tree.
2608     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2609     {
2610         // If the immediate dominator is not the imaginary root (bbRoot)
2611         // we proceed to append this block to the children of the dominator node.
2612         if (block->bbIDom->bbNum != 0)
2613         {
2614             int bbNum      = block->bbIDom->bbNum;
2615             domTree[bbNum] = new (this, CMK_DominatorMemory) BasicBlockList(block, domTree[bbNum]);
2616         }
2617         else
2618         {
2619             // This means this block had bbRoot set as its IDom.  We clear it out
2620             // and convert the tree back to a forest.
2621             block->bbIDom = nullptr;
2622         }
2623     }
2624
2625 #ifdef DEBUG
2626     if (verbose)
2627     {
2628         printf("\nAfter computing the Dominance Tree:\n");
2629         fgDispDomTree(domTree);
2630     }
2631 #endif // DEBUG
2632
2633     // Get the bitset that represents the roots of the dominance tree.
2634     // Something to note here is that the dominance tree has been converted from a forest to a tree
2635     // by using the bbRoot trick on fgComputeDoms. The reason we have a forest instead of a real tree
2636     // is because we treat the EH blocks as entry nodes so the real dominance tree is not necessarily connected.
2637     BlockSet_ValRet_T domTreeEntryNodes = fgDomTreeEntryNodes(domTree);
2638
2639     // The preorder and postorder numbers.
2640     // We start from 1 to match the bbNum ordering.
2641     unsigned preNum  = 1;
2642     unsigned postNum = 1;
2643
2644     // There will be nodes in the dominance tree that will not be reachable:
2645     // the catch blocks that return since they don't have any predecessor.
2646     // For that matter we'll keep track of how many nodes we can
2647     // reach and assert at the end that we visited all of them.
2648     unsigned domTreeReachable = fgBBcount;
2649
2650     // Once we have the dominance tree computed, we need to traverse it
2651     // to get the preorder and postorder numbers for each node.  The purpose of
2652     // this is to achieve O(1) queries for of the form A dominates B.
2653     for (i = 1; i <= fgBBNumMax; ++i)
2654     {
2655         if (BlockSetOps::IsMember(this, domTreeEntryNodes, i))
2656         {
2657             if (domTree[i] == nullptr)
2658             {
2659                 // If this is an entry node but there's no children on this
2660                 // node, it means it's unreachable so we decrement the reachable
2661                 // counter.
2662                 --domTreeReachable;
2663             }
2664             else
2665             {
2666                 // Otherwise, we do a DFS traversal of the dominator tree.
2667                 fgTraverseDomTree(i, domTree, &preNum, &postNum);
2668             }
2669         }
2670     }
2671
2672     noway_assert(preNum == domTreeReachable + 1);
2673     noway_assert(postNum == domTreeReachable + 1);
2674
2675     // Once we have all the reachable nodes numbered, we proceed to
2676     // assign numbers to the non-reachable ones, just assign incrementing
2677     // values.  We must reach fgBBcount at the end.
2678
2679     for (i = 1; i <= fgBBNumMax; ++i)
2680     {
2681         if (BlockSetOps::IsMember(this, domTreeEntryNodes, i))
2682         {
2683             if (domTree[i] == nullptr)
2684             {
2685                 fgDomTreePreOrder[i]  = preNum++;
2686                 fgDomTreePostOrder[i] = postNum++;
2687             }
2688         }
2689     }
2690
2691     noway_assert(preNum == fgBBNumMax + 1);
2692     noway_assert(postNum == fgBBNumMax + 1);
2693     noway_assert(fgDomTreePreOrder[0] == 0);  // Unused first element
2694     noway_assert(fgDomTreePostOrder[0] == 0); // Unused first element
2695
2696 #ifdef DEBUG
2697     if (0 && verbose)
2698     {
2699         printf("\nAfter traversing the dominance tree:\n");
2700         printf("PreOrder:\n");
2701         for (i = 1; i <= fgBBNumMax; ++i)
2702         {
2703             printf("BB%02u : %02u\n", i, fgDomTreePreOrder[i]);
2704         }
2705         printf("PostOrder:\n");
2706         for (i = 1; i <= fgBBNumMax; ++i)
2707         {
2708             printf("BB%02u : %02u\n", i, fgDomTreePostOrder[i]);
2709         }
2710     }
2711 #endif // DEBUG
2712 }
2713
2714 BlockSet_ValRet_T Compiler::fgDomTreeEntryNodes(BasicBlockList** domTree)
2715 {
2716     // domTreeEntryNodes ::  Set that represents which basic blocks are roots of the dominator forest.
2717
2718     BlockSet domTreeEntryNodes(BlockSetOps::MakeFull(this));
2719
2720     // First of all we need to find all the roots of the dominance forest.
2721
2722     for (unsigned i = 1; i <= fgBBNumMax; ++i)
2723     {
2724         for (BasicBlockList* current = domTree[i]; current != nullptr; current = current->next)
2725         {
2726             BlockSetOps::RemoveElemD(this, domTreeEntryNodes, current->block->bbNum);
2727         }
2728     }
2729
2730     return domTreeEntryNodes;
2731 }
2732
2733 #ifdef DEBUG
2734 void Compiler::fgDispDomTree(BasicBlockList** domTree)
2735 {
2736     for (unsigned i = 1; i <= fgBBNumMax; ++i)
2737     {
2738         if (domTree[i] != nullptr)
2739         {
2740             printf("BB%02u : ", i);
2741             for (BasicBlockList* current = domTree[i]; current != nullptr; current = current->next)
2742             {
2743                 assert(current->block);
2744                 printf("BB%02u ", current->block->bbNum);
2745             }
2746             printf("\n");
2747         }
2748     }
2749     printf("\n");
2750 }
2751 #endif // DEBUG
2752
2753 //------------------------------------------------------------------------
2754 // fgTraverseDomTree: Assign pre/post-order numbers to the dominator tree.
2755 //
2756 // Arguments:
2757 //    bbNum   - The basic block number of the starting block
2758 //    domTree - The dominator tree (as child block lists)
2759 //    preNum  - Pointer to the pre-number counter
2760 //    postNum - Pointer to the post-number counter
2761 //
2762 // Notes:
2763 //    Runs a non-recursive DFS traversal of the dominator tree using an
2764 //    evaluation stack to assign pre-order and post-order numbers.
2765 //    These numberings are used to provide constant time lookup for
2766 //    ancestor/descendent tests between pairs of nodes in the tree.
2767
2768 void Compiler::fgTraverseDomTree(unsigned bbNum, BasicBlockList** domTree, unsigned* preNum, unsigned* postNum)
2769 {
2770     noway_assert(bbNum <= fgBBNumMax);
2771
2772     // If the block preorder number is not zero it means we already visited
2773     // that node, so we skip it.
2774     if (fgDomTreePreOrder[bbNum] == 0)
2775     {
2776         // If this is the first time we visit this node, both preorder and postnumber
2777         // values must be zero.
2778         noway_assert(fgDomTreePostOrder[bbNum] == 0);
2779
2780         // Allocate a local stack to hold the Dfs traversal actions necessary
2781         // to compute pre/post-ordering of the dominator tree.
2782         ArrayStack<DfsNumEntry> stack(this);
2783
2784         // Push the first entry number on the stack to seed the traversal.
2785         stack.Push(DfsNumEntry(DSS_Pre, bbNum));
2786
2787         // The search is terminated once all the actions have been processed.
2788         while (stack.Height() != 0)
2789         {
2790             DfsNumEntry current    = stack.Pop();
2791             unsigned    currentNum = current.dfsNum;
2792
2793             if (current.dfsStackState == DSS_Pre)
2794             {
2795                 // This pre-visit action corresponds to the first time the
2796                 // node is encountered during the spanning traversal.
2797                 noway_assert(fgDomTreePreOrder[currentNum] == 0);
2798                 noway_assert(fgDomTreePostOrder[currentNum] == 0);
2799
2800                 // Assign the preorder number on the first visit.
2801                 fgDomTreePreOrder[currentNum] = (*preNum)++;
2802
2803                 // Push this nodes post-action on the stack such that all successors
2804                 // pre-order visits occur before this nodes post-action. We will assign
2805                 // its post-order numbers when we pop off the stack.
2806                 stack.Push(DfsNumEntry(DSS_Post, currentNum));
2807
2808                 // For each child in the dominator tree process its pre-actions.
2809                 for (BasicBlockList* child = domTree[currentNum]; child != nullptr; child = child->next)
2810                 {
2811                     unsigned childNum = child->block->bbNum;
2812
2813                     // This is a tree so never could have been visited
2814                     assert(fgDomTreePreOrder[childNum] == 0);
2815
2816                     // Push the successor in the dominator tree for pre-actions.
2817                     stack.Push(DfsNumEntry(DSS_Pre, childNum));
2818                 }
2819             }
2820             else
2821             {
2822                 // This post-visit action corresponds to the last time the node
2823                 // is encountered and only after all descendents in the spanning
2824                 // tree have had pre and post-order numbers assigned.
2825
2826                 assert(current.dfsStackState == DSS_Post);
2827                 assert(fgDomTreePreOrder[currentNum] != 0);
2828                 assert(fgDomTreePostOrder[currentNum] == 0);
2829
2830                 // Now assign this nodes post-order number.
2831                 fgDomTreePostOrder[currentNum] = (*postNum)++;
2832             }
2833         }
2834     }
2835 }
2836
2837 // This code finds the lowest common ancestor in the
2838 // dominator tree between two basic blocks. The LCA in the Dominance tree
2839 // represents the closest dominator between the two basic blocks. Used to
2840 // adjust the IDom value in fgComputDoms.
2841 BasicBlock* Compiler::fgIntersectDom(BasicBlock* a, BasicBlock* b)
2842 {
2843     BasicBlock* finger1 = a;
2844     BasicBlock* finger2 = b;
2845     while (finger1 != finger2)
2846     {
2847         while (finger1->bbDfsNum > finger2->bbDfsNum)
2848         {
2849             finger1 = finger1->bbIDom;
2850         }
2851         while (finger2->bbDfsNum > finger1->bbDfsNum)
2852         {
2853             finger2 = finger2->bbIDom;
2854         }
2855     }
2856     return finger1;
2857 }
2858
2859 // Return a BlockSet containing all the blocks that dominate 'block'.
2860 BlockSet_ValRet_T Compiler::fgGetDominatorSet(BasicBlock* block)
2861 {
2862     assert(block != nullptr);
2863
2864     BlockSet domSet(BlockSetOps::MakeEmpty(this));
2865
2866     do
2867     {
2868         BlockSetOps::AddElemD(this, domSet, block->bbNum);
2869         if (block == block->bbIDom)
2870         {
2871             break; // We found a cycle in the IDom list, so we're done.
2872         }
2873         block = block->bbIDom;
2874     } while (block != nullptr);
2875
2876     return domSet;
2877 }
2878
2879 /*****************************************************************************
2880  *
2881  *  fgComputeCheapPreds: Function called to compute the BasicBlock::bbCheapPreds lists.
2882  *
2883  *  No other block data is changed (e.g., bbRefs, bbFlags).
2884  *
2885  *  The cheap preds lists are similar to the normal (bbPreds) predecessor lists, but are cheaper to
2886  *  compute and store, as follows:
2887  *  1. A flow edge is typed BasicBlockList, which only has a block pointer and 'next' pointer. It doesn't
2888  *     have weights or a dup count.
2889  *  2. The preds list for a block is not sorted by block number.
2890  *  3. The predecessors of the block following a BBJ_CALLFINALLY (the corresponding BBJ_ALWAYS,
2891  *     for normal, non-retless calls to the finally) are not computed.
2892  *  4. The cheap preds lists will contain duplicates if a single switch table has multiple branches
2893  *     to the same block. Thus, we don't spend the time looking for duplicates for every edge we insert.
2894  */
2895 void Compiler::fgComputeCheapPreds()
2896 {
2897     noway_assert(!fgComputePredsDone); // We can't do this if we've got the full preds.
2898     noway_assert(fgFirstBB != nullptr);
2899
2900     BasicBlock* block;
2901
2902 #ifdef DEBUG
2903     if (verbose)
2904     {
2905         printf("\n*************** In fgComputeCheapPreds()\n");
2906         fgDispBasicBlocks();
2907         printf("\n");
2908     }
2909 #endif // DEBUG
2910
2911     // Clear out the cheap preds lists.
2912     fgRemovePreds();
2913
2914     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2915     {
2916         switch (block->bbJumpKind)
2917         {
2918             case BBJ_COND:
2919                 fgAddCheapPred(block->bbJumpDest, block);
2920                 fgAddCheapPred(block->bbNext, block);
2921                 break;
2922
2923             case BBJ_CALLFINALLY:
2924             case BBJ_LEAVE: // If fgComputeCheapPreds is called before all blocks are imported, BBJ_LEAVE blocks are
2925                             // still in the BB list.
2926             case BBJ_ALWAYS:
2927             case BBJ_EHCATCHRET:
2928                 fgAddCheapPred(block->bbJumpDest, block);
2929                 break;
2930
2931             case BBJ_NONE:
2932                 fgAddCheapPred(block->bbNext, block);
2933                 break;
2934
2935             case BBJ_EHFILTERRET:
2936                 // Connect end of filter to catch handler.
2937                 // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
2938                 // fgComputeCheapPreds before fgImport on an ill-formed program; the problem will be detected in
2939                 // fgImport.
2940                 if (block->bbJumpDest != nullptr)
2941                 {
2942                     fgAddCheapPred(block->bbJumpDest, block);
2943                 }
2944                 break;
2945
2946             case BBJ_SWITCH:
2947                 unsigned jumpCnt;
2948                 jumpCnt = block->bbJumpSwt->bbsCount;
2949                 BasicBlock** jumpTab;
2950                 jumpTab = block->bbJumpSwt->bbsDstTab;
2951
2952                 do
2953                 {
2954                     fgAddCheapPred(*jumpTab, block);
2955                 } while (++jumpTab, --jumpCnt);
2956
2957                 break;
2958
2959             case BBJ_EHFINALLYRET: // It's expensive to compute the preds for this case, so we don't for the cheap
2960                                    // preds.
2961             case BBJ_THROW:
2962             case BBJ_RETURN:
2963                 break;
2964
2965             default:
2966                 noway_assert(!"Unexpected bbJumpKind");
2967                 break;
2968         }
2969     }
2970
2971     fgCheapPredsValid = true;
2972
2973 #ifdef DEBUG
2974     if (verbose)
2975     {
2976         printf("\n*************** After fgComputeCheapPreds()\n");
2977         fgDispBasicBlocks();
2978         printf("\n");
2979     }
2980 #endif
2981 }
2982
2983 /*****************************************************************************
2984  * Add 'blockPred' to the cheap predecessor list of 'block'.
2985  */
2986
2987 void Compiler::fgAddCheapPred(BasicBlock* block, BasicBlock* blockPred)
2988 {
2989     assert(!fgComputePredsDone);
2990     assert(block != nullptr);
2991     assert(blockPred != nullptr);
2992
2993     block->bbCheapPreds = new (this, CMK_FlowList) BasicBlockList(blockPred, block->bbCheapPreds);
2994
2995 #if MEASURE_BLOCK_SIZE
2996     genFlowNodeCnt += 1;
2997     genFlowNodeSize += sizeof(BasicBlockList);
2998 #endif // MEASURE_BLOCK_SIZE
2999 }
3000
3001 /*****************************************************************************
3002  * Remove 'blockPred' from the cheap predecessor list of 'block'.
3003  * If there are duplicate edges, only remove one of them.
3004  */
3005 void Compiler::fgRemoveCheapPred(BasicBlock* block, BasicBlock* blockPred)
3006 {
3007     assert(!fgComputePredsDone);
3008     assert(fgCheapPredsValid);
3009
3010     flowList* oldEdge = nullptr;
3011
3012     assert(block != nullptr);
3013     assert(blockPred != nullptr);
3014     assert(block->bbCheapPreds != nullptr);
3015
3016     /* Is this the first block in the pred list? */
3017     if (blockPred == block->bbCheapPreds->block)
3018     {
3019         block->bbCheapPreds = block->bbCheapPreds->next;
3020     }
3021     else
3022     {
3023         BasicBlockList* pred;
3024         for (pred = block->bbCheapPreds; pred->next != nullptr; pred = pred->next)
3025         {
3026             if (blockPred == pred->next->block)
3027             {
3028                 break;
3029             }
3030         }
3031         noway_assert(pred->next != nullptr); // we better have found it!
3032         pred->next = pred->next->next;       // splice it out
3033     }
3034 }
3035
3036 void Compiler::fgRemovePreds()
3037 {
3038     C_ASSERT(offsetof(BasicBlock, bbPreds) ==
3039              offsetof(BasicBlock, bbCheapPreds)); // bbPreds and bbCheapPreds are at the same place in a union,
3040     C_ASSERT(sizeof(((BasicBlock*)nullptr)->bbPreds) ==
3041              sizeof(((BasicBlock*)nullptr)->bbCheapPreds)); // and are the same size. So, this function removes both.
3042
3043     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
3044     {
3045         block->bbPreds = nullptr;
3046     }
3047     fgComputePredsDone = false;
3048     fgCheapPredsValid  = false;
3049 }
3050
3051 /*****************************************************************************
3052  *
3053  *  Function called to compute the bbPreds lists.
3054  */
3055 void Compiler::fgComputePreds()
3056 {
3057     noway_assert(fgFirstBB);
3058
3059     BasicBlock* block;
3060
3061 #ifdef DEBUG
3062     if (verbose)
3063     {
3064         printf("\n*************** In fgComputePreds()\n");
3065         fgDispBasicBlocks();
3066         printf("\n");
3067     }
3068 #endif // DEBUG
3069
3070     // reset the refs count for each basic block
3071
3072     for (block = fgFirstBB; block; block = block->bbNext)
3073     {
3074         block->bbRefs = 0;
3075     }
3076
3077     /* the first block is always reachable! */
3078     fgFirstBB->bbRefs = 1;
3079
3080     /* Treat the initial block as a jump target */
3081     fgFirstBB->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3082
3083     fgRemovePreds();
3084
3085     for (block = fgFirstBB; block; block = block->bbNext)
3086     {
3087         switch (block->bbJumpKind)
3088         {
3089             case BBJ_CALLFINALLY:
3090                 if (!(block->bbFlags & BBF_RETLESS_CALL))
3091                 {
3092                     assert(block->isBBCallAlwaysPair());
3093
3094                     /* Mark the next block as being a jump target,
3095                        since the call target will return there */
3096                     PREFIX_ASSUME(block->bbNext != nullptr);
3097                     block->bbNext->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
3098                 }
3099
3100                 __fallthrough;
3101
3102             case BBJ_LEAVE: // Sometimes fgComputePreds is called before all blocks are imported, so BBJ_LEAVE
3103                             // blocks are still in the BB list.
3104             case BBJ_COND:
3105             case BBJ_ALWAYS:
3106             case BBJ_EHCATCHRET:
3107
3108                 /* Mark the jump dest block as being a jump target */
3109                 block->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3110
3111                 fgAddRefPred(block->bbJumpDest, block, nullptr, true);
3112
3113                 /* Is the next block reachable? */
3114
3115                 if (block->bbJumpKind != BBJ_COND)
3116                 {
3117                     break;
3118                 }
3119
3120                 noway_assert(block->bbNext);
3121
3122                 /* Fall through, the next block is also reachable */
3123                 __fallthrough;
3124
3125             case BBJ_NONE:
3126
3127                 fgAddRefPred(block->bbNext, block, nullptr, true);
3128                 break;
3129
3130             case BBJ_EHFILTERRET:
3131
3132                 // Connect end of filter to catch handler.
3133                 // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
3134                 // fgComputePreds before fgImport on an ill-formed program; the problem will be detected in fgImport.
3135                 if (block->bbJumpDest != nullptr)
3136                 {
3137                     fgAddRefPred(block->bbJumpDest, block, nullptr, true);
3138                 }
3139                 break;
3140
3141             case BBJ_EHFINALLYRET:
3142             {
3143                 /* Connect the end of the finally to the successor of
3144                   the call to this finally */
3145
3146                 if (!block->hasHndIndex())
3147                 {
3148                     NO_WAY("endfinally outside a finally/fault block.");
3149                 }
3150
3151                 unsigned  hndIndex = block->getHndIndex();
3152                 EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
3153
3154                 if (!ehDsc->HasFinallyOrFaultHandler())
3155                 {
3156                     NO_WAY("endfinally outside a finally/fault block.");
3157                 }
3158
3159                 if (ehDsc->HasFinallyHandler())
3160                 {
3161                     // Find all BBJ_CALLFINALLY that branched to this finally handler.
3162                     BasicBlock* begBlk;
3163                     BasicBlock* endBlk;
3164                     ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
3165
3166                     BasicBlock* finBeg = ehDsc->ebdHndBeg;
3167                     for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
3168                     {
3169                         if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
3170                         {
3171                             continue;
3172                         }
3173
3174                         noway_assert(bcall->isBBCallAlwaysPair());
3175                         fgAddRefPred(bcall->bbNext, block, nullptr, true);
3176                     }
3177                 }
3178             }
3179             break;
3180
3181             case BBJ_THROW:
3182             case BBJ_RETURN:
3183                 break;
3184
3185             case BBJ_SWITCH:
3186                 unsigned jumpCnt;
3187                 jumpCnt = block->bbJumpSwt->bbsCount;
3188                 BasicBlock** jumpTab;
3189                 jumpTab = block->bbJumpSwt->bbsDstTab;
3190
3191                 do
3192                 {
3193                     /* Mark the target block as being a jump target */
3194                     (*jumpTab)->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3195
3196                     fgAddRefPred(*jumpTab, block, nullptr, true);
3197                 } while (++jumpTab, --jumpCnt);
3198
3199                 break;
3200
3201             default:
3202                 noway_assert(!"Unexpected bbJumpKind");
3203                 break;
3204         }
3205     }
3206
3207     for (unsigned EHnum = 0; EHnum < compHndBBtabCount; EHnum++)
3208     {
3209         EHblkDsc* ehDsc = ehGetDsc(EHnum);
3210
3211         if (ehDsc->HasFilter())
3212         {
3213             ehDsc->ebdFilter->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3214
3215             // The first block of a filter has an artifical extra refcount.
3216             ehDsc->ebdFilter->bbRefs++;
3217         }
3218
3219         ehDsc->ebdHndBeg->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3220
3221         // The first block of a handler has an artificial extra refcount.
3222         ehDsc->ebdHndBeg->bbRefs++;
3223     }
3224
3225     fgModified         = false;
3226     fgComputePredsDone = true;
3227
3228 #ifdef DEBUG
3229     if (verbose)
3230     {
3231         printf("\n*************** After fgComputePreds()\n");
3232         fgDispBasicBlocks();
3233         printf("\n");
3234     }
3235 #endif
3236 }
3237
3238 unsigned Compiler::fgNSuccsOfFinallyRet(BasicBlock* block)
3239 {
3240     BasicBlock* bb;
3241     unsigned    res;
3242     fgSuccOfFinallyRetWork(block, ~0, &bb, &res);
3243     return res;
3244 }
3245
3246 BasicBlock* Compiler::fgSuccOfFinallyRet(BasicBlock* block, unsigned i)
3247 {
3248     BasicBlock* bb;
3249     unsigned    res;
3250     fgSuccOfFinallyRetWork(block, i, &bb, &res);
3251     return bb;
3252 }
3253
3254 void Compiler::fgSuccOfFinallyRetWork(BasicBlock* block, unsigned i, BasicBlock** bres, unsigned* nres)
3255 {
3256     assert(block->hasHndIndex()); // Otherwise, endfinally outside a finally/fault block?
3257
3258     unsigned  hndIndex = block->getHndIndex();
3259     EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
3260
3261     assert(ehDsc->HasFinallyOrFaultHandler()); // Otherwise, endfinally outside a finally/fault block.
3262
3263     *bres            = nullptr;
3264     unsigned succNum = 0;
3265
3266     if (ehDsc->HasFinallyHandler())
3267     {
3268         BasicBlock* begBlk;
3269         BasicBlock* endBlk;
3270         ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
3271
3272         BasicBlock* finBeg = ehDsc->ebdHndBeg;
3273
3274         for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
3275         {
3276             if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
3277             {
3278                 continue;
3279             }
3280
3281             assert(bcall->isBBCallAlwaysPair());
3282
3283             if (succNum == i)
3284             {
3285                 *bres = bcall->bbNext;
3286                 return;
3287             }
3288             succNum++;
3289         }
3290     }
3291     assert(i == ~0u || ehDsc->HasFaultHandler()); // Should reach here only for fault blocks.
3292     if (i == ~0u)
3293     {
3294         *nres = succNum;
3295     }
3296 }
3297
3298 Compiler::SwitchUniqueSuccSet Compiler::GetDescriptorForSwitch(BasicBlock* switchBlk)
3299 {
3300     assert(switchBlk->bbJumpKind == BBJ_SWITCH);
3301     BlockToSwitchDescMap* switchMap = GetSwitchDescMap();
3302     SwitchUniqueSuccSet   res;
3303     if (switchMap->Lookup(switchBlk, &res))
3304     {
3305         return res;
3306     }
3307     else
3308     {
3309         // We must compute the descriptor. Find which are dups, by creating a bit set with the unique successors.
3310         // We create a temporary bitset of blocks to compute the unique set of successor blocks,
3311         // since adding a block's number twice leaves just one "copy" in the bitset. Note that
3312         // we specifically don't use the BlockSet type, because doing so would require making a
3313         // call to EnsureBasicBlockEpoch() to make sure the epoch is up-to-date. However, that
3314         // can create a new epoch, thus invalidating all existing BlockSet objects, such as
3315         // reachability information stored in the blocks. To avoid that, we just use a local BitVec.
3316
3317         BitVecTraits blockVecTraits(fgBBNumMax + 1, this);
3318         BitVec       uniqueSuccBlocks(BitVecOps::MakeEmpty(&blockVecTraits));
3319         BasicBlock** jumpTable = switchBlk->bbJumpSwt->bbsDstTab;
3320         unsigned     jumpCount = switchBlk->bbJumpSwt->bbsCount;
3321         for (unsigned i = 0; i < jumpCount; i++)
3322         {
3323             BasicBlock* targ = jumpTable[i];
3324             BitVecOps::AddElemD(&blockVecTraits, uniqueSuccBlocks, targ->bbNum);
3325         }
3326         // Now we have a set of unique successors.
3327         unsigned numNonDups = BitVecOps::Count(&blockVecTraits, uniqueSuccBlocks);
3328
3329         BasicBlock** nonDups = new (getAllocator()) BasicBlock*[numNonDups];
3330
3331         unsigned nonDupInd = 0;
3332         // At this point, all unique targets are in "uniqueSuccBlocks".  As we encounter each,
3333         // add to nonDups, remove from "uniqueSuccBlocks".
3334         for (unsigned i = 0; i < jumpCount; i++)
3335         {
3336             BasicBlock* targ = jumpTable[i];
3337             if (BitVecOps::IsMember(&blockVecTraits, uniqueSuccBlocks, targ->bbNum))
3338             {
3339                 nonDups[nonDupInd] = targ;
3340                 nonDupInd++;
3341                 BitVecOps::RemoveElemD(&blockVecTraits, uniqueSuccBlocks, targ->bbNum);
3342             }
3343         }
3344
3345         assert(nonDupInd == numNonDups);
3346         assert(BitVecOps::Count(&blockVecTraits, uniqueSuccBlocks) == 0);
3347         res.numDistinctSuccs = numNonDups;
3348         res.nonDuplicates    = nonDups;
3349         switchMap->Set(switchBlk, res);
3350         return res;
3351     }
3352 }
3353
3354 void Compiler::SwitchUniqueSuccSet::UpdateTarget(CompAllocator* alloc,
3355                                                  BasicBlock*    switchBlk,
3356                                                  BasicBlock*    from,
3357                                                  BasicBlock*    to)
3358 {
3359     assert(switchBlk->bbJumpKind == BBJ_SWITCH); // Precondition.
3360     unsigned     jmpTabCnt = switchBlk->bbJumpSwt->bbsCount;
3361     BasicBlock** jmpTab    = switchBlk->bbJumpSwt->bbsDstTab;
3362
3363     // Is "from" still in the switch table (because it had more than one entry before?)
3364     bool fromStillPresent = false;
3365     for (unsigned i = 0; i < jmpTabCnt; i++)
3366     {
3367         if (jmpTab[i] == from)
3368         {
3369             fromStillPresent = true;
3370             break;
3371         }
3372     }
3373
3374     // Is "to" already in "this"?
3375     bool toAlreadyPresent = false;
3376     for (unsigned i = 0; i < numDistinctSuccs; i++)
3377     {
3378         if (nonDuplicates[i] == to)
3379         {
3380             toAlreadyPresent = true;
3381             break;
3382         }
3383     }
3384
3385     // Four cases:
3386     //   If "from" is still present, and "to" is already present, do nothing
3387     //   If "from" is still present, and "to" is not, must reallocate to add an entry.
3388     //   If "from" is not still present, and "to" is not present, write "to" where "from" was.
3389     //   If "from" is not still present, but "to" is present, remove "from".
3390     if (fromStillPresent && toAlreadyPresent)
3391     {
3392         return;
3393     }
3394     else if (fromStillPresent && !toAlreadyPresent)
3395     {
3396         // reallocate to add an entry
3397         BasicBlock** newNonDups = new (alloc) BasicBlock*[numDistinctSuccs + 1];
3398         memcpy(newNonDups, nonDuplicates, numDistinctSuccs * sizeof(BasicBlock*));
3399         newNonDups[numDistinctSuccs] = to;
3400         numDistinctSuccs++;
3401         nonDuplicates = newNonDups;
3402     }
3403     else if (!fromStillPresent && !toAlreadyPresent)
3404     {
3405 #ifdef DEBUG
3406         // write "to" where "from" was
3407         bool foundFrom = false;
3408 #endif // DEBUG
3409         for (unsigned i = 0; i < numDistinctSuccs; i++)
3410         {
3411             if (nonDuplicates[i] == from)
3412             {
3413                 nonDuplicates[i] = to;
3414 #ifdef DEBUG
3415                 foundFrom = true;
3416 #endif // DEBUG
3417                 break;
3418             }
3419         }
3420         assert(foundFrom);
3421     }
3422     else
3423     {
3424         assert(!fromStillPresent && toAlreadyPresent);
3425 #ifdef DEBUG
3426         // remove "from".
3427         bool foundFrom = false;
3428 #endif // DEBUG
3429         for (unsigned i = 0; i < numDistinctSuccs; i++)
3430         {
3431             if (nonDuplicates[i] == from)
3432             {
3433                 nonDuplicates[i] = nonDuplicates[numDistinctSuccs - 1];
3434                 numDistinctSuccs--;
3435 #ifdef DEBUG
3436                 foundFrom = true;
3437 #endif // DEBUG
3438                 break;
3439             }
3440         }
3441         assert(foundFrom);
3442     }
3443 }
3444
3445 /*****************************************************************************
3446  *
3447  *  Simple utility function to remove an entry for a block in the switch desc
3448  *  map. So it can be called from other phases.
3449  *
3450  */
3451 void Compiler::fgInvalidateSwitchDescMapEntry(BasicBlock* block)
3452 {
3453     // Check if map has no entries yet.
3454     if (m_switchDescMap != nullptr)
3455     {
3456         m_switchDescMap->Remove(block);
3457     }
3458 }
3459
3460 void Compiler::UpdateSwitchTableTarget(BasicBlock* switchBlk, BasicBlock* from, BasicBlock* to)
3461 {
3462     if (m_switchDescMap == nullptr)
3463     {
3464         return; // No mappings, nothing to do.
3465     }
3466
3467     // Otherwise...
3468     BlockToSwitchDescMap* switchMap = GetSwitchDescMap();
3469     SwitchUniqueSuccSet*  res       = switchMap->LookupPointer(switchBlk);
3470     if (res != nullptr)
3471     {
3472         // If no result, nothing to do. Otherwise, update it.
3473         res->UpdateTarget(getAllocator(), switchBlk, from, to);
3474     }
3475 }
3476
3477 /*****************************************************************************
3478  *  For a block that is in a handler region, find the first block of the most-nested
3479  *  handler containing the block.
3480  */
3481 BasicBlock* Compiler::fgFirstBlockOfHandler(BasicBlock* block)
3482 {
3483     assert(block->hasHndIndex());
3484     return ehGetDsc(block->getHndIndex())->ebdHndBeg;
3485 }
3486
3487 /*****************************************************************************
3488  *
3489  *  Function called to find back edges and return blocks and mark them as needing GC Polls.  This marks all
3490  *  blocks.
3491  */
3492 void Compiler::fgMarkGCPollBlocks()
3493 {
3494     if (GCPOLL_NONE == opts.compGCPollType)
3495     {
3496         return;
3497     }
3498
3499 #ifdef DEBUG
3500     /* Check that the flowgraph data (bbNum, bbRefs, bbPreds) is up-to-date */
3501     fgDebugCheckBBlist();
3502 #endif
3503
3504     BasicBlock* block;
3505
3506     // Return blocks always need GC polls.  In addition, all back edges (including those from switch
3507     // statements) need GC polls.  The poll is on the block with the outgoing back edge (or ret), rather than
3508     // on the destination or on the edge itself.
3509     for (block = fgFirstBB; block; block = block->bbNext)
3510     {
3511         bool blockNeedsPoll = false;
3512         switch (block->bbJumpKind)
3513         {
3514             case BBJ_COND:
3515             case BBJ_ALWAYS:
3516                 blockNeedsPoll = (block->bbJumpDest->bbNum <= block->bbNum);
3517                 break;
3518
3519             case BBJ_RETURN:
3520                 blockNeedsPoll = true;
3521                 break;
3522
3523             case BBJ_SWITCH:
3524                 unsigned jumpCnt;
3525                 jumpCnt = block->bbJumpSwt->bbsCount;
3526                 BasicBlock** jumpTab;
3527                 jumpTab = block->bbJumpSwt->bbsDstTab;
3528
3529                 do
3530                 {
3531                     if ((*jumpTab)->bbNum <= block->bbNum)
3532                     {
3533                         blockNeedsPoll = true;
3534                         break;
3535                     }
3536                 } while (++jumpTab, --jumpCnt);
3537                 break;
3538
3539             default:
3540                 break;
3541         }
3542
3543         if (blockNeedsPoll)
3544         {
3545             block->bbFlags |= BBF_NEEDS_GCPOLL;
3546         }
3547     }
3548 }
3549
3550 void Compiler::fgInitBlockVarSets()
3551 {
3552     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
3553     {
3554         block->InitVarSets(this);
3555     }
3556
3557     fgBBVarSetsInited = true;
3558 }
3559
3560 /*****************************************************************************
3561  *
3562  *  The following does the final pass on BBF_NEEDS_GCPOLL and then actually creates the GC Polls.
3563  */
3564 void Compiler::fgCreateGCPolls()
3565 {
3566     if (GCPOLL_NONE == opts.compGCPollType)
3567     {
3568         return;
3569     }
3570
3571     bool createdPollBlocks = false;
3572
3573 #ifdef DEBUG
3574     if (verbose)
3575     {
3576         printf("*************** In fgCreateGCPolls() for %s\n", info.compFullName);
3577     }
3578 #endif // DEBUG
3579
3580     if (!(opts.MinOpts() || opts.compDbgCode))
3581     {
3582         // Remove polls from well formed loops with a constant upper bound.
3583         for (unsigned lnum = 0; lnum < optLoopCount; ++lnum)
3584         {
3585             // Look for constant counted loops that run for a short duration.  This logic is very similar to
3586             // what's in code:Compiler::optUnrollLoops, since they have similar constraints.  However, this
3587             // logic is much more permissive since we're not doing a complex transformation.
3588
3589             /* TODO-Cleanup:
3590              * I feel bad cloning so much logic from optUnrollLoops
3591              */
3592
3593             // Filter out loops not meeting the obvious preconditions.
3594             //
3595             if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED)
3596             {
3597                 continue;
3598             }
3599
3600             if (!(optLoopTable[lnum].lpFlags & LPFLG_CONST))
3601             {
3602                 continue;
3603             }
3604
3605             BasicBlock* head   = optLoopTable[lnum].lpHead;
3606             BasicBlock* bottom = optLoopTable[lnum].lpBottom;
3607
3608             // Loops dominated by GC_SAFE_POINT won't have this set.
3609             if (!(bottom->bbFlags & BBF_NEEDS_GCPOLL))
3610             {
3611                 continue;
3612             }
3613
3614             /* Get the loop data:
3615                 - initial constant
3616                 - limit constant
3617                 - iterator
3618                 - iterator increment
3619                 - increment operation type (i.e. ASG_ADD, ASG_SUB, etc...)
3620                 - loop test type (i.e. GT_GE, GT_LT, etc...)
3621              */
3622
3623             int        lbeg     = optLoopTable[lnum].lpConstInit;
3624             int        llim     = optLoopTable[lnum].lpConstLimit();
3625             genTreeOps testOper = optLoopTable[lnum].lpTestOper();
3626
3627             int        lvar     = optLoopTable[lnum].lpIterVar();
3628             int        iterInc  = optLoopTable[lnum].lpIterConst();
3629             genTreeOps iterOper = optLoopTable[lnum].lpIterOper();
3630
3631             var_types iterOperType = optLoopTable[lnum].lpIterOperType();
3632             bool      unsTest      = (optLoopTable[lnum].lpTestTree->gtFlags & GTF_UNSIGNED) != 0;
3633             if (lvaTable[lvar].lvAddrExposed)
3634             { // Can't reason about the value of the iteration variable.
3635                 continue;
3636             }
3637
3638             unsigned totalIter;
3639
3640             /* Find the number of iterations - the function returns false if not a constant number */
3641
3642             if (!optComputeLoopRep(lbeg, llim, iterInc, iterOper, iterOperType, testOper, unsTest,
3643                                    // The value here doesn't matter for this variation of the optimization
3644                                    true, &totalIter))
3645             {
3646 #ifdef DEBUG
3647                 if (verbose)
3648                 {
3649                     printf("Could not compute loop iterations for loop from BB%02u to BB%02u", head->bbNum,
3650                            bottom->bbNum);
3651                 }
3652 #endif                      // DEBUG
3653                 (void)head; // suppress gcc error.
3654
3655                 continue;
3656             }
3657
3658             /* Forget it if there are too many repetitions or not a constant loop */
3659
3660             static const unsigned ITER_LIMIT = 256;
3661             if (totalIter > ITER_LIMIT)
3662             {
3663                 continue;
3664             }
3665
3666             // It is safe to elminate the poll from this loop.
3667             bottom->bbFlags &= ~BBF_NEEDS_GCPOLL;
3668
3669 #ifdef DEBUG
3670             if (verbose)
3671             {
3672                 printf("Removing poll in block BB%02u because it forms a bounded counted loop\n", bottom->bbNum);
3673             }
3674 #endif // DEBUG
3675         }
3676     }
3677
3678     // Final chance to optimize the polls.  Move all polls in loops from the bottom of the loop up to the
3679     // loop head.  Also eliminate all epilog polls in non-leaf methods.  This only works if we have dominator
3680     // information.
3681     if (fgDomsComputed)
3682     {
3683         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
3684         {
3685             if (!(block->bbFlags & BBF_NEEDS_GCPOLL))
3686             {
3687                 continue;
3688             }
3689
3690             if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
3691             {
3692                 // make sure that this is loop-like
3693                 if (!fgReachable(block->bbJumpDest, block))
3694                 {
3695                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3696 #ifdef DEBUG
3697                     if (verbose)
3698                     {
3699                         printf("Removing poll in block BB%02u because it is not loop\n", block->bbNum);
3700                     }
3701 #endif // DEBUG
3702                     continue;
3703                 }
3704             }
3705             else if (!(block->bbJumpKind == BBJ_RETURN || block->bbJumpKind == BBJ_SWITCH))
3706             {
3707                 noway_assert(!"GC Poll on a block that has no control transfer.");
3708 #ifdef DEBUG
3709                 if (verbose)
3710                 {
3711                     printf("Removing poll in block BB%02u because it is not a jump\n", block->bbNum);
3712                 }
3713 #endif // DEBUG
3714                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3715                 continue;
3716             }
3717
3718             // Because of block compaction, it's possible to end up with a block that is both poll and safe.
3719             // Clean those up now.
3720
3721             if (block->bbFlags & BBF_GC_SAFE_POINT)
3722             {
3723 #ifdef DEBUG
3724                 if (verbose)
3725                 {
3726                     printf("Removing poll in return block BB%02u because it is GC Safe\n", block->bbNum);
3727                 }
3728 #endif // DEBUG
3729                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3730                 continue;
3731             }
3732
3733             if (block->bbJumpKind == BBJ_RETURN)
3734             {
3735                 if (!optReachWithoutCall(fgFirstBB, block))
3736                 {
3737                     // check to see if there is a call along the path between the first block and the return
3738                     // block.
3739                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3740 #ifdef DEBUG
3741                     if (verbose)
3742                     {
3743                         printf("Removing poll in return block BB%02u because it dominated by a call\n", block->bbNum);
3744                     }
3745 #endif // DEBUG
3746                     continue;
3747                 }
3748             }
3749         }
3750     }
3751
3752     noway_assert(!fgGCPollsCreated);
3753     BasicBlock* block;
3754     fgGCPollsCreated = true;
3755
3756     // Walk through the blocks and hunt for a block that has BBF_NEEDS_GCPOLL
3757     for (block = fgFirstBB; block; block = block->bbNext)
3758     {
3759         // Because of block compaction, it's possible to end up with a block that is both poll and safe.
3760         // And if !fgDomsComputed, we won't have cleared them, so skip them now
3761         if (!(block->bbFlags & BBF_NEEDS_GCPOLL) || (block->bbFlags & BBF_GC_SAFE_POINT))
3762         {
3763             continue;
3764         }
3765
3766         // This block needs a poll.  We either just insert a callout or we split the block and inline part of
3767         // the test.  This depends on the value of opts.compGCPollType.
3768
3769         // If we're doing GCPOLL_CALL, just insert a GT_CALL node before the last node in the block.
3770         CLANG_FORMAT_COMMENT_ANCHOR;
3771
3772 #ifdef DEBUG
3773         switch (block->bbJumpKind)
3774         {
3775             case BBJ_RETURN:
3776             case BBJ_ALWAYS:
3777             case BBJ_COND:
3778             case BBJ_SWITCH:
3779                 break;
3780             default:
3781                 noway_assert(!"Unknown block type for BBF_NEEDS_GCPOLL");
3782         }
3783 #endif // DEBUG
3784
3785         noway_assert(opts.compGCPollType);
3786
3787         GCPollType pollType = opts.compGCPollType;
3788         // pollType is set to either CALL or INLINE at this point.  Below is the list of places where we
3789         // can't or don't want to emit an inline check.  Check all of those.  If after all of that we still
3790         // have INLINE, then emit an inline check.
3791
3792         if (opts.MinOpts() || opts.compDbgCode)
3793         {
3794 #ifdef DEBUG
3795             if (verbose)
3796             {
3797                 printf("Selecting CALL poll in block BB%02u because of debug/minopts\n", block->bbNum);
3798             }
3799 #endif // DEBUG
3800
3801             // Don't split blocks and create inlined polls unless we're optimizing.
3802             pollType = GCPOLL_CALL;
3803         }
3804         else if (genReturnBB == block)
3805         {
3806 #ifdef DEBUG
3807             if (verbose)
3808             {
3809                 printf("Selecting CALL poll in block BB%02u because it is the single return block\n", block->bbNum);
3810             }
3811 #endif // DEBUG
3812
3813             // we don't want to split the single return block
3814             pollType = GCPOLL_CALL;
3815         }
3816         else if (BBJ_SWITCH == block->bbJumpKind)
3817         {
3818 #ifdef DEBUG
3819             if (verbose)
3820             {
3821                 printf("Selecting CALL poll in block BB%02u because it is a loop formed by a SWITCH\n", block->bbNum);
3822             }
3823 #endif // DEBUG
3824
3825             // I don't want to deal with all the outgoing edges of a switch block.
3826             pollType = GCPOLL_CALL;
3827         }
3828
3829         // TODO-Cleanup: potentially don't split if we're in an EH region.
3830
3831         createdPollBlocks |= fgCreateGCPoll(pollType, block);
3832     }
3833
3834     // If we split a block to create a GC Poll, then rerun fgReorderBlocks to push the rarely run blocks out
3835     // past the epilog.  We should never split blocks unless we're optimizing.
3836     if (createdPollBlocks)
3837     {
3838         noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3839         fgReorderBlocks();
3840     }
3841 }
3842
3843 /*****************************************************************************
3844  *
3845  *  Actually create a GCPoll in the given block. Returns true if it created
3846  *  a basic block.
3847  */
3848
3849 bool Compiler::fgCreateGCPoll(GCPollType pollType, BasicBlock* block)
3850 {
3851     assert(!(block->bbFlags & BBF_GC_SAFE_POINT));
3852     bool createdPollBlocks;
3853
3854     void* addrTrap;
3855     void* pAddrOfCaptureThreadGlobal;
3856
3857     addrTrap = info.compCompHnd->getAddrOfCaptureThreadGlobal(&pAddrOfCaptureThreadGlobal);
3858
3859 #ifdef ENABLE_FAST_GCPOLL_HELPER
3860     // I never want to split blocks if we've got two indirections here.
3861     // This is a size trade-off assuming the VM has ENABLE_FAST_GCPOLL_HELPER.
3862     // So don't do it when that is off
3863     if (pAddrOfCaptureThreadGlobal != NULL)
3864     {
3865         pollType = GCPOLL_CALL;
3866     }
3867 #endif // ENABLE_FAST_GCPOLL_HELPER
3868
3869     if (GCPOLL_CALL == pollType)
3870     {
3871         createdPollBlocks = false;
3872         GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_POLL_GC, TYP_VOID);
3873
3874         // for BBJ_ALWAYS I don't need to insert it before the condition.  Just append it.
3875         if (block->bbJumpKind == BBJ_ALWAYS)
3876         {
3877             fgInsertStmtAtEnd(block, call);
3878         }
3879         else
3880         {
3881             GenTreeStmt* newStmt = fgInsertStmtNearEnd(block, call);
3882             // For DDB156656, we need to associate the GC Poll with the IL offset (and therefore sequence
3883             // point) of the tree before which we inserted the poll.  One example of when this is a
3884             // problem:
3885             //  if (...) {  //1
3886             //      ...
3887             //  } //2
3888             //  else { //3
3889             //      ...
3890             //  }
3891             //  (gcpoll) //4
3892             //  return. //5
3893             //
3894             //  If we take the if statement at 1, we encounter a jump at 2.  This jumps over the else
3895             //  and lands at 4.  4 is where we inserted the gcpoll.  However, that is associated with
3896             //  the sequence point a 3.  Therefore, the debugger displays the wrong source line at the
3897             //  gc poll location.
3898             //
3899             //  More formally, if control flow targets an instruction, that instruction must be the
3900             //  start of a new sequence point.
3901             if (newStmt->gtNext)
3902             {
3903                 // Is it possible for gtNext to be NULL?
3904                 noway_assert(newStmt->gtNext->gtOper == GT_STMT);
3905                 newStmt->gtStmtILoffsx = newStmt->gtNextStmt->gtStmtILoffsx;
3906             }
3907         }
3908
3909         block->bbFlags |= BBF_GC_SAFE_POINT;
3910 #ifdef DEBUG
3911         if (verbose)
3912         {
3913             printf("*** creating GC Poll in block BB%02u\n", block->bbNum);
3914             gtDispTreeList(block->bbTreeList);
3915         }
3916 #endif // DEBUG
3917     }
3918     else
3919     {
3920         createdPollBlocks = true;
3921         // if we're doing GCPOLL_INLINE, then:
3922         //  1) Create two new blocks: Poll and Bottom.  The original block is called Top.
3923
3924         // I want to create:
3925         // top -> poll -> bottom (lexically)
3926         // so that we jump over poll to get to bottom.
3927         BasicBlock* top         = block;
3928         BasicBlock* poll        = fgNewBBafter(BBJ_NONE, top, true);
3929         BasicBlock* bottom      = fgNewBBafter(top->bbJumpKind, poll, true);
3930         BBjumpKinds oldJumpKind = top->bbJumpKind;
3931
3932         // Update block flags
3933         const unsigned __int64 originalFlags = top->bbFlags | BBF_GC_SAFE_POINT;
3934
3935         // Unlike Fei's inliner from puclr, I'm allowed to split loops.
3936         // And we keep a few other flags...
3937         noway_assert((originalFlags & (BBF_SPLIT_NONEXIST & ~(BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1))) == 0);
3938         top->bbFlags = originalFlags & (~BBF_SPLIT_LOST | BBF_GC_SAFE_POINT);
3939         bottom->bbFlags |= originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT);
3940         bottom->inheritWeight(top);
3941         poll->bbFlags |= originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT);
3942
3943         //  9) Mark Poll as rarely run.
3944         poll->bbSetRunRarely();
3945
3946         //  5) Bottom gets all the outgoing edges and inherited flags of Original.
3947         bottom->bbJumpDest = top->bbJumpDest;
3948
3949         //  2) Add a GC_CALL node to Poll.
3950         GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_POLL_GC, TYP_VOID);
3951         fgInsertStmtAtEnd(poll, call);
3952
3953         //  3) Remove the last statement from Top and add it to Bottom.
3954         if (oldJumpKind != BBJ_ALWAYS)
3955         {
3956             // if I'm always jumping to the target, then this is not a condition that needs moving.
3957             GenTreeStmt* stmt = top->firstStmt();
3958             while (stmt->gtNext)
3959             {
3960                 stmt = stmt->gtNextStmt;
3961             }
3962             fgRemoveStmt(top, stmt);
3963             fgInsertStmtAtEnd(bottom, stmt);
3964         }
3965
3966         // for BBJ_ALWAYS blocks, bottom is an empty block.
3967
3968         //  4) Create a GT_EQ node that checks against g_TrapReturningThreads.  True jumps to Bottom,
3969         //  false falls through to poll.  Add this to the end of Top.  Top is now BBJ_COND.  Bottom is
3970         //  now a jump target
3971         CLANG_FORMAT_COMMENT_ANCHOR;
3972
3973 #ifdef ENABLE_FAST_GCPOLL_HELPER
3974         // Prefer the fast gc poll helepr over the double indirection
3975         noway_assert(pAddrOfCaptureThreadGlobal == nullptr);
3976 #endif
3977
3978         GenTree* value; // The value of g_TrapReturningThreads
3979         if (pAddrOfCaptureThreadGlobal != nullptr)
3980         {
3981             // Use a double indirection
3982             GenTree* addr =
3983                 gtNewIndOfIconHandleNode(TYP_I_IMPL, (size_t)pAddrOfCaptureThreadGlobal, GTF_ICON_PTR_HDL, true);
3984
3985             value = gtNewOperNode(GT_IND, TYP_INT, addr);
3986             // This indirection won't cause an exception.
3987             value->gtFlags |= GTF_IND_NONFAULTING;
3988         }
3989         else
3990         {
3991             // Use a single indirection
3992             value = gtNewIndOfIconHandleNode(TYP_INT, (size_t)addrTrap, GTF_ICON_PTR_HDL, false);
3993         }
3994
3995         // Treat the reading of g_TrapReturningThreads as volatile.
3996         value->gtFlags |= GTF_IND_VOLATILE;
3997
3998         // Compare for equal to zero
3999         GenTree* trapRelop = gtNewOperNode(GT_EQ, TYP_INT, value, gtNewIconNode(0, TYP_INT));
4000
4001         trapRelop->gtFlags |= GTF_RELOP_JMP_USED | GTF_DONT_CSE;
4002         GenTree* trapCheck = gtNewOperNode(GT_JTRUE, TYP_VOID, trapRelop);
4003         fgInsertStmtAtEnd(top, trapCheck);
4004         top->bbJumpDest = bottom;
4005         top->bbJumpKind = BBJ_COND;
4006         bottom->bbFlags |= BBF_JMP_TARGET;
4007
4008         //  7) Bottom has Top and Poll as its predecessors.  Poll has just Top as a predecessor.
4009         fgAddRefPred(bottom, poll);
4010         fgAddRefPred(bottom, top);
4011         fgAddRefPred(poll, top);
4012
4013         //  8) Replace Top with Bottom in the predecessor list of all outgoing edges from Bottom (1 for
4014         //      jumps, 2 for conditional branches, N for switches).
4015         switch (oldJumpKind)
4016         {
4017             case BBJ_RETURN:
4018                 // no successors
4019                 break;
4020             case BBJ_COND:
4021                 // replace predecessor in the fall through block.
4022                 noway_assert(bottom->bbNext);
4023                 fgReplacePred(bottom->bbNext, top, bottom);
4024
4025                 // fall through for the jump target
4026                 __fallthrough;
4027
4028             case BBJ_ALWAYS:
4029                 fgReplacePred(bottom->bbJumpDest, top, bottom);
4030                 break;
4031             case BBJ_SWITCH:
4032                 NO_WAY("SWITCH should be a call rather than an inlined poll.");
4033                 break;
4034             default:
4035                 NO_WAY("Unknown block type for updating predecessor lists.");
4036         }
4037
4038         top->bbFlags &= ~BBF_NEEDS_GCPOLL;
4039         noway_assert(!(poll->bbFlags & BBF_NEEDS_GCPOLL));
4040         noway_assert(!(bottom->bbFlags & BBF_NEEDS_GCPOLL));
4041
4042         if (compCurBB == top)
4043         {
4044             compCurBB = bottom;
4045         }
4046
4047 #ifdef DEBUG
4048         if (verbose)
4049         {
4050             printf("*** creating inlined GC Poll in top block BB%02u\n", top->bbNum);
4051             gtDispTreeList(top->bbTreeList);
4052             printf(" poll block is BB%02u\n", poll->bbNum);
4053             gtDispTreeList(poll->bbTreeList);
4054             printf(" bottom block is BB%02u\n", bottom->bbNum);
4055             gtDispTreeList(bottom->bbTreeList);
4056         }
4057 #endif // DEBUG
4058     }
4059
4060     return createdPollBlocks;
4061 }
4062
4063 /*****************************************************************************
4064  *
4065  *  The following helps find a basic block given its PC offset.
4066  */
4067
4068 void Compiler::fgInitBBLookup()
4069 {
4070     BasicBlock** dscBBptr;
4071     BasicBlock*  tmpBBdesc;
4072
4073     /* Allocate the basic block table */
4074
4075     dscBBptr = fgBBs = new (this, CMK_BasicBlock) BasicBlock*[fgBBcount];
4076
4077     /* Walk all the basic blocks, filling in the table */
4078
4079     for (tmpBBdesc = fgFirstBB; tmpBBdesc; tmpBBdesc = tmpBBdesc->bbNext)
4080     {
4081         *dscBBptr++ = tmpBBdesc;
4082     }
4083
4084     noway_assert(dscBBptr == fgBBs + fgBBcount);
4085 }
4086
4087 BasicBlock* Compiler::fgLookupBB(unsigned addr)
4088 {
4089     unsigned lo;
4090     unsigned hi;
4091
4092     /* Do a binary search */
4093
4094     for (lo = 0, hi = fgBBcount - 1;;)
4095     {
4096
4097     AGAIN:;
4098
4099         if (lo > hi)
4100         {
4101             break;
4102         }
4103
4104         unsigned    mid = (lo + hi) / 2;
4105         BasicBlock* dsc = fgBBs[mid];
4106
4107         // We introduce internal blocks for BBJ_CALLFINALLY. Skip over these.
4108
4109         while (dsc->bbFlags & BBF_INTERNAL)
4110         {
4111             dsc = dsc->bbNext;
4112             mid++;
4113
4114             // We skipped over too many, Set hi back to the original mid - 1
4115
4116             if (mid > hi)
4117             {
4118                 mid = (lo + hi) / 2;
4119                 hi  = mid - 1;
4120                 goto AGAIN;
4121             }
4122         }
4123
4124         unsigned pos = dsc->bbCodeOffs;
4125
4126         if (pos < addr)
4127         {
4128             if ((lo == hi) && (lo == (fgBBcount - 1)))
4129             {
4130                 noway_assert(addr == dsc->bbCodeOffsEnd);
4131                 return nullptr; // NULL means the end of method
4132             }
4133             lo = mid + 1;
4134             continue;
4135         }
4136
4137         if (pos > addr)
4138         {
4139             hi = mid - 1;
4140             continue;
4141         }
4142
4143         return dsc;
4144     }
4145 #ifdef DEBUG
4146     printf("ERROR: Couldn't find basic block at offset %04X\n", addr);
4147 #endif // DEBUG
4148     NO_WAY("fgLookupBB failed.");
4149 }
4150
4151 /*****************************************************************************
4152  *
4153  *  The 'jump target' array uses the following flags to indicate what kind
4154  *  of label is present.
4155  */
4156
4157 #define JT_NONE 0x00  // This IL offset is never used
4158 #define JT_ADDR 0x01  // merely make sure this is an OK address
4159 #define JT_JUMP 0x02  // 'normal' jump target
4160 #define JT_MULTI 0x04 // target of multiple jumps
4161
4162 inline void Compiler::fgMarkJumpTarget(BYTE* jumpTarget, unsigned offs)
4163 {
4164     /* Make sure we set JT_MULTI if target of multiple jumps */
4165
4166     noway_assert(JT_MULTI == JT_JUMP << 1);
4167
4168     jumpTarget[offs] |= (jumpTarget[offs] & JT_JUMP) << 1 | JT_JUMP;
4169 }
4170
4171 //------------------------------------------------------------------------
4172 // FgStack: simple stack model for the inlinee's evaluation stack.
4173 //
4174 // Model the inputs available to various operations in the inline body.
4175 // Tracks constants, arguments, array lengths.
4176
4177 class FgStack
4178 {
4179 public:
4180     FgStack() : slot0(SLOT_INVALID), slot1(SLOT_INVALID), depth(0)
4181     {
4182         // Empty
4183     }
4184
4185     void Clear()
4186     {
4187         depth = 0;
4188     }
4189     void PushUnknown()
4190     {
4191         Push(SLOT_UNKNOWN);
4192     }
4193     void PushConstant()
4194     {
4195         Push(SLOT_CONSTANT);
4196     }
4197     void PushArrayLen()
4198     {
4199         Push(SLOT_ARRAYLEN);
4200     }
4201     void PushArgument(unsigned arg)
4202     {
4203         Push(SLOT_ARGUMENT + arg);
4204     }
4205     unsigned GetSlot0() const
4206     {
4207         assert(depth >= 1);
4208         return slot0;
4209     }
4210     unsigned GetSlot1() const
4211     {
4212         assert(depth >= 2);
4213         return slot1;
4214     }
4215     static bool IsConstant(unsigned value)
4216     {
4217         return value == SLOT_CONSTANT;
4218     }
4219     static bool IsArrayLen(unsigned value)
4220     {
4221         return value == SLOT_ARRAYLEN;
4222     }
4223     static bool IsArgument(unsigned value)
4224     {
4225         return value >= SLOT_ARGUMENT;
4226     }
4227     static unsigned SlotTypeToArgNum(unsigned value)
4228     {
4229         assert(IsArgument(value));
4230         return value - SLOT_ARGUMENT;
4231     }
4232     bool IsStackTwoDeep() const
4233     {
4234         return depth == 2;
4235     }
4236     bool IsStackOneDeep() const
4237     {
4238         return depth == 1;
4239     }
4240     bool IsStackAtLeastOneDeep() const
4241     {
4242         return depth >= 1;
4243     }
4244
4245 private:
4246     enum
4247     {
4248         SLOT_INVALID  = UINT_MAX,
4249         SLOT_UNKNOWN  = 0,
4250         SLOT_CONSTANT = 1,
4251         SLOT_ARRAYLEN = 2,
4252         SLOT_ARGUMENT = 3
4253     };
4254
4255     void Push(int type)
4256     {
4257         switch (depth)
4258         {
4259             case 0:
4260                 ++depth;
4261                 slot0 = type;
4262                 break;
4263             case 1:
4264                 ++depth;
4265                 __fallthrough;
4266             case 2:
4267                 slot1 = slot0;
4268                 slot0 = type;
4269         }
4270     }
4271
4272     unsigned slot0;
4273     unsigned slot1;
4274     unsigned depth;
4275 };
4276
4277 //------------------------------------------------------------------------
4278 // fgFindJumpTargets: walk the IL stream, determining jump target offsets
4279 //
4280 // Arguments:
4281 //    codeAddr   - base address of the IL code buffer
4282 //    codeSize   - number of bytes in the IL code buffer
4283 //    jumpTarget - [OUT] byte array for flagging jump targets
4284 //
4285 // Notes:
4286 //    If inlining or prejitting the root, this method also makes
4287 //    various observations about the method that factor into inline
4288 //    decisions.
4289 //
4290 //    May throw an exception if the IL is malformed.
4291 //
4292 //    jumpTarget[N] is set to a JT_* value if IL offset N is a
4293 //    jump target in the method.
4294 //
4295 //    Also sets lvAddrExposed and lvHasILStoreOp, ilHasMultipleILStoreOp in lvaTable[].
4296
4297 #ifdef _PREFAST_
4298 #pragma warning(push)
4299 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
4300 #endif
4301
4302 void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget)
4303 {
4304     const BYTE* codeBegp = codeAddr;
4305     const BYTE* codeEndp = codeAddr + codeSize;
4306     unsigned    varNum;
4307     bool        seenJump = false;
4308     var_types   varType  = DUMMY_INIT(TYP_UNDEF); // TYP_ type
4309     typeInfo    ti;                               // Verifier type.
4310     bool        typeIsNormed = false;
4311     FgStack     pushedStack;
4312     const bool  isForceInline          = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0;
4313     const bool  makeInlineObservations = (compInlineResult != nullptr);
4314     const bool  isInlining             = compIsForInlining();
4315     unsigned    retBlocks              = 0;
4316
4317     if (makeInlineObservations)
4318     {
4319         // Observe force inline state and code size.
4320         compInlineResult->NoteBool(InlineObservation::CALLEE_IS_FORCE_INLINE, isForceInline);
4321         compInlineResult->NoteInt(InlineObservation::CALLEE_IL_CODE_SIZE, codeSize);
4322
4323         // Determine if call site is within a try.
4324         if (isInlining && impInlineInfo->iciBlock->hasTryIndex())
4325         {
4326             compInlineResult->Note(InlineObservation::CALLSITE_IN_TRY_REGION);
4327         }
4328
4329         // Determine if the call site is in a loop.
4330         if (isInlining && ((impInlineInfo->iciBlock->bbFlags & BBF_BACKWARD_JUMP) != 0))
4331         {
4332             compInlineResult->Note(InlineObservation::CALLSITE_IN_LOOP);
4333         }
4334
4335 #ifdef DEBUG
4336
4337         // If inlining, this method should still be a candidate.
4338         if (isInlining)
4339         {
4340             assert(compInlineResult->IsCandidate());
4341         }
4342
4343 #endif // DEBUG
4344
4345         // note that we're starting to look at the opcodes.
4346         compInlineResult->Note(InlineObservation::CALLEE_BEGIN_OPCODE_SCAN);
4347     }
4348
4349     while (codeAddr < codeEndp)
4350     {
4351         OPCODE opcode = (OPCODE)getU1LittleEndian(codeAddr);
4352         codeAddr += sizeof(__int8);
4353         opts.instrCount++;
4354         typeIsNormed = false;
4355
4356     DECODE_OPCODE:
4357
4358         if ((unsigned)opcode >= CEE_COUNT)
4359         {
4360             BADCODE3("Illegal opcode", ": %02X", (int)opcode);
4361         }
4362
4363         if ((opcode >= CEE_LDARG_0 && opcode <= CEE_STLOC_S) || (opcode >= CEE_LDARG && opcode <= CEE_STLOC))
4364         {
4365             opts.lvRefCount++;
4366         }
4367
4368         if (makeInlineObservations && (opcode >= CEE_LDNULL) && (opcode <= CEE_LDC_R8))
4369         {
4370             pushedStack.PushConstant();
4371         }
4372
4373         unsigned sz = opcodeSizes[opcode];
4374
4375         switch (opcode)
4376         {
4377             case CEE_PREFIX1:
4378             {
4379                 if (codeAddr >= codeEndp)
4380                 {
4381                     goto TOO_FAR;
4382                 }
4383                 opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr));
4384                 codeAddr += sizeof(__int8);
4385                 goto DECODE_OPCODE;
4386             }
4387
4388             case CEE_PREFIX2:
4389             case CEE_PREFIX3:
4390             case CEE_PREFIX4:
4391             case CEE_PREFIX5:
4392             case CEE_PREFIX6:
4393             case CEE_PREFIX7:
4394             case CEE_PREFIXREF:
4395             {
4396                 BADCODE3("Illegal opcode", ": %02X", (int)opcode);
4397             }
4398
4399             case CEE_CALL:
4400             case CEE_CALLVIRT:
4401             {
4402                 // There has to be code after the call, otherwise the inlinee is unverifiable.
4403                 if (isInlining)
4404                 {
4405
4406                     noway_assert(codeAddr < codeEndp - sz);
4407                 }
4408
4409                 // If the method has a call followed by a ret, assume that
4410                 // it is a wrapper method.
4411                 if (makeInlineObservations)
4412                 {
4413                     if ((OPCODE)getU1LittleEndian(codeAddr + sz) == CEE_RET)
4414                     {
4415                         compInlineResult->Note(InlineObservation::CALLEE_LOOKS_LIKE_WRAPPER);
4416                     }
4417                 }
4418             }
4419             break;
4420
4421             case CEE_LEAVE:
4422             case CEE_LEAVE_S:
4423             case CEE_BR:
4424             case CEE_BR_S:
4425             case CEE_BRFALSE:
4426             case CEE_BRFALSE_S:
4427             case CEE_BRTRUE:
4428             case CEE_BRTRUE_S:
4429             case CEE_BEQ:
4430             case CEE_BEQ_S:
4431             case CEE_BGE:
4432             case CEE_BGE_S:
4433             case CEE_BGE_UN:
4434             case CEE_BGE_UN_S:
4435             case CEE_BGT:
4436             case CEE_BGT_S:
4437             case CEE_BGT_UN:
4438             case CEE_BGT_UN_S:
4439             case CEE_BLE:
4440             case CEE_BLE_S:
4441             case CEE_BLE_UN:
4442             case CEE_BLE_UN_S:
4443             case CEE_BLT:
4444             case CEE_BLT_S:
4445             case CEE_BLT_UN:
4446             case CEE_BLT_UN_S:
4447             case CEE_BNE_UN:
4448             case CEE_BNE_UN_S:
4449             {
4450                 seenJump = true;
4451
4452                 if (codeAddr > codeEndp - sz)
4453                 {
4454                     goto TOO_FAR;
4455                 }
4456
4457                 // Compute jump target address
4458                 signed jmpDist = (sz == 1) ? getI1LittleEndian(codeAddr) : getI4LittleEndian(codeAddr);
4459
4460                 if (compIsForInlining() && jmpDist == 0 &&
4461                     (opcode == CEE_LEAVE || opcode == CEE_LEAVE_S || opcode == CEE_BR || opcode == CEE_BR_S))
4462                 {
4463                     break; /* NOP */
4464                 }
4465
4466                 unsigned jmpAddr = (IL_OFFSET)(codeAddr - codeBegp) + sz + jmpDist;
4467
4468                 // Make sure target is reasonable
4469                 if (jmpAddr >= codeSize)
4470                 {
4471                     BADCODE3("code jumps to outer space", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4472                 }
4473
4474                 // Mark the jump target
4475                 fgMarkJumpTarget(jumpTarget, jmpAddr);
4476
4477                 // See if jump might be sensitive to inlining
4478                 if (makeInlineObservations && (opcode != CEE_BR_S) && (opcode != CEE_BR))
4479                 {
4480                     fgObserveInlineConstants(opcode, pushedStack, isInlining);
4481                 }
4482             }
4483             break;
4484
4485             case CEE_SWITCH:
4486             {
4487                 seenJump = true;
4488
4489                 if (makeInlineObservations)
4490                 {
4491                     compInlineResult->Note(InlineObservation::CALLEE_HAS_SWITCH);
4492
4493                     // Fail fast, if we're inlining and can't handle this.
4494                     if (isInlining && compInlineResult->IsFailure())
4495                     {
4496                         return;
4497                     }
4498                 }
4499
4500                 // Make sure we don't go past the end reading the number of cases
4501                 if (codeAddr > codeEndp - sizeof(DWORD))
4502                 {
4503                     goto TOO_FAR;
4504                 }
4505
4506                 // Read the number of cases
4507                 unsigned jmpCnt = getU4LittleEndian(codeAddr);
4508                 codeAddr += sizeof(DWORD);
4509
4510                 if (jmpCnt > codeSize / sizeof(DWORD))
4511                 {
4512                     goto TOO_FAR;
4513                 }
4514
4515                 // Find the end of the switch table
4516                 unsigned jmpBase = (unsigned)((codeAddr - codeBegp) + jmpCnt * sizeof(DWORD));
4517
4518                 // Make sure there is more code after the switch
4519                 if (jmpBase >= codeSize)
4520                 {
4521                     goto TOO_FAR;
4522                 }
4523
4524                 // jmpBase is also the target of the default case, so mark it
4525                 fgMarkJumpTarget(jumpTarget, jmpBase);
4526
4527                 // Process table entries
4528                 while (jmpCnt > 0)
4529                 {
4530                     unsigned jmpAddr = jmpBase + getI4LittleEndian(codeAddr);
4531                     codeAddr += 4;
4532
4533                     if (jmpAddr >= codeSize)
4534                     {
4535                         BADCODE3("jump target out of range", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4536                     }
4537
4538                     fgMarkJumpTarget(jumpTarget, jmpAddr);
4539                     jmpCnt--;
4540                 }
4541
4542                 // We've advanced past all the bytes in this instruction
4543                 sz = 0;
4544             }
4545             break;
4546
4547             case CEE_UNALIGNED:
4548             case CEE_CONSTRAINED:
4549             case CEE_READONLY:
4550             case CEE_VOLATILE:
4551             case CEE_TAILCALL:
4552             {
4553                 if (codeAddr >= codeEndp)
4554                 {
4555                     goto TOO_FAR;
4556                 }
4557             }
4558             break;
4559
4560             case CEE_STARG:
4561             case CEE_STARG_S:
4562             {
4563                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4564
4565                 if (codeAddr > codeEndp - sz)
4566                 {
4567                     goto TOO_FAR;
4568                 }
4569
4570                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4571
4572                 if (isInlining)
4573                 {
4574                     if (varNum < impInlineInfo->argCnt)
4575                     {
4576                         impInlineInfo->inlArgInfo[varNum].argHasStargOp = true;
4577                     }
4578                 }
4579                 else
4580                 {
4581                     // account for possible hidden param
4582                     varNum = compMapILargNum(varNum);
4583
4584                     // This check is only intended to prevent an AV.  Bad varNum values will later
4585                     // be handled properly by the verifier.
4586                     if (varNum < lvaTableCnt)
4587                     {
4588                         // In non-inline cases, note written-to arguments.
4589                         lvaTable[varNum].lvHasILStoreOp = 1;
4590                     }
4591                 }
4592             }
4593             break;
4594
4595             case CEE_STLOC_0:
4596             case CEE_STLOC_1:
4597             case CEE_STLOC_2:
4598             case CEE_STLOC_3:
4599                 varNum = (opcode - CEE_STLOC_0);
4600                 goto STLOC;
4601
4602             case CEE_STLOC:
4603             case CEE_STLOC_S:
4604             {
4605                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4606
4607                 if (codeAddr > codeEndp - sz)
4608                 {
4609                     goto TOO_FAR;
4610                 }
4611
4612                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4613
4614             STLOC:
4615                 if (isInlining)
4616                 {
4617                     InlLclVarInfo& lclInfo = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt];
4618
4619                     if (lclInfo.lclHasStlocOp)
4620                     {
4621                         lclInfo.lclHasMultipleStlocOp = 1;
4622                     }
4623                     else
4624                     {
4625                         lclInfo.lclHasStlocOp = 1;
4626                     }
4627                 }
4628                 else
4629                 {
4630                     varNum += info.compArgsCount;
4631
4632                     // This check is only intended to prevent an AV.  Bad varNum values will later
4633                     // be handled properly by the verifier.
4634                     if (varNum < lvaTableCnt)
4635                     {
4636                         // In non-inline cases, note written-to locals.
4637                         if (lvaTable[varNum].lvHasILStoreOp)
4638                         {
4639                             lvaTable[varNum].lvHasMultipleILStoreOp = 1;
4640                         }
4641                         else
4642                         {
4643                             lvaTable[varNum].lvHasILStoreOp = 1;
4644                         }
4645                     }
4646                 }
4647             }
4648             break;
4649
4650             case CEE_LDARGA:
4651             case CEE_LDARGA_S:
4652             case CEE_LDLOCA:
4653             case CEE_LDLOCA_S:
4654             {
4655                 // Handle address-taken args or locals
4656                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4657
4658                 if (codeAddr > codeEndp - sz)
4659                 {
4660                     goto TOO_FAR;
4661                 }
4662
4663                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4664
4665                 if (isInlining)
4666                 {
4667                     if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
4668                     {
4669                         varType = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclTypeInfo;
4670                         ti      = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclVerTypeInfo;
4671
4672                         impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclHasLdlocaOp = true;
4673                     }
4674                     else
4675                     {
4676                         noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
4677
4678                         varType = impInlineInfo->lclVarInfo[varNum].lclTypeInfo;
4679                         ti      = impInlineInfo->lclVarInfo[varNum].lclVerTypeInfo;
4680
4681                         impInlineInfo->inlArgInfo[varNum].argHasLdargaOp = true;
4682
4683                         pushedStack.PushArgument(varNum);
4684                     }
4685                 }
4686                 else
4687                 {
4688                     if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
4689                     {
4690                         if (varNum >= info.compMethodInfo->locals.numArgs)
4691                         {
4692                             BADCODE("bad local number");
4693                         }
4694
4695                         varNum += info.compArgsCount;
4696                     }
4697                     else
4698                     {
4699                         noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
4700
4701                         if (varNum >= info.compILargsCount)
4702                         {
4703                             BADCODE("bad argument number");
4704                         }
4705
4706                         varNum = compMapILargNum(varNum); // account for possible hidden param
4707                     }
4708
4709                     varType = (var_types)lvaTable[varNum].lvType;
4710                     ti      = lvaTable[varNum].lvVerTypeInfo;
4711
4712                     // Determine if the next instruction will consume
4713                     // the address. If so we won't mark this var as
4714                     // address taken.
4715                     //
4716                     // We will put structs on the stack and changing
4717                     // the addrTaken of a local requires an extra pass
4718                     // in the morpher so we won't apply this
4719                     // optimization to structs.
4720                     //
4721                     // Debug code spills for every IL instruction, and
4722                     // therefore it will split statements, so we will
4723                     // need the address.  Note that this optimization
4724                     // is based in that we know what trees we will
4725                     // generate for this ldfld, and we require that we
4726                     // won't need the address of this local at all
4727                     noway_assert(varNum < lvaTableCnt);
4728
4729                     const bool notStruct    = !varTypeIsStruct(&lvaTable[varNum]);
4730                     const bool notLastInstr = (codeAddr < codeEndp - sz);
4731                     const bool notDebugCode = !opts.compDbgCode;
4732
4733                     if (notStruct && notLastInstr && notDebugCode &&
4734                         impILConsumesAddr(codeAddr + sz, impTokenLookupContextHandle, info.compScopeHnd))
4735                     {
4736                         // We can skip the addrtaken, as next IL instruction consumes
4737                         // the address.
4738                     }
4739                     else
4740                     {
4741                         lvaTable[varNum].lvHasLdAddrOp = 1;
4742                         if (!info.compIsStatic && (varNum == 0))
4743                         {
4744                             // Addr taken on "this" pointer is significant,
4745                             // go ahead to mark it as permanently addr-exposed here.
4746                             lvaSetVarAddrExposed(0);
4747                             // This may be conservative, but probably not very.
4748                         }
4749                     }
4750                 } // isInlining
4751
4752                 typeIsNormed = ti.IsValueClass() && !varTypeIsStruct(varType);
4753             }
4754             break;
4755
4756             case CEE_CALLI:
4757
4758                 // CEE_CALLI should not be inlined if the call indirect target has a calling convention other than
4759                 // CORINFO_CALLCONV_DEFAULT. In the case where we have a no-marshal CALLI P/Invoke we end up calling
4760                 // the IL stub. We don't NGEN these stubs, so we'll have to JIT an IL stub for a trivial func.
4761                 // It's almost certainly a better choice to leave out the inline candidate so we can generate an inlined
4762                 // call frame.
4763
4764                 // Consider skipping this bail-out for force inlines.
4765                 if (makeInlineObservations)
4766                 {
4767                     if (codeAddr > codeEndp - sizeof(DWORD))
4768                     {
4769                         goto TOO_FAR;
4770                     }
4771
4772                     CORINFO_SIG_INFO calliSig;
4773                     eeGetSig(getU4LittleEndian(codeAddr), info.compScopeHnd, impTokenLookupContextHandle, &calliSig);
4774
4775                     if (calliSig.getCallConv() != CORINFO_CALLCONV_DEFAULT)
4776                     {
4777                         compInlineResult->Note(InlineObservation::CALLEE_UNSUPPORTED_OPCODE);
4778
4779                         // Fail fast if we're inlining
4780                         if (isInlining)
4781                         {
4782                             assert(compInlineResult->IsFailure());
4783                             return;
4784                         }
4785                     }
4786                 }
4787                 break;
4788
4789             case CEE_JMP:
4790                 retBlocks++;
4791
4792 #if !defined(_TARGET_X86_) && !defined(_TARGET_ARM_)
4793                 if (!isInlining)
4794                 {
4795                     // We transform this into a set of ldarg's + tail call and
4796                     // thus may push more onto the stack than originally thought.
4797                     // This doesn't interfere with verification because CEE_JMP
4798                     // is never verifiable, and there's nothing unsafe you can
4799                     // do with a an IL stack overflow if the JIT is expecting it.
4800                     info.compMaxStack = max(info.compMaxStack, info.compILargsCount);
4801                     break;
4802                 }
4803 #endif // !_TARGET_X86_ && !_TARGET_ARM_
4804
4805                 // If we are inlining, we need to fail for a CEE_JMP opcode, just like
4806                 // the list of other opcodes (for all platforms).
4807
4808                 __fallthrough;
4809             case CEE_MKREFANY:
4810             case CEE_RETHROW:
4811                 if (makeInlineObservations)
4812                 {
4813                     // Arguably this should be NoteFatal, but the legacy behavior is
4814                     // to ignore this for the prejit root.
4815                     compInlineResult->Note(InlineObservation::CALLEE_UNSUPPORTED_OPCODE);
4816
4817                     // Fail fast if we're inlining...
4818                     if (isInlining)
4819                     {
4820                         assert(compInlineResult->IsFailure());
4821                         return;
4822                     }
4823                 }
4824                 break;
4825
4826             case CEE_LOCALLOC:
4827
4828                 // We now allow localloc callees to become candidates in some cases.
4829                 if (makeInlineObservations)
4830                 {
4831                     compInlineResult->Note(InlineObservation::CALLEE_HAS_LOCALLOC);
4832                     if (isInlining && compInlineResult->IsFailure())
4833                     {
4834                         return;
4835                     }
4836                 }
4837                 break;
4838
4839             case CEE_LDARG_0:
4840             case CEE_LDARG_1:
4841             case CEE_LDARG_2:
4842             case CEE_LDARG_3:
4843                 if (makeInlineObservations)
4844                 {
4845                     pushedStack.PushArgument(opcode - CEE_LDARG_0);
4846                 }
4847                 break;
4848
4849             case CEE_LDARG_S:
4850             case CEE_LDARG:
4851             {
4852                 if (codeAddr > codeEndp - sz)
4853                 {
4854                     goto TOO_FAR;
4855                 }
4856
4857                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4858
4859                 if (makeInlineObservations)
4860                 {
4861                     pushedStack.PushArgument(varNum);
4862                 }
4863             }
4864             break;
4865
4866             case CEE_LDLEN:
4867                 if (makeInlineObservations)
4868                 {
4869                     pushedStack.PushArrayLen();
4870                 }
4871                 break;
4872
4873             case CEE_CEQ:
4874             case CEE_CGT:
4875             case CEE_CGT_UN:
4876             case CEE_CLT:
4877             case CEE_CLT_UN:
4878                 if (makeInlineObservations)
4879                 {
4880                     fgObserveInlineConstants(opcode, pushedStack, isInlining);
4881                 }
4882                 break;
4883             case CEE_RET:
4884                 retBlocks++;
4885
4886             default:
4887                 break;
4888         }
4889
4890         // Skip any remaining operands this opcode may have
4891         codeAddr += sz;
4892
4893         // Note the opcode we just saw
4894         if (makeInlineObservations)
4895         {
4896             InlineObservation obs =
4897                 typeIsNormed ? InlineObservation::CALLEE_OPCODE_NORMED : InlineObservation::CALLEE_OPCODE;
4898             compInlineResult->NoteInt(obs, opcode);
4899         }
4900     }
4901
4902     if (codeAddr != codeEndp)
4903     {
4904     TOO_FAR:
4905         BADCODE3("Code ends in the middle of an opcode, or there is a branch past the end of the method",
4906                  " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4907     }
4908
4909     if (makeInlineObservations)
4910     {
4911         compInlineResult->Note(InlineObservation::CALLEE_END_OPCODE_SCAN);
4912
4913         // If there are no return blocks we know it does not return, however if there
4914         // return blocks we don't know it returns as it may be counting unreachable code.
4915         // However we will still make the CALLEE_DOES_NOT_RETURN observation.
4916
4917         compInlineResult->NoteBool(InlineObservation::CALLEE_DOES_NOT_RETURN, retBlocks == 0);
4918
4919         if (retBlocks == 0 && isInlining)
4920         {
4921             // Mark the call node as "no return" as it can impact caller's code quality.
4922             impInlineInfo->iciCall->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN;
4923         }
4924
4925         // If the inline is viable and discretionary, do the
4926         // profitability screening.
4927         if (compInlineResult->IsDiscretionaryCandidate())
4928         {
4929             // Make some callsite specific observations that will feed
4930             // into the profitability model.
4931             impMakeDiscretionaryInlineObservations(impInlineInfo, compInlineResult);
4932
4933             // None of those observations should have changed the
4934             // inline's viability.
4935             assert(compInlineResult->IsCandidate());
4936
4937             if (isInlining)
4938             {
4939                 // Assess profitability...
4940                 CORINFO_METHOD_INFO* methodInfo = &impInlineInfo->inlineCandidateInfo->methInfo;
4941                 compInlineResult->DetermineProfitability(methodInfo);
4942
4943                 if (compInlineResult->IsFailure())
4944                 {
4945                     impInlineRoot()->m_inlineStrategy->NoteUnprofitable();
4946                     JITDUMP("\n\nInline expansion aborted, inline not profitable\n");
4947                     return;
4948                 }
4949                 else
4950                 {
4951                     // The inline is still viable.
4952                     assert(compInlineResult->IsCandidate());
4953                 }
4954             }
4955             else
4956             {
4957                 // Prejit root case. Profitability assessment for this
4958                 // is done over in compCompileHelper.
4959             }
4960         }
4961     }
4962
4963     // None of the local vars in the inlinee should have address taken or been written to.
4964     // Therefore we should NOT need to enter this "if" statement.
4965     if (!isInlining && !info.compIsStatic)
4966     {
4967         fgAdjustForAddressExposedOrWrittenThis();
4968     }
4969 }
4970
4971 #ifdef _PREFAST_
4972 #pragma warning(pop)
4973 #endif
4974
4975 //------------------------------------------------------------------------
4976 // fgAdjustForAddressExposedOrWrittenThis: update var table for cases
4977 //   where the this pointer value can change.
4978 //
4979 // Notes:
4980 //    Modifies lvaArg0Var to refer to a temp if the value of 'this' can
4981 //    change. The original this (info.compThisArg) then remains
4982 //    unmodified in the method.  fgAddInternal is reponsible for
4983 //    adding the code to copy the initial this into the temp.
4984
4985 void Compiler::fgAdjustForAddressExposedOrWrittenThis()
4986 {
4987     // Optionally enable adjustment during stress.
4988     if (!tiVerificationNeeded && compStressCompile(STRESS_GENERIC_VARN, 15))
4989     {
4990         lvaTable[info.compThisArg].lvHasILStoreOp = true;
4991     }
4992
4993     // If this is exposed or written to, create a temp for the modifiable this
4994     if (lvaTable[info.compThisArg].lvAddrExposed || lvaTable[info.compThisArg].lvHasILStoreOp)
4995     {
4996         // If there is a "ldarga 0" or "starg 0", grab and use the temp.
4997         lvaArg0Var = lvaGrabTemp(false DEBUGARG("Address-exposed, or written this pointer"));
4998         noway_assert(lvaArg0Var > (unsigned)info.compThisArg);
4999         lvaTable[lvaArg0Var].lvType            = lvaTable[info.compThisArg].TypeGet();
5000         lvaTable[lvaArg0Var].lvAddrExposed     = lvaTable[info.compThisArg].lvAddrExposed;
5001         lvaTable[lvaArg0Var].lvDoNotEnregister = lvaTable[info.compThisArg].lvDoNotEnregister;
5002 #ifdef DEBUG
5003         lvaTable[lvaArg0Var].lvVMNeedsStackAddr = lvaTable[info.compThisArg].lvVMNeedsStackAddr;
5004         lvaTable[lvaArg0Var].lvLiveInOutOfHndlr = lvaTable[info.compThisArg].lvLiveInOutOfHndlr;
5005         lvaTable[lvaArg0Var].lvLclFieldExpr     = lvaTable[info.compThisArg].lvLclFieldExpr;
5006         lvaTable[lvaArg0Var].lvLiveAcrossUCall  = lvaTable[info.compThisArg].lvLiveAcrossUCall;
5007 #endif
5008         lvaTable[lvaArg0Var].lvHasILStoreOp = lvaTable[info.compThisArg].lvHasILStoreOp;
5009         lvaTable[lvaArg0Var].lvVerTypeInfo  = lvaTable[info.compThisArg].lvVerTypeInfo;
5010
5011         // Clear the TI_FLAG_THIS_PTR in the original 'this' pointer.
5012         noway_assert(lvaTable[lvaArg0Var].lvVerTypeInfo.IsThisPtr());
5013         lvaTable[info.compThisArg].lvVerTypeInfo.ClearThisPtr();
5014         lvaTable[info.compThisArg].lvAddrExposed  = false;
5015         lvaTable[info.compThisArg].lvHasILStoreOp = false;
5016     }
5017 }
5018
5019 //------------------------------------------------------------------------
5020 // fgObserveInlineConstants: look for operations that might get optimized
5021 //   if this method were to be inlined, and report these to the inliner.
5022 //
5023 // Arguments:
5024 //    opcode     -- MSIL opcode under consideration
5025 //    stack      -- abstract stack model at this point in the IL
5026 //    isInlining -- true if we're inlining (vs compiling a prejit root)
5027 //
5028 // Notes:
5029 //    Currently only invoked on compare and branch opcodes.
5030 //
5031 //    If we're inlining we also look at the argument values supplied by
5032 //    the caller at this call site.
5033 //
5034 //    The crude stack model may overestimate stack depth.
5035
5036 void Compiler::fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, bool isInlining)
5037 {
5038     // We should be able to record inline observations.
5039     assert(compInlineResult != nullptr);
5040
5041     // The stack only has to be 1 deep for BRTRUE/FALSE
5042     bool lookForBranchCases = stack.IsStackAtLeastOneDeep();
5043
5044     if (lookForBranchCases)
5045     {
5046         if (opcode == CEE_BRFALSE || opcode == CEE_BRFALSE_S || opcode == CEE_BRTRUE || opcode == CEE_BRTRUE_S)
5047         {
5048             unsigned slot0 = stack.GetSlot0();
5049             if (FgStack::IsArgument(slot0))
5050             {
5051                 compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST);
5052
5053                 if (isInlining)
5054                 {
5055                     // Check for the double whammy of an incoming constant argument
5056                     // feeding a constant test.
5057                     unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
5058                     if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5059                     {
5060                         compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5061                     }
5062                 }
5063             }
5064
5065             return;
5066         }
5067     }
5068
5069     // Remaining cases require at least two things on the stack.
5070     if (!stack.IsStackTwoDeep())
5071     {
5072         return;
5073     }
5074
5075     unsigned slot0 = stack.GetSlot0();
5076     unsigned slot1 = stack.GetSlot1();
5077
5078     // Arg feeds constant test
5079     if ((FgStack::IsConstant(slot0) && FgStack::IsArgument(slot1)) ||
5080         (FgStack::IsConstant(slot1) && FgStack::IsArgument(slot0)))
5081     {
5082         compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST);
5083     }
5084
5085     // Arg feeds range check
5086     if ((FgStack::IsArrayLen(slot0) && FgStack::IsArgument(slot1)) ||
5087         (FgStack::IsArrayLen(slot1) && FgStack::IsArgument(slot0)))
5088     {
5089         compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_RANGE_CHECK);
5090     }
5091
5092     // Check for an incoming arg that's a constant
5093     if (isInlining)
5094     {
5095         if (FgStack::IsArgument(slot0))
5096         {
5097             compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_TEST);
5098
5099             unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
5100             if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5101             {
5102                 compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5103             }
5104         }
5105
5106         if (FgStack::IsArgument(slot1))
5107         {
5108             compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_TEST);
5109
5110             unsigned varNum = FgStack::SlotTypeToArgNum(slot1);
5111             if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
5112             {
5113                 compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
5114             }
5115         }
5116     }
5117 }
5118
5119 /*****************************************************************************
5120  *
5121  *  Finally link up the bbJumpDest of the blocks together
5122  */
5123
5124 void Compiler::fgMarkBackwardJump(BasicBlock* startBlock, BasicBlock* endBlock)
5125 {
5126     noway_assert(startBlock->bbNum <= endBlock->bbNum);
5127
5128     for (BasicBlock* block = startBlock; block != endBlock->bbNext; block = block->bbNext)
5129     {
5130         if ((block->bbFlags & BBF_BACKWARD_JUMP) == 0)
5131         {
5132             block->bbFlags |= BBF_BACKWARD_JUMP;
5133         }
5134     }
5135 }
5136
5137 /*****************************************************************************
5138  *
5139  *  Finally link up the bbJumpDest of the blocks together
5140  */
5141
5142 void Compiler::fgLinkBasicBlocks()
5143 {
5144     /* Create the basic block lookup tables */
5145
5146     fgInitBBLookup();
5147
5148     /* First block is always reachable */
5149
5150     fgFirstBB->bbRefs = 1;
5151
5152     /* Walk all the basic blocks, filling in the target addresses */
5153
5154     for (BasicBlock* curBBdesc = fgFirstBB; curBBdesc; curBBdesc = curBBdesc->bbNext)
5155     {
5156         switch (curBBdesc->bbJumpKind)
5157         {
5158             case BBJ_COND:
5159             case BBJ_ALWAYS:
5160             case BBJ_LEAVE:
5161                 curBBdesc->bbJumpDest = fgLookupBB(curBBdesc->bbJumpOffs);
5162                 curBBdesc->bbJumpDest->bbRefs++;
5163                 if (curBBdesc->bbJumpDest->bbNum <= curBBdesc->bbNum)
5164                 {
5165                     fgMarkBackwardJump(curBBdesc->bbJumpDest, curBBdesc);
5166                 }
5167
5168                 /* Is the next block reachable? */
5169
5170                 if (curBBdesc->bbJumpKind == BBJ_ALWAYS || curBBdesc->bbJumpKind == BBJ_LEAVE)
5171                 {
5172                     break;
5173                 }
5174
5175                 if (!curBBdesc->bbNext)
5176                 {
5177                     BADCODE("Fall thru the end of a method");
5178                 }
5179
5180             // Fall through, the next block is also reachable
5181
5182             case BBJ_NONE:
5183                 curBBdesc->bbNext->bbRefs++;
5184                 break;
5185
5186             case BBJ_EHFINALLYRET:
5187             case BBJ_EHFILTERRET:
5188             case BBJ_THROW:
5189             case BBJ_RETURN:
5190                 break;
5191
5192             case BBJ_SWITCH:
5193
5194                 unsigned jumpCnt;
5195                 jumpCnt = curBBdesc->bbJumpSwt->bbsCount;
5196                 BasicBlock** jumpPtr;
5197                 jumpPtr = curBBdesc->bbJumpSwt->bbsDstTab;
5198
5199                 do
5200                 {
5201                     *jumpPtr = fgLookupBB((unsigned)*(size_t*)jumpPtr);
5202                     (*jumpPtr)->bbRefs++;
5203                     if ((*jumpPtr)->bbNum <= curBBdesc->bbNum)
5204                     {
5205                         fgMarkBackwardJump(*jumpPtr, curBBdesc);
5206                     }
5207                 } while (++jumpPtr, --jumpCnt);
5208
5209                 /* Default case of CEE_SWITCH (next block), is at end of jumpTab[] */
5210
5211                 noway_assert(*(jumpPtr - 1) == curBBdesc->bbNext);
5212                 break;
5213
5214             case BBJ_CALLFINALLY: // BBJ_CALLFINALLY and BBJ_EHCATCHRET don't appear until later
5215             case BBJ_EHCATCHRET:
5216             default:
5217                 noway_assert(!"Unexpected bbJumpKind");
5218                 break;
5219         }
5220     }
5221 }
5222
5223 /*****************************************************************************
5224  *
5225  *  Walk the instrs to create the basic blocks. Returns the number of BBJ_RETURN in method
5226  */
5227
5228 unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget)
5229 {
5230     unsigned    retBlocks;
5231     const BYTE* codeBegp = codeAddr;
5232     const BYTE* codeEndp = codeAddr + codeSize;
5233     bool        tailCall = false;
5234     unsigned    curBBoffs;
5235     BasicBlock* curBBdesc;
5236
5237     retBlocks = 0;
5238     /* Clear the beginning offset for the first BB */
5239
5240     curBBoffs = 0;
5241
5242     if (opts.compDbgCode && (info.compVarScopesCount > 0))
5243     {
5244         compResetScopeLists();
5245
5246         // Ignore scopes beginning at offset 0
5247         while (compGetNextEnterScope(0))
5248         { /* do nothing */
5249         }
5250         while (compGetNextExitScope(0))
5251         { /* do nothing */
5252         }
5253     }
5254
5255     BBjumpKinds jmpKind;
5256
5257     do
5258     {
5259         OPCODE     opcode;
5260         unsigned   sz;
5261         unsigned   jmpAddr = DUMMY_INIT(BAD_IL_OFFSET);
5262         unsigned   bbFlags = 0;
5263         BBswtDesc* swtDsc  = nullptr;
5264         unsigned   nxtBBoffs;
5265
5266         opcode = (OPCODE)getU1LittleEndian(codeAddr);
5267         codeAddr += sizeof(__int8);
5268         jmpKind = BBJ_NONE;
5269
5270     DECODE_OPCODE:
5271
5272         /* Get the size of additional parameters */
5273
5274         noway_assert((unsigned)opcode < CEE_COUNT);
5275
5276         sz = opcodeSizes[opcode];
5277
5278         switch (opcode)
5279         {
5280             signed jmpDist;
5281
5282             case CEE_PREFIX1:
5283                 if (jumpTarget[codeAddr - codeBegp] != JT_NONE)
5284                 {
5285                     BADCODE3("jump target between prefix 0xFE and opcode", " at offset %04X",
5286                              (IL_OFFSET)(codeAddr - codeBegp));
5287                 }
5288
5289                 opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr));
5290                 codeAddr += sizeof(__int8);
5291                 goto DECODE_OPCODE;
5292
5293             /* Check to see if we have a jump/return opcode */
5294
5295             case CEE_BRFALSE:
5296             case CEE_BRFALSE_S:
5297             case CEE_BRTRUE:
5298             case CEE_BRTRUE_S:
5299
5300             case CEE_BEQ:
5301             case CEE_BEQ_S:
5302             case CEE_BGE:
5303             case CEE_BGE_S:
5304             case CEE_BGE_UN:
5305             case CEE_BGE_UN_S:
5306             case CEE_BGT:
5307             case CEE_BGT_S:
5308             case CEE_BGT_UN:
5309             case CEE_BGT_UN_S:
5310             case CEE_BLE:
5311             case CEE_BLE_S:
5312             case CEE_BLE_UN:
5313             case CEE_BLE_UN_S:
5314             case CEE_BLT:
5315             case CEE_BLT_S:
5316             case CEE_BLT_UN:
5317             case CEE_BLT_UN_S:
5318             case CEE_BNE_UN:
5319             case CEE_BNE_UN_S:
5320
5321                 jmpKind = BBJ_COND;
5322                 goto JMP;
5323
5324             case CEE_LEAVE:
5325             case CEE_LEAVE_S:
5326
5327                 // We need to check if we are jumping out of a finally-protected try.
5328                 jmpKind = BBJ_LEAVE;
5329                 goto JMP;
5330
5331             case CEE_BR:
5332             case CEE_BR_S:
5333                 jmpKind = BBJ_ALWAYS;
5334                 goto JMP;
5335
5336             JMP:
5337
5338                 /* Compute the target address of the jump */
5339
5340                 jmpDist = (sz == 1) ? getI1LittleEndian(codeAddr) : getI4LittleEndian(codeAddr);
5341
5342                 if (compIsForInlining() && jmpDist == 0 && (opcode == CEE_BR || opcode == CEE_BR_S))
5343                 {
5344                     continue; /* NOP */
5345                 }
5346
5347                 jmpAddr = (IL_OFFSET)(codeAddr - codeBegp) + sz + jmpDist;
5348                 break;
5349
5350             case CEE_SWITCH:
5351             {
5352                 unsigned jmpBase;
5353                 unsigned jmpCnt; // # of switch cases (excluding defualt)
5354
5355                 BasicBlock** jmpTab;
5356                 BasicBlock** jmpPtr;
5357
5358                 /* Allocate the switch descriptor */
5359
5360                 swtDsc = new (this, CMK_BasicBlock) BBswtDesc;
5361
5362                 /* Read the number of entries in the table */
5363
5364                 jmpCnt = getU4LittleEndian(codeAddr);
5365                 codeAddr += 4;
5366
5367                 /* Compute  the base offset for the opcode */
5368
5369                 jmpBase = (IL_OFFSET)((codeAddr - codeBegp) + jmpCnt * sizeof(DWORD));
5370
5371                 /* Allocate the jump table */
5372
5373                 jmpPtr = jmpTab = new (this, CMK_BasicBlock) BasicBlock*[jmpCnt + 1];
5374
5375                 /* Fill in the jump table */
5376
5377                 for (unsigned count = jmpCnt; count; count--)
5378                 {
5379                     jmpDist = getI4LittleEndian(codeAddr);
5380                     codeAddr += 4;
5381
5382                     // store the offset in the pointer.  We change these in fgLinkBasicBlocks().
5383                     *jmpPtr++ = (BasicBlock*)(size_t)(jmpBase + jmpDist);
5384                 }
5385
5386                 /* Append the default label to the target table */
5387
5388                 *jmpPtr++ = (BasicBlock*)(size_t)jmpBase;
5389
5390                 /* Make sure we found the right number of labels */
5391
5392                 noway_assert(jmpPtr == jmpTab + jmpCnt + 1);
5393
5394                 /* Compute the size of the switch opcode operands */
5395
5396                 sz = sizeof(DWORD) + jmpCnt * sizeof(DWORD);
5397
5398                 /* Fill in the remaining fields of the switch descriptor */
5399
5400                 swtDsc->bbsCount  = jmpCnt + 1;
5401                 swtDsc->bbsDstTab = jmpTab;
5402
5403                 /* This is definitely a jump */
5404
5405                 jmpKind     = BBJ_SWITCH;
5406                 fgHasSwitch = true;
5407
5408                 if (opts.compProcedureSplitting)
5409                 {
5410                     // TODO-CQ: We might need to create a switch table; we won't know for sure until much later.
5411                     // However, switch tables don't work with hot/cold splitting, currently. The switch table data needs
5412                     // a relocation such that if the base (the first block after the prolog) and target of the switch
5413                     // branch are put in different sections, the difference stored in the table is updated. However, our
5414                     // relocation implementation doesn't support three different pointers (relocation address, base, and
5415                     // target). So, we need to change our switch table implementation to be more like
5416                     // JIT64: put the table in the code section, in the same hot/cold section as the switch jump itself
5417                     // (maybe immediately after the switch jump), and make the "base" address be also in that section,
5418                     // probably the address after the switch jump.
5419                     opts.compProcedureSplitting = false;
5420                     JITDUMP("Turning off procedure splitting for this method, as it might need switch tables; "
5421                             "implementation limitation.\n");
5422                 }
5423             }
5424                 goto GOT_ENDP;
5425
5426             case CEE_ENDFILTER:
5427                 bbFlags |= BBF_DONT_REMOVE;
5428                 jmpKind = BBJ_EHFILTERRET;
5429                 break;
5430
5431             case CEE_ENDFINALLY:
5432                 jmpKind = BBJ_EHFINALLYRET;
5433                 break;
5434
5435             case CEE_TAILCALL:
5436                 if (compIsForInlining())
5437                 {
5438                     // TODO-CQ: We can inline some callees with explicit tail calls if we can guarantee that the calls
5439                     // can be dispatched as tail calls from the caller.
5440                     compInlineResult->NoteFatal(InlineObservation::CALLEE_EXPLICIT_TAIL_PREFIX);
5441                     retBlocks++;
5442                     return retBlocks;
5443                 }
5444
5445                 __fallthrough;
5446
5447             case CEE_READONLY:
5448             case CEE_CONSTRAINED:
5449             case CEE_VOLATILE:
5450             case CEE_UNALIGNED:
5451                 // fgFindJumpTargets should have ruled out this possibility
5452                 //   (i.e. a prefix opcodes as last intruction in a block)
5453                 noway_assert(codeAddr < codeEndp);
5454
5455                 if (jumpTarget[codeAddr - codeBegp] != JT_NONE)
5456                 {
5457                     BADCODE3("jump target between prefix and an opcode", " at offset %04X",
5458                              (IL_OFFSET)(codeAddr - codeBegp));
5459                 }
5460                 break;
5461
5462             case CEE_CALL:
5463             case CEE_CALLVIRT:
5464             case CEE_CALLI:
5465             {
5466                 if (compIsForInlining() ||               // Ignore tail call in the inlinee. Period.
5467                     (!tailCall && !compTailCallStress()) // A new BB with BBJ_RETURN would have been created
5468
5469                     // after a tailcall statement.
5470                     // We need to keep this invariant if we want to stress the tailcall.
5471                     // That way, the potential (tail)call statement is always the last
5472                     // statement in the block.
5473                     // Otherwise, we will assert at the following line in fgMorphCall()
5474                     //     noway_assert(fgMorphStmt->gtNext == NULL);
5475                     )
5476                 {
5477                     // Neither .tailcall prefix, no tailcall stress. So move on.
5478                     break;
5479                 }
5480
5481                 // Make sure the code sequence is legal for the tail call.
5482                 // If so, mark this BB as having a BBJ_RETURN.
5483
5484                 if (codeAddr >= codeEndp - sz)
5485                 {
5486                     BADCODE3("No code found after the call instruction", " at offset %04X",
5487                              (IL_OFFSET)(codeAddr - codeBegp));
5488                 }
5489
5490                 if (tailCall)
5491                 {
5492                     bool isCallPopAndRet = false;
5493
5494                     // impIsTailCallILPattern uses isRecursive flag to determine whether ret in a fallthrough block is
5495                     // allowed. We don't know at this point whether the call is recursive so we conservatively pass
5496                     // false. This will only affect explicit tail calls when IL verification is not needed for the
5497                     // method.
5498                     bool isRecursive = false;
5499                     if (!impIsTailCallILPattern(tailCall, opcode, codeAddr + sz, codeEndp, isRecursive,
5500                                                 &isCallPopAndRet))
5501                     {
5502 #if !defined(FEATURE_CORECLR) && defined(_TARGET_AMD64_)
5503                         BADCODE3("tail call not followed by ret or pop+ret", " at offset %04X",
5504                                  (IL_OFFSET)(codeAddr - codeBegp));
5505 #else
5506                         BADCODE3("tail call not followed by ret", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5507 #endif // !FEATURE_CORECLR && _TARGET_AMD64_
5508                     }
5509
5510 #if !defined(FEATURE_CORECLR) && defined(_TARGET_AMD64_)
5511                     if (isCallPopAndRet)
5512                     {
5513                         // By breaking here, we let pop and ret opcodes to be
5514                         // imported after tail call.  If tail prefix is honored,
5515                         // stmts corresponding to pop and ret will be removed
5516                         // in fgMorphCall().
5517                         break;
5518                     }
5519 #endif // !FEATURE_CORECLR && _TARGET_AMD64_
5520                 }
5521                 else
5522                 {
5523                     OPCODE nextOpcode = (OPCODE)getU1LittleEndian(codeAddr + sz);
5524
5525                     if (nextOpcode != CEE_RET)
5526                     {
5527                         noway_assert(compTailCallStress());
5528                         // Next OPCODE is not a CEE_RET, bail the attempt to stress the tailcall.
5529                         // (I.e. We will not make a new BB after the "call" statement.)
5530                         break;
5531                     }
5532                 }
5533             }
5534
5535             /* For tail call, we just call CORINFO_HELP_TAILCALL, and it jumps to the
5536                target. So we don't need an epilog - just like CORINFO_HELP_THROW.
5537                Make the block BBJ_RETURN, but we will change it to BBJ_THROW
5538                if the tailness of the call is satisfied.
5539                NOTE : The next instruction is guaranteed to be a CEE_RET
5540                and it will create another BasicBlock. But there may be an
5541                jump directly to that CEE_RET. If we want to avoid creating
5542                an unnecessary block, we need to check if the CEE_RETURN is
5543                the target of a jump.
5544              */
5545
5546             // fall-through
5547
5548             case CEE_JMP:
5549             /* These are equivalent to a return from the current method
5550                But instead of directly returning to the caller we jump and
5551                execute something else in between */
5552             case CEE_RET:
5553                 retBlocks++;
5554                 jmpKind = BBJ_RETURN;
5555                 break;
5556
5557             case CEE_THROW:
5558             case CEE_RETHROW:
5559                 jmpKind = BBJ_THROW;
5560                 break;
5561
5562 #ifdef DEBUG
5563 // make certain we did not forget any flow of control instructions
5564 // by checking the 'ctrl' field in opcode.def. First filter out all
5565 // non-ctrl instructions
5566 #define BREAK(name)                                                                                                    \
5567     case name:                                                                                                         \
5568         break;
5569 #define NEXT(name)                                                                                                     \
5570     case name:                                                                                                         \
5571         break;
5572 #define CALL(name)
5573 #define THROW(name)
5574 #undef RETURN // undef contract RETURN macro
5575 #define RETURN(name)
5576 #define META(name)
5577 #define BRANCH(name)
5578 #define COND_BRANCH(name)
5579 #define PHI(name)
5580
5581 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) ctrl(name)
5582 #include "opcode.def"
5583 #undef OPDEF
5584
5585 #undef PHI
5586 #undef BREAK
5587 #undef CALL
5588 #undef NEXT
5589 #undef THROW
5590 #undef RETURN
5591 #undef META
5592 #undef BRANCH
5593 #undef COND_BRANCH
5594
5595             // These ctrl-flow opcodes don't need any special handling
5596             case CEE_NEWOBJ: // CTRL_CALL
5597                 break;
5598
5599             // what's left are forgotten instructions
5600             default:
5601                 BADCODE("Unrecognized control Opcode");
5602                 break;
5603 #else  // !DEBUG
5604             default:
5605                 break;
5606 #endif // !DEBUG
5607         }
5608
5609         /* Jump over the operand */
5610
5611         codeAddr += sz;
5612
5613     GOT_ENDP:
5614
5615         tailCall = (opcode == CEE_TAILCALL);
5616
5617         /* Make sure a jump target isn't in the middle of our opcode */
5618
5619         if (sz)
5620         {
5621             IL_OFFSET offs = (IL_OFFSET)(codeAddr - codeBegp) - sz; // offset of the operand
5622
5623             for (unsigned i = 0; i < sz; i++, offs++)
5624             {
5625                 if (jumpTarget[offs] != JT_NONE)
5626                 {
5627                     BADCODE3("jump into the middle of an opcode", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5628                 }
5629             }
5630         }
5631
5632         /* Compute the offset of the next opcode */
5633
5634         nxtBBoffs = (IL_OFFSET)(codeAddr - codeBegp);
5635
5636         bool foundScope = false;
5637
5638         if (opts.compDbgCode && (info.compVarScopesCount > 0))
5639         {
5640             while (compGetNextEnterScope(nxtBBoffs))
5641             {
5642                 foundScope = true;
5643             }
5644             while (compGetNextExitScope(nxtBBoffs))
5645             {
5646                 foundScope = true;
5647             }
5648         }
5649
5650         /* Do we have a jump? */
5651
5652         if (jmpKind == BBJ_NONE)
5653         {
5654             /* No jump; make sure we don't fall off the end of the function */
5655
5656             if (codeAddr == codeEndp)
5657             {
5658                 BADCODE3("missing return opcode", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5659             }
5660
5661             /* If a label follows this opcode, we'll have to make a new BB */
5662
5663             bool makeBlock = (jumpTarget[nxtBBoffs] != JT_NONE);
5664
5665             if (!makeBlock && foundScope)
5666             {
5667                 makeBlock = true;
5668 #ifdef DEBUG
5669                 if (verbose)
5670                 {
5671                     printf("Splitting at BBoffs = %04u\n", nxtBBoffs);
5672                 }
5673 #endif // DEBUG
5674             }
5675
5676             if (!makeBlock)
5677             {
5678                 continue;
5679             }
5680         }
5681
5682         /* We need to create a new basic block */
5683
5684         curBBdesc = fgNewBasicBlock(jmpKind);
5685
5686         curBBdesc->bbFlags |= bbFlags;
5687         curBBdesc->bbRefs = 0;
5688
5689         curBBdesc->bbCodeOffs    = curBBoffs;
5690         curBBdesc->bbCodeOffsEnd = nxtBBoffs;
5691
5692         unsigned profileWeight;
5693         if (fgGetProfileWeightForBasicBlock(curBBoffs, &profileWeight))
5694         {
5695             curBBdesc->setBBProfileWeight(profileWeight);
5696             if (profileWeight == 0)
5697             {
5698                 curBBdesc->bbSetRunRarely();
5699             }
5700             else
5701             {
5702                 // Note that bbNewBasicBlock (called from fgNewBasicBlock) may have
5703                 // already marked the block as rarely run.  In that case (and when we know
5704                 // that the block profile weight is non-zero) we want to unmark that.
5705
5706                 curBBdesc->bbFlags &= ~BBF_RUN_RARELY;
5707             }
5708         }
5709
5710         switch (jmpKind)
5711         {
5712             case BBJ_SWITCH:
5713                 curBBdesc->bbJumpSwt = swtDsc;
5714                 break;
5715
5716             case BBJ_COND:
5717             case BBJ_ALWAYS:
5718             case BBJ_LEAVE:
5719                 noway_assert(jmpAddr != DUMMY_INIT(BAD_IL_OFFSET));
5720                 curBBdesc->bbJumpOffs = jmpAddr;
5721                 break;
5722
5723             default:
5724                 break;
5725         }
5726
5727         DBEXEC(verbose, curBBdesc->dspBlockHeader(this, false, false, false));
5728
5729         /* Remember where the next BB will start */
5730
5731         curBBoffs = nxtBBoffs;
5732     } while (codeAddr < codeEndp);
5733
5734     noway_assert(codeAddr == codeEndp);
5735
5736     /* Finally link up the bbJumpDest of the blocks together */
5737
5738     fgLinkBasicBlocks();
5739
5740     return retBlocks;
5741 }
5742
5743 /*****************************************************************************
5744  *
5745  *  Main entry point to discover the basic blocks for the current function.
5746  */
5747
5748 void Compiler::fgFindBasicBlocks()
5749 {
5750 #ifdef DEBUG
5751     if (verbose)
5752     {
5753         printf("*************** In fgFindBasicBlocks() for %s\n", info.compFullName);
5754     }
5755 #endif
5756
5757     /* Allocate the 'jump target' vector
5758      *
5759      *  We need one extra byte as we mark
5760      *  jumpTarget[info.compILCodeSize] with JT_ADDR
5761      *  when we need to add a dummy block
5762      *  to record the end of a try or handler region.
5763      */
5764     BYTE* jumpTarget = new (this, CMK_Unknown) BYTE[info.compILCodeSize + 1];
5765     memset(jumpTarget, JT_NONE, info.compILCodeSize + 1);
5766     noway_assert(JT_NONE == 0);
5767
5768     /* Walk the instrs to find all jump targets */
5769
5770     fgFindJumpTargets(info.compCode, info.compILCodeSize, jumpTarget);
5771     if (compDonotInline())
5772     {
5773         return;
5774     }
5775
5776     unsigned XTnum;
5777
5778     /* Are there any exception handlers? */
5779
5780     if (info.compXcptnsCount > 0)
5781     {
5782         noway_assert(!compIsForInlining());
5783
5784         /* Check and mark all the exception handlers */
5785
5786         for (XTnum = 0; XTnum < info.compXcptnsCount; XTnum++)
5787         {
5788             DWORD             tmpOffset;
5789             CORINFO_EH_CLAUSE clause;
5790             info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
5791             noway_assert(clause.HandlerLength != (unsigned)-1);
5792
5793             if (clause.TryLength <= 0)
5794             {
5795                 BADCODE("try block length <=0");
5796             }
5797
5798             /* Mark the 'try' block extent and the handler itself */
5799
5800             if (clause.TryOffset > info.compILCodeSize)
5801             {
5802                 BADCODE("try offset is > codesize");
5803             }
5804             if (jumpTarget[clause.TryOffset] == JT_NONE)
5805             {
5806                 jumpTarget[clause.TryOffset] = JT_ADDR;
5807             }
5808
5809             tmpOffset = clause.TryOffset + clause.TryLength;
5810             if (tmpOffset > info.compILCodeSize)
5811             {
5812                 BADCODE("try end is > codesize");
5813             }
5814             if (jumpTarget[tmpOffset] == JT_NONE)
5815             {
5816                 jumpTarget[tmpOffset] = JT_ADDR;
5817             }
5818
5819             if (clause.HandlerOffset > info.compILCodeSize)
5820             {
5821                 BADCODE("handler offset > codesize");
5822             }
5823             if (jumpTarget[clause.HandlerOffset] == JT_NONE)
5824             {
5825                 jumpTarget[clause.HandlerOffset] = JT_ADDR;
5826             }
5827
5828             tmpOffset = clause.HandlerOffset + clause.HandlerLength;
5829             if (tmpOffset > info.compILCodeSize)
5830             {
5831                 BADCODE("handler end > codesize");
5832             }
5833             if (jumpTarget[tmpOffset] == JT_NONE)
5834             {
5835                 jumpTarget[tmpOffset] = JT_ADDR;
5836             }
5837
5838             if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5839             {
5840                 if (clause.FilterOffset > info.compILCodeSize)
5841                 {
5842                     BADCODE("filter offset > codesize");
5843                 }
5844                 if (jumpTarget[clause.FilterOffset] == JT_NONE)
5845                 {
5846                     jumpTarget[clause.FilterOffset] = JT_ADDR;
5847                 }
5848             }
5849         }
5850     }
5851
5852 #ifdef DEBUG
5853     if (verbose)
5854     {
5855         bool anyJumpTargets = false;
5856         printf("Jump targets:\n");
5857         for (unsigned i = 0; i < info.compILCodeSize + 1; i++)
5858         {
5859             if (jumpTarget[i] == JT_NONE)
5860             {
5861                 continue;
5862             }
5863
5864             anyJumpTargets = true;
5865             printf("  IL_%04x", i);
5866
5867             if (jumpTarget[i] & JT_ADDR)
5868             {
5869                 printf(" addr");
5870             }
5871             if (jumpTarget[i] & JT_MULTI)
5872             {
5873                 printf(" multi");
5874             }
5875             printf("\n");
5876         }
5877         if (!anyJumpTargets)
5878         {
5879             printf("  none\n");
5880         }
5881     }
5882 #endif // DEBUG
5883
5884     /* Now create the basic blocks */
5885
5886     unsigned retBlocks = fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget);
5887
5888     if (compIsForInlining())
5889     {
5890
5891 #ifdef DEBUG
5892         // If fgFindJumpTargets marked the call as "no return" there
5893         // really should be no BBJ_RETURN blocks in the method.
5894         bool markedNoReturn = (impInlineInfo->iciCall->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN) != 0;
5895         assert((markedNoReturn && (retBlocks == 0)) || (!markedNoReturn && (retBlocks >= 1)));
5896 #endif // DEBUG
5897
5898         if (compInlineResult->IsFailure())
5899         {
5900             return;
5901         }
5902
5903         noway_assert(info.compXcptnsCount == 0);
5904         compHndBBtab = impInlineInfo->InlinerCompiler->compHndBBtab;
5905         compHndBBtabAllocCount =
5906             impInlineInfo->InlinerCompiler->compHndBBtabAllocCount; // we probably only use the table, not add to it.
5907         compHndBBtabCount    = impInlineInfo->InlinerCompiler->compHndBBtabCount;
5908         info.compXcptnsCount = impInlineInfo->InlinerCompiler->info.compXcptnsCount;
5909
5910         // Use a spill temp for the return value if there are multiple return blocks,
5911         // or if the inlinee has GC ref locals.
5912         if ((info.compRetNativeType != TYP_VOID) && ((retBlocks > 1) || impInlineInfo->HasGcRefLocals()))
5913         {
5914             // The lifetime of this var might expand multiple BBs. So it is a long lifetime compiler temp.
5915             lvaInlineeReturnSpillTemp                  = lvaGrabTemp(false DEBUGARG("Inline return value spill temp"));
5916             lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType;
5917
5918             // If the method returns a ref class, set the class of the spill temp
5919             // to the method's return value. We may update this later if it turns
5920             // out we can prove the method returns a more specific type.
5921             if (info.compRetType == TYP_REF)
5922             {
5923                 CORINFO_CLASS_HANDLE retClassHnd = impInlineInfo->inlineCandidateInfo->methInfo.args.retTypeClass;
5924                 if (retClassHnd != nullptr)
5925                 {
5926                     lvaSetClass(lvaInlineeReturnSpillTemp, retClassHnd);
5927                 }
5928             }
5929         }
5930
5931         return;
5932     }
5933
5934     /* Mark all blocks within 'try' blocks as such */
5935
5936     if (info.compXcptnsCount == 0)
5937     {
5938         return;
5939     }
5940
5941     if (info.compXcptnsCount > MAX_XCPTN_INDEX)
5942     {
5943         IMPL_LIMITATION("too many exception clauses");
5944     }
5945
5946     /* Allocate the exception handler table */
5947
5948     fgAllocEHTable();
5949
5950     /* Assume we don't need to sort the EH table (such that nested try/catch
5951      * appear before their try or handler parent). The EH verifier will notice
5952      * when we do need to sort it.
5953      */
5954
5955     fgNeedToSortEHTable = false;
5956
5957     verInitEHTree(info.compXcptnsCount);
5958     EHNodeDsc* initRoot = ehnNext; // remember the original root since
5959                                    // it may get modified during insertion
5960
5961     // Annotate BBs with exception handling information required for generating correct eh code
5962     // as well as checking for correct IL
5963
5964     EHblkDsc* HBtab;
5965
5966     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
5967     {
5968         CORINFO_EH_CLAUSE clause;
5969         info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
5970         noway_assert(clause.HandlerLength != (unsigned)-1); // @DEPRECATED
5971
5972 #ifdef DEBUG
5973         if (verbose)
5974         {
5975             dispIncomingEHClause(XTnum, clause);
5976         }
5977 #endif // DEBUG
5978
5979         IL_OFFSET tryBegOff    = clause.TryOffset;
5980         IL_OFFSET tryEndOff    = tryBegOff + clause.TryLength;
5981         IL_OFFSET filterBegOff = 0;
5982         IL_OFFSET hndBegOff    = clause.HandlerOffset;
5983         IL_OFFSET hndEndOff    = hndBegOff + clause.HandlerLength;
5984
5985         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5986         {
5987             filterBegOff = clause.FilterOffset;
5988         }
5989
5990         if (tryEndOff > info.compILCodeSize)
5991         {
5992             BADCODE3("end of try block beyond end of method for try", " at offset %04X", tryBegOff);
5993         }
5994         if (hndEndOff > info.compILCodeSize)
5995         {
5996             BADCODE3("end of hnd block beyond end of method for try", " at offset %04X", tryBegOff);
5997         }
5998
5999         HBtab->ebdTryBegOffset    = tryBegOff;
6000         HBtab->ebdTryEndOffset    = tryEndOff;
6001         HBtab->ebdFilterBegOffset = filterBegOff;
6002         HBtab->ebdHndBegOffset    = hndBegOff;
6003         HBtab->ebdHndEndOffset    = hndEndOff;
6004
6005         /* Convert the various addresses to basic blocks */
6006
6007         BasicBlock* tryBegBB = fgLookupBB(tryBegOff);
6008         BasicBlock* tryEndBB =
6009             fgLookupBB(tryEndOff); // note: this can be NULL if the try region is at the end of the function
6010         BasicBlock* hndBegBB = fgLookupBB(hndBegOff);
6011         BasicBlock* hndEndBB = nullptr;
6012         BasicBlock* filtBB   = nullptr;
6013         BasicBlock* block;
6014
6015         //
6016         // Assert that the try/hnd beginning blocks are set up correctly
6017         //
6018         if (tryBegBB == nullptr)
6019         {
6020             BADCODE("Try Clause is invalid");
6021         }
6022
6023         if (hndBegBB == nullptr)
6024         {
6025             BADCODE("Handler Clause is invalid");
6026         }
6027
6028         tryBegBB->bbFlags |= BBF_HAS_LABEL;
6029         hndBegBB->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
6030
6031 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
6032         // This will change the block weight from 0 to 1
6033         // and clear the rarely run flag
6034         hndBegBB->makeBlockHot();
6035 #else
6036         hndBegBB->bbSetRunRarely();   // handler entry points are rarely executed
6037 #endif
6038
6039         if (hndEndOff < info.compILCodeSize)
6040         {
6041             hndEndBB = fgLookupBB(hndEndOff);
6042         }
6043
6044         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
6045         {
6046             filtBB = HBtab->ebdFilter = fgLookupBB(clause.FilterOffset);
6047
6048             filtBB->bbCatchTyp = BBCT_FILTER;
6049             filtBB->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
6050
6051             hndBegBB->bbCatchTyp = BBCT_FILTER_HANDLER;
6052
6053 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
6054             // This will change the block weight from 0 to 1
6055             // and clear the rarely run flag
6056             filtBB->makeBlockHot();
6057 #else
6058             filtBB->bbSetRunRarely(); // filter entry points are rarely executed
6059 #endif
6060
6061             // Mark all BBs that belong to the filter with the XTnum of the corresponding handler
6062             for (block = filtBB; /**/; block = block->bbNext)
6063             {
6064                 if (block == nullptr)
6065                 {
6066                     BADCODE3("Missing endfilter for filter", " at offset %04X", filtBB->bbCodeOffs);
6067                     return;
6068                 }
6069
6070                 // Still inside the filter
6071                 block->setHndIndex(XTnum);
6072
6073                 if (block->bbJumpKind == BBJ_EHFILTERRET)
6074                 {
6075                     // Mark catch handler as successor.
6076                     block->bbJumpDest = hndBegBB;
6077                     assert(block->bbJumpDest->bbCatchTyp == BBCT_FILTER_HANDLER);
6078                     break;
6079                 }
6080             }
6081
6082             if (!block->bbNext || block->bbNext != hndBegBB)
6083             {
6084                 BADCODE3("Filter does not immediately precede handler for filter", " at offset %04X",
6085                          filtBB->bbCodeOffs);
6086             }
6087         }
6088         else
6089         {
6090             HBtab->ebdTyp = clause.ClassToken;
6091
6092             /* Set bbCatchTyp as appropriate */
6093
6094             if (clause.Flags & CORINFO_EH_CLAUSE_FINALLY)
6095             {
6096                 hndBegBB->bbCatchTyp = BBCT_FINALLY;
6097             }
6098             else
6099             {
6100                 if (clause.Flags & CORINFO_EH_CLAUSE_FAULT)
6101                 {
6102                     hndBegBB->bbCatchTyp = BBCT_FAULT;
6103                 }
6104                 else
6105                 {
6106                     hndBegBB->bbCatchTyp = clause.ClassToken;
6107
6108                     // These values should be non-zero value that will
6109                     // not collide with real tokens for bbCatchTyp
6110                     if (clause.ClassToken == 0)
6111                     {
6112                         BADCODE("Exception catch type is Null");
6113                     }
6114
6115                     noway_assert(clause.ClassToken != BBCT_FAULT);
6116                     noway_assert(clause.ClassToken != BBCT_FINALLY);
6117                     noway_assert(clause.ClassToken != BBCT_FILTER);
6118                     noway_assert(clause.ClassToken != BBCT_FILTER_HANDLER);
6119                 }
6120             }
6121         }
6122
6123         /* Mark the initial block and last blocks in the 'try' region */
6124
6125         tryBegBB->bbFlags |= BBF_TRY_BEG | BBF_HAS_LABEL;
6126
6127         /*  Prevent future optimizations of removing the first block   */
6128         /*  of a TRY block and the first block of an exception handler */
6129
6130         tryBegBB->bbFlags |= BBF_DONT_REMOVE;
6131         hndBegBB->bbFlags |= BBF_DONT_REMOVE;
6132         hndBegBB->bbRefs++; // The first block of a handler gets an extra, "artificial" reference count.
6133
6134         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
6135         {
6136             filtBB->bbFlags |= BBF_DONT_REMOVE;
6137             filtBB->bbRefs++; // The first block of a filter gets an extra, "artificial" reference count.
6138         }
6139
6140         tryBegBB->bbFlags |= BBF_DONT_REMOVE;
6141         hndBegBB->bbFlags |= BBF_DONT_REMOVE;
6142
6143         //
6144         // Store the info to the table of EH block handlers
6145         //
6146
6147         HBtab->ebdHandlerType = ToEHHandlerType(clause.Flags);
6148
6149         HBtab->ebdTryBeg  = tryBegBB;
6150         HBtab->ebdTryLast = (tryEndBB == nullptr) ? fgLastBB : tryEndBB->bbPrev;
6151
6152         HBtab->ebdHndBeg  = hndBegBB;
6153         HBtab->ebdHndLast = (hndEndBB == nullptr) ? fgLastBB : hndEndBB->bbPrev;
6154
6155         //
6156         // Assert that all of our try/hnd blocks are setup correctly.
6157         //
6158         if (HBtab->ebdTryLast == nullptr)
6159         {
6160             BADCODE("Try Clause is invalid");
6161         }
6162
6163         if (HBtab->ebdHndLast == nullptr)
6164         {
6165             BADCODE("Handler Clause is invalid");
6166         }
6167
6168         //
6169         // Verify that it's legal
6170         //
6171
6172         verInsertEhNode(&clause, HBtab);
6173
6174     } // end foreach handler table entry
6175
6176     fgSortEHTable();
6177
6178     // Next, set things related to nesting that depend on the sorting being complete.
6179
6180     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
6181     {
6182         /* Mark all blocks in the finally/fault or catch clause */
6183
6184         BasicBlock* tryBegBB = HBtab->ebdTryBeg;
6185         BasicBlock* hndBegBB = HBtab->ebdHndBeg;
6186
6187         IL_OFFSET tryBegOff = HBtab->ebdTryBegOffset;
6188         IL_OFFSET tryEndOff = HBtab->ebdTryEndOffset;
6189
6190         IL_OFFSET hndBegOff = HBtab->ebdHndBegOffset;
6191         IL_OFFSET hndEndOff = HBtab->ebdHndEndOffset;
6192
6193         BasicBlock* block;
6194
6195         for (block = hndBegBB; block && (block->bbCodeOffs < hndEndOff); block = block->bbNext)
6196         {
6197             if (!block->hasHndIndex())
6198             {
6199                 block->setHndIndex(XTnum);
6200             }
6201
6202             // All blocks in a catch handler or filter are rarely run, except the entry
6203             if ((block != hndBegBB) && (hndBegBB->bbCatchTyp != BBCT_FINALLY))
6204             {
6205                 block->bbSetRunRarely();
6206             }
6207         }
6208
6209         /* Mark all blocks within the covered range of the try */
6210
6211         for (block = tryBegBB; block && (block->bbCodeOffs < tryEndOff); block = block->bbNext)
6212         {
6213             /* Mark this BB as belonging to a 'try' block */
6214
6215             if (!block->hasTryIndex())
6216             {
6217                 block->setTryIndex(XTnum);
6218             }
6219
6220 #ifdef DEBUG
6221             /* Note: the BB can't span the 'try' block */
6222
6223             if (!(block->bbFlags & BBF_INTERNAL))
6224             {
6225                 noway_assert(tryBegOff <= block->bbCodeOffs);
6226                 noway_assert(tryEndOff >= block->bbCodeOffsEnd || tryEndOff == tryBegOff);
6227             }
6228 #endif
6229         }
6230
6231 /*  Init ebdHandlerNestingLevel of current clause, and bump up value for all
6232  *  enclosed clauses (which have to be before it in the table).
6233  *  Innermost try-finally blocks must precede outermost
6234  *  try-finally blocks.
6235  */
6236
6237 #if !FEATURE_EH_FUNCLETS
6238         HBtab->ebdHandlerNestingLevel = 0;
6239 #endif // !FEATURE_EH_FUNCLETS
6240
6241         HBtab->ebdEnclosingTryIndex = EHblkDsc::NO_ENCLOSING_INDEX;
6242         HBtab->ebdEnclosingHndIndex = EHblkDsc::NO_ENCLOSING_INDEX;
6243
6244         noway_assert(XTnum < compHndBBtabCount);
6245         noway_assert(XTnum == ehGetIndex(HBtab));
6246
6247         for (EHblkDsc* xtab = compHndBBtab; xtab < HBtab; xtab++)
6248         {
6249 #if !FEATURE_EH_FUNCLETS
6250             if (jitIsBetween(xtab->ebdHndBegOffs(), hndBegOff, hndEndOff))
6251             {
6252                 xtab->ebdHandlerNestingLevel++;
6253             }
6254 #endif // !FEATURE_EH_FUNCLETS
6255
6256             /* If we haven't recorded an enclosing try index for xtab then see
6257              *  if this EH region should be recorded.  We check if the
6258              *  first offset in the xtab lies within our region.  If so,
6259              *  the last offset also must lie within the region, due to
6260              *  nesting rules. verInsertEhNode(), below, will check for proper nesting.
6261              */
6262             if (xtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
6263             {
6264                 bool begBetween = jitIsBetween(xtab->ebdTryBegOffs(), tryBegOff, tryEndOff);
6265                 if (begBetween)
6266                 {
6267                     // Record the enclosing scope link
6268                     xtab->ebdEnclosingTryIndex = (unsigned short)XTnum;
6269                 }
6270             }
6271
6272             /* Do the same for the enclosing handler index.
6273              */
6274             if (xtab->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX)
6275             {
6276                 bool begBetween = jitIsBetween(xtab->ebdTryBegOffs(), hndBegOff, hndEndOff);
6277                 if (begBetween)
6278                 {
6279                     // Record the enclosing scope link
6280                     xtab->ebdEnclosingHndIndex = (unsigned short)XTnum;
6281                 }
6282             }
6283         }
6284
6285     } // end foreach handler table entry
6286
6287 #if !FEATURE_EH_FUNCLETS
6288
6289     EHblkDsc* HBtabEnd;
6290     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
6291     {
6292         if (ehMaxHndNestingCount <= HBtab->ebdHandlerNestingLevel)
6293             ehMaxHndNestingCount = HBtab->ebdHandlerNestingLevel + 1;
6294     }
6295
6296 #endif // !FEATURE_EH_FUNCLETS
6297
6298 #ifndef DEBUG
6299     if (tiVerificationNeeded)
6300 #endif
6301     {
6302         // always run these checks for a debug build
6303         verCheckNestingLevel(initRoot);
6304     }
6305
6306 #ifndef DEBUG
6307     // fgNormalizeEH assumes that this test has been passed.  And Ssa assumes that fgNormalizeEHTable
6308     // has been run.  So do this unless we're in minOpts mode (and always in debug).
6309     if (tiVerificationNeeded || !opts.MinOpts())
6310 #endif
6311     {
6312         fgCheckBasicBlockControlFlow();
6313     }
6314
6315 #ifdef DEBUG
6316     if (verbose)
6317     {
6318         JITDUMP("*************** After fgFindBasicBlocks() has created the EH table\n");
6319         fgDispHandlerTab();
6320     }
6321
6322     // We can't verify the handler table until all the IL legality checks have been done (above), since bad IL
6323     // (such as illegal nesting of regions) will trigger asserts here.
6324     fgVerifyHandlerTab();
6325 #endif
6326
6327     fgNormalizeEH();
6328 }
6329
6330 /*****************************************************************************
6331  * Check control flow constraints for well formed IL. Bail if any of the constraints
6332  * are violated.
6333  */
6334
6335 void Compiler::fgCheckBasicBlockControlFlow()
6336 {
6337     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6338
6339     EHblkDsc* HBtab;
6340
6341     for (BasicBlock* blk = fgFirstBB; blk; blk = blk->bbNext)
6342     {
6343         if (blk->bbFlags & BBF_INTERNAL)
6344         {
6345             continue;
6346         }
6347
6348         switch (blk->bbJumpKind)
6349         {
6350             case BBJ_NONE: // block flows into the next one (no jump)
6351
6352                 fgControlFlowPermitted(blk, blk->bbNext);
6353
6354                 break;
6355
6356             case BBJ_ALWAYS: // block does unconditional jump to target
6357
6358                 fgControlFlowPermitted(blk, blk->bbJumpDest);
6359
6360                 break;
6361
6362             case BBJ_COND: // block conditionally jumps to the target
6363
6364                 fgControlFlowPermitted(blk, blk->bbNext);
6365
6366                 fgControlFlowPermitted(blk, blk->bbJumpDest);
6367
6368                 break;
6369
6370             case BBJ_RETURN: // block ends with 'ret'
6371
6372                 if (blk->hasTryIndex() || blk->hasHndIndex())
6373                 {
6374                     BADCODE3("Return from a protected block", ". Before offset %04X", blk->bbCodeOffsEnd);
6375                 }
6376                 break;
6377
6378             case BBJ_EHFINALLYRET:
6379             case BBJ_EHFILTERRET:
6380
6381                 if (!blk->hasHndIndex()) // must be part of a handler
6382                 {
6383                     BADCODE3("Missing handler", ". Before offset %04X", blk->bbCodeOffsEnd);
6384                 }
6385
6386                 HBtab = ehGetDsc(blk->getHndIndex());
6387
6388                 // Endfilter allowed only in a filter block
6389                 if (blk->bbJumpKind == BBJ_EHFILTERRET)
6390                 {
6391                     if (!HBtab->HasFilter())
6392                     {
6393                         BADCODE("Unexpected endfilter");
6394                     }
6395                 }
6396                 // endfinally allowed only in a finally/fault block
6397                 else if (!HBtab->HasFinallyOrFaultHandler())
6398                 {
6399                     BADCODE("Unexpected endfinally");
6400                 }
6401
6402                 // The handler block should be the innermost block
6403                 // Exception blocks are listed, innermost first.
6404                 if (blk->hasTryIndex() && (blk->getTryIndex() < blk->getHndIndex()))
6405                 {
6406                     BADCODE("endfinally / endfilter in nested try block");
6407                 }
6408
6409                 break;
6410
6411             case BBJ_THROW: // block ends with 'throw'
6412                 /* throw is permitted from every BB, so nothing to check */
6413                 /* importer makes sure that rethrow is done from a catch */
6414                 break;
6415
6416             case BBJ_LEAVE: // block always jumps to the target, maybe out of guarded
6417                             // region. Used temporarily until importing
6418                 fgControlFlowPermitted(blk, blk->bbJumpDest, TRUE);
6419
6420                 break;
6421
6422             case BBJ_SWITCH: // block ends with a switch statement
6423
6424                 BBswtDesc* swtDesc;
6425                 swtDesc = blk->bbJumpSwt;
6426
6427                 assert(swtDesc);
6428
6429                 unsigned i;
6430                 for (i = 0; i < swtDesc->bbsCount; i++)
6431                 {
6432                     fgControlFlowPermitted(blk, swtDesc->bbsDstTab[i]);
6433                 }
6434
6435                 break;
6436
6437             case BBJ_EHCATCHRET:  // block ends with a leave out of a catch (only #if FEATURE_EH_FUNCLETS)
6438             case BBJ_CALLFINALLY: // block always calls the target finally
6439             default:
6440                 noway_assert(!"Unexpected bbJumpKind"); // these blocks don't get created until importing
6441                 break;
6442         }
6443     }
6444 }
6445
6446 /****************************************************************************
6447  * Check that the leave from the block is legal.
6448  * Consider removing this check here if we  can do it cheaply during importing
6449  */
6450
6451 void Compiler::fgControlFlowPermitted(BasicBlock* blkSrc, BasicBlock* blkDest, BOOL isLeave)
6452 {
6453     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6454
6455     unsigned srcHndBeg, destHndBeg;
6456     unsigned srcHndEnd, destHndEnd;
6457     bool     srcInFilter, destInFilter;
6458     bool     srcInCatch = false;
6459
6460     EHblkDsc* srcHndTab;
6461
6462     srcHndTab = ehInitHndRange(blkSrc, &srcHndBeg, &srcHndEnd, &srcInFilter);
6463     ehInitHndRange(blkDest, &destHndBeg, &destHndEnd, &destInFilter);
6464
6465     /* Impose the rules for leaving or jumping from handler blocks */
6466
6467     if (blkSrc->hasHndIndex())
6468     {
6469         srcInCatch = srcHndTab->HasCatchHandler() && srcHndTab->InHndRegionILRange(blkSrc);
6470
6471         /* Are we jumping within the same handler index? */
6472         if (BasicBlock::sameHndRegion(blkSrc, blkDest))
6473         {
6474             /* Do we have a filter clause? */
6475             if (srcHndTab->HasFilter())
6476             {
6477                 /* filters and catch handlers share same eh index  */
6478                 /* we need to check for control flow between them. */
6479                 if (srcInFilter != destInFilter)
6480                 {
6481                     if (!jitIsBetween(blkDest->bbCodeOffs, srcHndBeg, srcHndEnd))
6482                     {
6483                         BADCODE3("Illegal control flow between filter and handler", ". Before offset %04X",
6484                                  blkSrc->bbCodeOffsEnd);
6485                     }
6486                 }
6487             }
6488         }
6489         else
6490         {
6491             /* The handler indexes of blkSrc and blkDest are different */
6492             if (isLeave)
6493             {
6494                 /* Any leave instructions must not enter the dest handler from outside*/
6495                 if (!jitIsBetween(srcHndBeg, destHndBeg, destHndEnd))
6496                 {
6497                     BADCODE3("Illegal use of leave to enter handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6498                 }
6499             }
6500             else
6501             {
6502                 /* We must use a leave to exit a handler */
6503                 BADCODE3("Illegal control flow out of a handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6504             }
6505
6506             /* Do we have a filter clause? */
6507             if (srcHndTab->HasFilter())
6508             {
6509                 /* It is ok to leave from the handler block of a filter, */
6510                 /* but not from the filter block of a filter             */
6511                 if (srcInFilter != destInFilter)
6512                 {
6513                     BADCODE3("Illegal to leave a filter handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6514                 }
6515             }
6516
6517             /* We should never leave a finally handler */
6518             if (srcHndTab->HasFinallyHandler())
6519             {
6520                 BADCODE3("Illegal to leave a finally handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6521             }
6522
6523             /* We should never leave a fault handler */
6524             if (srcHndTab->HasFaultHandler())
6525             {
6526                 BADCODE3("Illegal to leave a fault handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6527             }
6528         }
6529     }
6530     else if (blkDest->hasHndIndex())
6531     {
6532         /* blkSrc was not inside a handler, but blkDst is inside a handler */
6533         BADCODE3("Illegal control flow into a handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6534     }
6535
6536     /* Are we jumping from a catch handler into the corresponding try? */
6537     /* VB uses this for "on error goto "                               */
6538
6539     if (isLeave && srcInCatch)
6540     {
6541         // inspect all handlers containing the jump source
6542
6543         bool      bValidJumpToTry   = false; // are we jumping in a valid way from a catch to the corresponding try?
6544         bool      bCatchHandlerOnly = true;  // false if we are jumping out of a non-catch handler
6545         EHblkDsc* ehTableEnd;
6546         EHblkDsc* ehDsc;
6547
6548         for (ehDsc = compHndBBtab, ehTableEnd = compHndBBtab + compHndBBtabCount;
6549              bCatchHandlerOnly && ehDsc < ehTableEnd; ehDsc++)
6550         {
6551             if (ehDsc->InHndRegionILRange(blkSrc))
6552             {
6553                 if (ehDsc->HasCatchHandler())
6554                 {
6555                     if (ehDsc->InTryRegionILRange(blkDest))
6556                     {
6557                         // If we already considered the jump for a different try/catch,
6558                         // we would have two overlapping try regions with two overlapping catch
6559                         // regions, which is illegal.
6560                         noway_assert(!bValidJumpToTry);
6561
6562                         // Allowed if it is the first instruction of an inner try
6563                         // (and all trys in between)
6564                         //
6565                         // try {
6566                         //  ..
6567                         // _tryAgain:
6568                         //  ..
6569                         //      try {
6570                         //      _tryNestedInner:
6571                         //        ..
6572                         //          try {
6573                         //          _tryNestedIllegal:
6574                         //            ..
6575                         //          } catch {
6576                         //            ..
6577                         //          }
6578                         //        ..
6579                         //      } catch {
6580                         //        ..
6581                         //      }
6582                         //  ..
6583                         // } catch {
6584                         //  ..
6585                         //  leave _tryAgain         // Allowed
6586                         //  ..
6587                         //  leave _tryNestedInner   // Allowed
6588                         //  ..
6589                         //  leave _tryNestedIllegal // Not Allowed
6590                         //  ..
6591                         // }
6592                         //
6593                         // Note: The leave is allowed also from catches nested inside the catch shown above.
6594
6595                         /* The common case where leave is to the corresponding try */
6596                         if (ehDsc->ebdIsSameTry(this, blkDest->getTryIndex()) ||
6597                             /* Also allowed is a leave to the start of a try which starts in the handler's try */
6598                             fgFlowToFirstBlockOfInnerTry(ehDsc->ebdTryBeg, blkDest, false))
6599                         {
6600                             bValidJumpToTry = true;
6601                         }
6602                     }
6603                 }
6604                 else
6605                 {
6606                     // We are jumping from a handler which is not a catch handler.
6607
6608                     // If it's a handler, but not a catch handler, it must be either a finally or fault
6609                     if (!ehDsc->HasFinallyOrFaultHandler())
6610                     {
6611                         BADCODE3("Handlers must be catch, finally, or fault", ". Before offset %04X",
6612                                  blkSrc->bbCodeOffsEnd);
6613                     }
6614
6615                     // Are we jumping out of this handler?
6616                     if (!ehDsc->InHndRegionILRange(blkDest))
6617                     {
6618                         bCatchHandlerOnly = false;
6619                     }
6620                 }
6621             }
6622             else if (ehDsc->InFilterRegionILRange(blkSrc))
6623             {
6624                 // Are we jumping out of a filter?
6625                 if (!ehDsc->InFilterRegionILRange(blkDest))
6626                 {
6627                     bCatchHandlerOnly = false;
6628                 }
6629             }
6630         }
6631
6632         if (bCatchHandlerOnly)
6633         {
6634             if (bValidJumpToTry)
6635             {
6636                 return;
6637             }
6638             else
6639             {
6640                 // FALL THROUGH
6641                 // This is either the case of a leave to outside the try/catch,
6642                 // or a leave to a try not nested in this try/catch.
6643                 // The first case is allowed, the second one will be checked
6644                 // later when we check the try block rules (it is illegal if we
6645                 // jump to the middle of the destination try).
6646             }
6647         }
6648         else
6649         {
6650             BADCODE3("illegal leave to exit a finally, fault or filter", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6651         }
6652     }
6653
6654     /* Check all the try block rules */
6655
6656     IL_OFFSET srcTryBeg;
6657     IL_OFFSET srcTryEnd;
6658     IL_OFFSET destTryBeg;
6659     IL_OFFSET destTryEnd;
6660
6661     ehInitTryRange(blkSrc, &srcTryBeg, &srcTryEnd);
6662     ehInitTryRange(blkDest, &destTryBeg, &destTryEnd);
6663
6664     /* Are we jumping between try indexes? */
6665     if (!BasicBlock::sameTryRegion(blkSrc, blkDest))
6666     {
6667         // Are we exiting from an inner to outer try?
6668         if (jitIsBetween(srcTryBeg, destTryBeg, destTryEnd) && jitIsBetween(srcTryEnd - 1, destTryBeg, destTryEnd))
6669         {
6670             if (!isLeave)
6671             {
6672                 BADCODE3("exit from try block without a leave", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6673             }
6674         }
6675         else if (jitIsBetween(destTryBeg, srcTryBeg, srcTryEnd))
6676         {
6677             // check that the dest Try is first instruction of an inner try
6678             if (!fgFlowToFirstBlockOfInnerTry(blkSrc, blkDest, false))
6679             {
6680                 BADCODE3("control flow into middle of try", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6681             }
6682         }
6683         else // there is no nesting relationship between src and dest
6684         {
6685             if (isLeave)
6686             {
6687                 // check that the dest Try is first instruction of an inner try sibling
6688                 if (!fgFlowToFirstBlockOfInnerTry(blkSrc, blkDest, true))
6689                 {
6690                     BADCODE3("illegal leave into middle of try", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6691                 }
6692             }
6693             else
6694             {
6695                 BADCODE3("illegal control flow in to/out of try block", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6696             }
6697         }
6698     }
6699 }
6700
6701 /*****************************************************************************
6702  *  Check that blkDest is the first block of an inner try or a sibling
6703  *    with no intervening trys in between
6704  */
6705
6706 bool Compiler::fgFlowToFirstBlockOfInnerTry(BasicBlock* blkSrc, BasicBlock* blkDest, bool sibling)
6707 {
6708     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6709
6710     noway_assert(blkDest->hasTryIndex());
6711
6712     unsigned XTnum     = blkDest->getTryIndex();
6713     unsigned lastXTnum = blkSrc->hasTryIndex() ? blkSrc->getTryIndex() : compHndBBtabCount;
6714     noway_assert(XTnum < compHndBBtabCount);
6715     noway_assert(lastXTnum <= compHndBBtabCount);
6716
6717     EHblkDsc* HBtab = ehGetDsc(XTnum);
6718
6719     // check that we are not jumping into middle of try
6720     if (HBtab->ebdTryBeg != blkDest)
6721     {
6722         return false;
6723     }
6724
6725     if (sibling)
6726     {
6727         noway_assert(!BasicBlock::sameTryRegion(blkSrc, blkDest));
6728
6729         // find the l.u.b of the two try ranges
6730         // Set lastXTnum to the l.u.b.
6731
6732         HBtab = ehGetDsc(lastXTnum);
6733
6734         for (lastXTnum++, HBtab++; lastXTnum < compHndBBtabCount; lastXTnum++, HBtab++)
6735         {
6736             if (jitIsBetweenInclusive(blkDest->bbNum, HBtab->ebdTryBeg->bbNum, HBtab->ebdTryLast->bbNum))
6737             {
6738                 break;
6739             }
6740         }
6741     }
6742
6743     // now check there are no intervening trys between dest and l.u.b
6744     // (it is ok to have intervening trys as long as they all start at
6745     //  the same code offset)
6746
6747     HBtab = ehGetDsc(XTnum);
6748
6749     for (XTnum++, HBtab++; XTnum < lastXTnum; XTnum++, HBtab++)
6750     {
6751         if (HBtab->ebdTryBeg->bbNum < blkDest->bbNum && blkDest->bbNum <= HBtab->ebdTryLast->bbNum)
6752         {
6753             return false;
6754         }
6755     }
6756
6757     return true;
6758 }
6759
6760 /*****************************************************************************
6761  *  Returns the handler nesting level of the block.
6762  *  *pFinallyNesting is set to the nesting level of the inner-most
6763  *  finally-protected try the block is in.
6764  */
6765
6766 unsigned Compiler::fgGetNestingLevel(BasicBlock* block, unsigned* pFinallyNesting)
6767 {
6768     unsigned  curNesting = 0;            // How many handlers is the block in
6769     unsigned  tryFin     = (unsigned)-1; // curNesting when we see innermost finally-protected try
6770     unsigned  XTnum;
6771     EHblkDsc* HBtab;
6772
6773     /* We find the block's handler nesting level by walking over the
6774        complete exception table and find enclosing clauses. */
6775
6776     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
6777     {
6778         noway_assert(HBtab->ebdTryBeg && HBtab->ebdHndBeg);
6779
6780         if (HBtab->HasFinallyHandler() && (tryFin == (unsigned)-1) && bbInTryRegions(XTnum, block))
6781         {
6782             tryFin = curNesting;
6783         }
6784         else if (bbInHandlerRegions(XTnum, block))
6785         {
6786             curNesting++;
6787         }
6788     }
6789
6790     if (tryFin == (unsigned)-1)
6791     {
6792         tryFin = curNesting;
6793     }
6794
6795     if (pFinallyNesting)
6796     {
6797         *pFinallyNesting = curNesting - tryFin;
6798     }
6799
6800     return curNesting;
6801 }
6802
6803 /*****************************************************************************
6804  *
6805  *  Import the basic blocks of the procedure.
6806  */
6807
6808 void Compiler::fgImport()
6809 {
6810     fgHasPostfix = false;
6811
6812     impImport(fgFirstBB);
6813
6814     if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION))
6815     {
6816         CorInfoMethodRuntimeFlags verFlag;
6817         verFlag = tiIsVerifiableCode ? CORINFO_FLG_VERIFIABLE : CORINFO_FLG_UNVERIFIABLE;
6818         info.compCompHnd->setMethodAttribs(info.compMethodHnd, verFlag);
6819     }
6820 }
6821
6822 /*****************************************************************************
6823  * This function returns true if tree is a node with a call
6824  * that unconditionally throws an exception
6825  */
6826
6827 bool Compiler::fgIsThrow(GenTree* tree)
6828 {
6829     if ((tree->gtOper != GT_CALL) || (tree->gtCall.gtCallType != CT_HELPER))
6830     {
6831         return false;
6832     }
6833
6834     // TODO-Throughput: Replace all these calls to eeFindHelper() with a table based lookup
6835
6836     if ((tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_OVERFLOW)) ||
6837         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_VERIFICATION)) ||
6838         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_RNGCHKFAIL)) ||
6839         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWDIVZERO)) ||
6840         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWNULLREF)) ||
6841         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW)) ||
6842         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_RETHROW)) ||
6843         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED)) ||
6844         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED)))
6845     {
6846         noway_assert(tree->gtFlags & GTF_CALL);
6847         noway_assert(tree->gtFlags & GTF_EXCEPT);
6848         return true;
6849     }
6850
6851     // TODO-CQ: there are a bunch of managed methods in [mscorlib]System.ThrowHelper
6852     // that would be nice to recognize.
6853
6854     return false;
6855 }
6856
6857 /*****************************************************************************
6858  * This function returns true for blocks that are in different hot-cold regions.
6859  * It returns false when the blocks are both in the same regions
6860  */
6861
6862 bool Compiler::fgInDifferentRegions(BasicBlock* blk1, BasicBlock* blk2)
6863 {
6864     noway_assert(blk1 != nullptr);
6865     noway_assert(blk2 != nullptr);
6866
6867     if (fgFirstColdBlock == nullptr)
6868     {
6869         return false;
6870     }
6871
6872     // If one block is Hot and the other is Cold then we are in different regions
6873     return ((blk1->bbFlags & BBF_COLD) != (blk2->bbFlags & BBF_COLD));
6874 }
6875
6876 bool Compiler::fgIsBlockCold(BasicBlock* blk)
6877 {
6878     noway_assert(blk != nullptr);
6879
6880     if (fgFirstColdBlock == nullptr)
6881     {
6882         return false;
6883     }
6884
6885     return ((blk->bbFlags & BBF_COLD) != 0);
6886 }
6887
6888 /*****************************************************************************
6889  * This function returns true if tree is a GT_COMMA node with a call
6890  * that unconditionally throws an exception
6891  */
6892
6893 bool Compiler::fgIsCommaThrow(GenTree* tree, bool forFolding /* = false */)
6894 {
6895     // Instead of always folding comma throws,
6896     // with stress enabled we only fold half the time
6897
6898     if (forFolding && compStressCompile(STRESS_FOLD, 50))
6899     {
6900         return false; /* Don't fold */
6901     }
6902
6903     /* Check for cast of a GT_COMMA with a throw overflow */
6904     if ((tree->gtOper == GT_COMMA) && (tree->gtFlags & GTF_CALL) && (tree->gtFlags & GTF_EXCEPT))
6905     {
6906         return (fgIsThrow(tree->gtOp.gtOp1));
6907     }
6908     return false;
6909 }
6910
6911 //------------------------------------------------------------------------
6912 // fgIsIndirOfAddrOfLocal: Determine whether "tree" is an indirection of a local.
6913 //
6914 // Arguments:
6915 //    tree - The tree node under consideration
6916 //
6917 // Return Value:
6918 //    If "tree" is a indirection (GT_IND, GT_BLK, or GT_OBJ) whose arg is an ADDR,
6919 //    whose arg in turn is a LCL_VAR, return that LCL_VAR node, else nullptr.
6920 //
6921 // static
6922 GenTree* Compiler::fgIsIndirOfAddrOfLocal(GenTree* tree)
6923 {
6924     GenTree* res = nullptr;
6925     if (tree->OperIsIndir())
6926     {
6927         GenTree* addr = tree->AsIndir()->Addr();
6928
6929         // Post rationalization, we can have Indir(Lea(..) trees. Therefore to recognize
6930         // Indir of addr of a local, skip over Lea in Indir(Lea(base, index, scale, offset))
6931         // to get to base variable.
6932         if (addr->OperGet() == GT_LEA)
6933         {
6934             // We use this method in backward dataflow after liveness computation - fgInterBlockLocalVarLiveness().
6935             // Therefore it is critical that we don't miss 'uses' of any local.  It may seem this method overlooks
6936             // if the index part of the LEA has indir( someAddrOperator ( lclVar ) ) to search for a use but it's
6937             // covered by the fact we're traversing the expression in execution order and we also visit the index.
6938             GenTreeAddrMode* lea  = addr->AsAddrMode();
6939             GenTree*         base = lea->Base();
6940
6941             if (base != nullptr)
6942             {
6943                 if (base->OperGet() == GT_IND)
6944                 {
6945                     return fgIsIndirOfAddrOfLocal(base);
6946                 }
6947                 // else use base as addr
6948                 addr = base;
6949             }
6950         }
6951
6952         if (addr->OperGet() == GT_ADDR)
6953         {
6954             GenTree* lclvar = addr->gtOp.gtOp1;
6955             if (lclvar->OperGet() == GT_LCL_VAR)
6956             {
6957                 res = lclvar;
6958             }
6959         }
6960         else if (addr->OperGet() == GT_LCL_VAR_ADDR)
6961         {
6962             res = addr;
6963         }
6964     }
6965     return res;
6966 }
6967
6968 GenTreeCall* Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfoHelpFunc helper)
6969 {
6970     bool     bNeedClassID = true;
6971     unsigned callFlags    = 0;
6972
6973     var_types type = TYP_BYREF;
6974
6975     // This is sort of ugly, as we have knowledge of what the helper is returning.
6976     // We need the return type.
6977     switch (helper)
6978     {
6979         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
6980             bNeedClassID = false;
6981             __fallthrough;
6982
6983         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
6984             callFlags |= GTF_CALL_HOISTABLE;
6985             __fallthrough;
6986
6987         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
6988         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
6989         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
6990         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
6991         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
6992             // type = TYP_BYREF;
6993             break;
6994
6995         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
6996             bNeedClassID = false;
6997             __fallthrough;
6998
6999         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
7000             callFlags |= GTF_CALL_HOISTABLE;
7001             __fallthrough;
7002
7003         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
7004         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
7005         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
7006         case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
7007             type = TYP_I_IMPL;
7008             break;
7009
7010         default:
7011             assert(!"unknown shared statics helper");
7012             break;
7013     }
7014
7015     GenTreeArgList* argList = nullptr;
7016
7017     GenTree* opModuleIDArg;
7018     GenTree* opClassIDArg;
7019
7020     // Get the class ID
7021     unsigned clsID;
7022     size_t   moduleID;
7023     void*    pclsID;
7024     void*    pmoduleID;
7025
7026     clsID = info.compCompHnd->getClassDomainID(cls, &pclsID);
7027
7028     moduleID = info.compCompHnd->getClassModuleIdForStatics(cls, nullptr, &pmoduleID);
7029
7030     if (!(callFlags & GTF_CALL_HOISTABLE))
7031     {
7032         if (info.compCompHnd->getClassAttribs(cls) & CORINFO_FLG_BEFOREFIELDINIT)
7033         {
7034             callFlags |= GTF_CALL_HOISTABLE;
7035         }
7036     }
7037
7038     if (pmoduleID)
7039     {
7040         opModuleIDArg = gtNewIndOfIconHandleNode(TYP_I_IMPL, (size_t)pmoduleID, GTF_ICON_CIDMID_HDL, true);
7041     }
7042     else
7043     {
7044         opModuleIDArg = gtNewIconNode((size_t)moduleID, TYP_I_IMPL);
7045     }
7046
7047     if (bNeedClassID)
7048     {
7049         if (pclsID)
7050         {
7051             opClassIDArg = gtNewIndOfIconHandleNode(TYP_INT, (size_t)pclsID, GTF_ICON_CIDMID_HDL, true);
7052         }
7053         else
7054         {
7055             opClassIDArg = gtNewIconNode(clsID, TYP_INT);
7056         }
7057
7058         // call the helper to get the base
7059         argList = gtNewArgList(opModuleIDArg, opClassIDArg);
7060     }
7061     else
7062     {
7063         argList = gtNewArgList(opModuleIDArg);
7064     }
7065
7066     GenTreeCall* result = gtNewHelperCallNode(helper, type, argList);
7067     result->gtFlags |= callFlags;
7068
7069     // If we're importing the special EqualityComparer<T>.Default
7070     // intrinsic, flag the helper call. Later during inlining, we can
7071     // remove the helper call if the associated field lookup is unused.
7072     if ((info.compFlags & CORINFO_FLG_JIT_INTRINSIC) != 0)
7073     {
7074         NamedIntrinsic ni = lookupNamedIntrinsic(info.compMethodHnd);
7075         if (ni == NI_System_Collections_Generic_EqualityComparer_get_Default)
7076         {
7077             JITDUMP("\nmarking helper call [06%u] as special dce...\n", result->gtTreeID);
7078             result->gtCallMoreFlags |= GTF_CALL_M_HELPER_SPECIAL_DCE;
7079         }
7080     }
7081
7082     return result;
7083 }
7084
7085 GenTreeCall* Compiler::fgGetSharedCCtor(CORINFO_CLASS_HANDLE cls)
7086 {
7087 #ifdef FEATURE_READYTORUN_COMPILER
7088     if (opts.IsReadyToRun())
7089     {
7090         CORINFO_RESOLVED_TOKEN resolvedToken;
7091         memset(&resolvedToken, 0, sizeof(resolvedToken));
7092         resolvedToken.hClass = cls;
7093
7094         return impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_STATIC_BASE, TYP_BYREF);
7095     }
7096 #endif
7097
7098     // Call the shared non gc static helper, as its the fastest
7099     return fgGetStaticsCCtorHelper(cls, info.compCompHnd->getSharedCCtorHelper(cls));
7100 }
7101
7102 //------------------------------------------------------------------------------
7103 // fgAddrCouldBeNull : Check whether the address tree can represent null.
7104 //
7105 //
7106 // Arguments:
7107 //    addr     -  Address to check
7108 //
7109 // Return Value:
7110 //    True if address could be null; false otherwise
7111
7112 bool Compiler::fgAddrCouldBeNull(GenTree* addr)
7113 {
7114     addr = addr->gtEffectiveVal();
7115     if ((addr->gtOper == GT_CNS_INT) && addr->IsIconHandle())
7116     {
7117         return false;
7118     }
7119     else if (addr->gtOper == GT_LCL_VAR)
7120     {
7121         unsigned varNum = addr->AsLclVarCommon()->GetLclNum();
7122
7123         if (lvaIsImplicitByRefLocal(varNum))
7124         {
7125             return false;
7126         }
7127
7128         LclVarDsc* varDsc = &lvaTable[varNum];
7129
7130         if (varDsc->lvStackByref)
7131         {
7132             return false;
7133         }
7134     }
7135     else if (addr->gtOper == GT_ADDR)
7136     {
7137         if (addr->gtOp.gtOp1->gtOper == GT_CNS_INT)
7138         {
7139             GenTree* cns1Tree = addr->gtOp.gtOp1;
7140             if (!cns1Tree->IsIconHandle())
7141             {
7142                 // Indirection of some random constant...
7143                 // It is safest just to return true
7144                 return true;
7145             }
7146         }
7147
7148         return false; // we can't have a null address
7149     }
7150     else if (addr->gtOper == GT_ADD)
7151     {
7152         if (addr->gtOp.gtOp1->gtOper == GT_CNS_INT)
7153         {
7154             GenTree* cns1Tree = addr->gtOp.gtOp1;
7155             if (!cns1Tree->IsIconHandle())
7156             {
7157                 if (!fgIsBigOffset(cns1Tree->gtIntCon.gtIconVal))
7158                 {
7159                     // Op1 was an ordinary small constant
7160                     return fgAddrCouldBeNull(addr->gtOp.gtOp2);
7161                 }
7162             }
7163             else // Op1 was a handle represented as a constant
7164             {
7165                 // Is Op2 also a constant?
7166                 if (addr->gtOp.gtOp2->gtOper == GT_CNS_INT)
7167                 {
7168                     GenTree* cns2Tree = addr->gtOp.gtOp2;
7169                     // Is this an addition of a handle and constant
7170                     if (!cns2Tree->IsIconHandle())
7171                     {
7172                         if (!fgIsBigOffset(cns2Tree->gtIntCon.gtIconVal))
7173                         {
7174                             // Op2 was an ordinary small constant
7175                             return false; // we can't have a null address
7176                         }
7177                     }
7178                 }
7179             }
7180         }
7181         else
7182         {
7183             // Op1 is not a constant
7184             // What about Op2?
7185             if (addr->gtOp.gtOp2->gtOper == GT_CNS_INT)
7186             {
7187                 GenTree* cns2Tree = addr->gtOp.gtOp2;
7188                 // Is this an addition of a small constant
7189                 if (!cns2Tree->IsIconHandle())
7190                 {
7191                     if (!fgIsBigOffset(cns2Tree->gtIntCon.gtIconVal))
7192                     {
7193                         // Op2 was an ordinary small constant
7194                         return fgAddrCouldBeNull(addr->gtOp.gtOp1);
7195                     }
7196                 }
7197             }
7198         }
7199     }
7200     return true; // default result: addr could be null
7201 }
7202
7203 //------------------------------------------------------------------------------
7204 // fgOptimizeDelegateConstructor: try and optimize construction of a delegate
7205 //
7206 // Arguments:
7207 //    call -- call to original delegate constructor
7208 //    exactContextHnd -- [out] context handle to update
7209 //    ldftnToken -- [in]  resolved token for the method the delegate will invoke,
7210 //      if known, or nullptr if not known
7211 //
7212 // Return Value:
7213 //    Original call tree if no optimization applies.
7214 //    Updated call tree if optimized.
7215
7216 GenTree* Compiler::fgOptimizeDelegateConstructor(GenTreeCall*            call,
7217                                                  CORINFO_CONTEXT_HANDLE* ExactContextHnd,
7218                                                  CORINFO_RESOLVED_TOKEN* ldftnToken)
7219 {
7220     JITDUMP("\nfgOptimizeDelegateConstructor: ");
7221     noway_assert(call->gtCallType == CT_USER_FUNC);
7222     CORINFO_METHOD_HANDLE methHnd = call->gtCallMethHnd;
7223     CORINFO_CLASS_HANDLE  clsHnd  = info.compCompHnd->getMethodClass(methHnd);
7224
7225     GenTree* targetMethod = call->gtCallArgs->Rest()->Current();
7226     noway_assert(targetMethod->TypeGet() == TYP_I_IMPL);
7227     genTreeOps            oper            = targetMethod->OperGet();
7228     CORINFO_METHOD_HANDLE targetMethodHnd = nullptr;
7229     GenTree*              qmarkNode       = nullptr;
7230     if (oper == GT_FTN_ADDR)
7231     {
7232         targetMethodHnd = targetMethod->gtFptrVal.gtFptrMethod;
7233     }
7234     else if (oper == GT_CALL && targetMethod->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_VIRTUAL_FUNC_PTR))
7235     {
7236         GenTree* handleNode = targetMethod->gtCall.gtCallArgs->Rest()->Rest()->Current();
7237
7238         if (handleNode->OperGet() == GT_CNS_INT)
7239         {
7240             // it's a ldvirtftn case, fetch the methodhandle off the helper for ldvirtftn. It's the 3rd arg
7241             targetMethodHnd = CORINFO_METHOD_HANDLE(handleNode->gtIntCon.gtCompileTimeHandle);
7242         }
7243         // Sometimes the argument to this is the result of a generic dictionary lookup, which shows
7244         // up as a GT_QMARK.
7245         else if (handleNode->OperGet() == GT_QMARK)
7246         {
7247             qmarkNode = handleNode;
7248         }
7249     }
7250     // Sometimes we don't call CORINFO_HELP_VIRTUAL_FUNC_PTR but instead just call
7251     // CORINFO_HELP_RUNTIMEHANDLE_METHOD directly.
7252     else if (oper == GT_QMARK)
7253     {
7254         qmarkNode = targetMethod;
7255     }
7256     if (qmarkNode)
7257     {
7258         noway_assert(qmarkNode->OperGet() == GT_QMARK);
7259         // The argument is actually a generic dictionary lookup.  For delegate creation it looks
7260         // like:
7261         // GT_QMARK
7262         //  GT_COLON
7263         //      op1 -> call
7264         //              Arg 1 -> token (has compile time handle)
7265         //      op2 -> lclvar
7266         //
7267         //
7268         // In this case I can find the token (which is a method handle) and that is the compile time
7269         // handle.
7270         noway_assert(qmarkNode->gtOp.gtOp2->OperGet() == GT_COLON);
7271         noway_assert(qmarkNode->gtOp.gtOp2->gtOp.gtOp1->OperGet() == GT_CALL);
7272         GenTreeCall* runtimeLookupCall = qmarkNode->gtOp.gtOp2->gtOp.gtOp1->AsCall();
7273
7274         // This could be any of CORINFO_HELP_RUNTIMEHANDLE_(METHOD|CLASS)(_LOG?)
7275         GenTree* tokenNode = runtimeLookupCall->gtCallArgs->gtOp.gtOp2->gtOp.gtOp1;
7276         noway_assert(tokenNode->OperGet() == GT_CNS_INT);
7277         targetMethodHnd = CORINFO_METHOD_HANDLE(tokenNode->gtIntCon.gtCompileTimeHandle);
7278     }
7279
7280     // Verify using the ldftnToken gives us all of what we used to get
7281     // via the above pattern match, and more...
7282     if (ldftnToken != nullptr)
7283     {
7284         assert(ldftnToken->hMethod != nullptr);
7285
7286         if (targetMethodHnd != nullptr)
7287         {
7288             assert(targetMethodHnd == ldftnToken->hMethod);
7289         }
7290
7291         targetMethodHnd = ldftnToken->hMethod;
7292     }
7293     else
7294     {
7295         assert(targetMethodHnd == nullptr);
7296     }
7297
7298 #ifdef FEATURE_READYTORUN_COMPILER
7299     if (opts.IsReadyToRun())
7300     {
7301         if (IsTargetAbi(CORINFO_CORERT_ABI))
7302         {
7303             if (ldftnToken != nullptr)
7304             {
7305                 JITDUMP("optimized\n");
7306
7307                 GenTree*             thisPointer       = call->gtCallObjp;
7308                 GenTree*             targetObjPointers = call->gtCallArgs->Current();
7309                 GenTreeArgList*      helperArgs        = nullptr;
7310                 CORINFO_LOOKUP       pLookup;
7311                 CORINFO_CONST_LOOKUP entryPoint;
7312                 info.compCompHnd->getReadyToRunDelegateCtorHelper(ldftnToken, clsHnd, &pLookup);
7313                 if (!pLookup.lookupKind.needsRuntimeLookup)
7314                 {
7315                     helperArgs = gtNewArgList(thisPointer, targetObjPointers);
7316                     entryPoint = pLookup.constLookup;
7317                 }
7318                 else
7319                 {
7320                     assert(oper != GT_FTN_ADDR);
7321                     CORINFO_CONST_LOOKUP genericLookup;
7322                     info.compCompHnd->getReadyToRunHelper(ldftnToken, &pLookup.lookupKind,
7323                                                           CORINFO_HELP_READYTORUN_GENERIC_HANDLE, &genericLookup);
7324                     GenTree* ctxTree = getRuntimeContextTree(pLookup.lookupKind.runtimeLookupKind);
7325                     helperArgs       = gtNewArgList(thisPointer, targetObjPointers, ctxTree);
7326                     entryPoint       = genericLookup;
7327                 }
7328                 call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, helperArgs);
7329                 call->setEntryPoint(entryPoint);
7330             }
7331             else
7332             {
7333                 JITDUMP("not optimized, CORERT no ldftnToken\n");
7334             }
7335         }
7336         // ReadyToRun has this optimization for a non-virtual function pointers only for now.
7337         else if (oper == GT_FTN_ADDR)
7338         {
7339             JITDUMP("optimized\n");
7340
7341             GenTree*        thisPointer       = call->gtCallObjp;
7342             GenTree*        targetObjPointers = call->gtCallArgs->Current();
7343             GenTreeArgList* helperArgs        = gtNewArgList(thisPointer, targetObjPointers);
7344
7345             call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, helperArgs);
7346
7347             CORINFO_LOOKUP entryPoint;
7348             info.compCompHnd->getReadyToRunDelegateCtorHelper(ldftnToken, clsHnd, &entryPoint);
7349             assert(!entryPoint.lookupKind.needsRuntimeLookup);
7350             call->setEntryPoint(entryPoint.constLookup);
7351         }
7352         else
7353         {
7354             JITDUMP("not optimized, R2R virtual case\n");
7355         }
7356     }
7357     else
7358 #endif
7359         if (targetMethodHnd != nullptr)
7360     {
7361         CORINFO_METHOD_HANDLE alternateCtor = nullptr;
7362         DelegateCtorArgs      ctorData;
7363         ctorData.pMethod = info.compMethodHnd;
7364         ctorData.pArg3   = nullptr;
7365         ctorData.pArg4   = nullptr;
7366         ctorData.pArg5   = nullptr;
7367
7368         alternateCtor = info.compCompHnd->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, &ctorData);
7369         if (alternateCtor != methHnd)
7370         {
7371             JITDUMP("optimized\n");
7372             // we erase any inline info that may have been set for generics has it is not needed here,
7373             // and in fact it will pass the wrong info to the inliner code
7374             *ExactContextHnd = nullptr;
7375
7376             call->gtCallMethHnd = alternateCtor;
7377
7378             noway_assert(call->gtCallArgs->Rest()->Rest() == nullptr);
7379             GenTreeArgList* addArgs = nullptr;
7380             if (ctorData.pArg5)
7381             {
7382                 GenTree* arg5 = gtNewIconHandleNode(size_t(ctorData.pArg5), GTF_ICON_FTN_ADDR);
7383                 addArgs       = gtNewListNode(arg5, addArgs);
7384             }
7385             if (ctorData.pArg4)
7386             {
7387                 GenTree* arg4 = gtNewIconHandleNode(size_t(ctorData.pArg4), GTF_ICON_FTN_ADDR);
7388                 addArgs       = gtNewListNode(arg4, addArgs);
7389             }
7390             if (ctorData.pArg3)
7391             {
7392                 GenTree* arg3 = gtNewIconHandleNode(size_t(ctorData.pArg3), GTF_ICON_FTN_ADDR);
7393                 addArgs       = gtNewListNode(arg3, addArgs);
7394             }
7395             call->gtCallArgs->Rest()->Rest() = addArgs;
7396         }
7397         else
7398         {
7399             JITDUMP("not optimized, no alternate ctor\n");
7400         }
7401     }
7402     else
7403     {
7404         JITDUMP("not optimized, no target method\n");
7405     }
7406     return call;
7407 }
7408
7409 bool Compiler::fgCastNeeded(GenTree* tree, var_types toType)
7410 {
7411     //
7412     // If tree is a relop and we need an 4-byte integer
7413     //  then we never need to insert a cast
7414     //
7415     if ((tree->OperKind() & GTK_RELOP) && (genActualType(toType) == TYP_INT))
7416     {
7417         return false;
7418     }
7419
7420     var_types fromType;
7421
7422     //
7423     // Is the tree as GT_CAST or a GT_CALL ?
7424     //
7425     if (tree->OperGet() == GT_CAST)
7426     {
7427         fromType = tree->CastToType();
7428     }
7429     else if (tree->OperGet() == GT_CALL)
7430     {
7431         fromType = (var_types)tree->gtCall.gtReturnType;
7432     }
7433     else
7434     {
7435         fromType = tree->TypeGet();
7436     }
7437
7438     //
7439     // If both types are the same then an additional cast is not necessary
7440     //
7441     if (toType == fromType)
7442     {
7443         return false;
7444     }
7445     //
7446     // If the sign-ness of the two types are different then a cast is necessary
7447     //
7448     if (varTypeIsUnsigned(toType) != varTypeIsUnsigned(fromType))
7449     {
7450         return true;
7451     }
7452     //
7453     // If the from type is the same size or smaller then an additional cast is not necessary
7454     //
7455     if (genTypeSize(toType) >= genTypeSize(fromType))
7456     {
7457         return false;
7458     }
7459
7460     //
7461     // Looks like we will need the cast
7462     //
7463     return true;
7464 }
7465
7466 // If assigning to a local var, add a cast if the target is
7467 // marked as NormalizedOnStore. Returns true if any change was made
7468 GenTree* Compiler::fgDoNormalizeOnStore(GenTree* tree)
7469 {
7470     //
7471     // Only normalize the stores in the global morph phase
7472     //
7473     if (fgGlobalMorph)
7474     {
7475         noway_assert(tree->OperGet() == GT_ASG);
7476
7477         GenTree* op1 = tree->gtOp.gtOp1;
7478         GenTree* op2 = tree->gtOp.gtOp2;
7479
7480         if (op1->gtOper == GT_LCL_VAR && genActualType(op1->TypeGet()) == TYP_INT)
7481         {
7482             // Small-typed arguments and aliased locals are normalized on load.
7483             // Other small-typed locals are normalized on store.
7484             // If it is an assignment to one of the latter, insert the cast on RHS
7485             unsigned   varNum = op1->gtLclVarCommon.gtLclNum;
7486             LclVarDsc* varDsc = &lvaTable[varNum];
7487
7488             if (varDsc->lvNormalizeOnStore())
7489             {
7490                 noway_assert(op1->gtType <= TYP_INT);
7491                 op1->gtType = TYP_INT;
7492
7493                 if (fgCastNeeded(op2, varDsc->TypeGet()))
7494                 {
7495                     op2              = gtNewCastNode(TYP_INT, op2, false, varDsc->TypeGet());
7496                     tree->gtOp.gtOp2 = op2;
7497
7498                     // Propagate GTF_COLON_COND
7499                     op2->gtFlags |= (tree->gtFlags & GTF_COLON_COND);
7500                 }
7501             }
7502         }
7503     }
7504
7505     return tree;
7506 }
7507
7508 /*****************************************************************************
7509  *
7510  *  Mark whether the edge "srcBB -> dstBB" forms a loop that will always
7511  *  execute a call or not.
7512  */
7513
7514 inline void Compiler::fgLoopCallTest(BasicBlock* srcBB, BasicBlock* dstBB)
7515 {
7516     /* Bail if this is not a backward edge */
7517
7518     if (srcBB->bbNum < dstBB->bbNum)
7519     {
7520         return;
7521     }
7522
7523     /* Unless we already know that there is a loop without a call here ... */
7524
7525     if (!(dstBB->bbFlags & BBF_LOOP_CALL0))
7526     {
7527         /* Check whether there is a loop path that doesn't call */
7528
7529         if (optReachWithoutCall(dstBB, srcBB))
7530         {
7531             dstBB->bbFlags |= BBF_LOOP_CALL0;
7532             dstBB->bbFlags &= ~BBF_LOOP_CALL1;
7533         }
7534         else
7535         {
7536             dstBB->bbFlags |= BBF_LOOP_CALL1;
7537         }
7538     }
7539     // if this loop will always call, then we can omit the GC Poll
7540     if ((GCPOLL_NONE != opts.compGCPollType) && (dstBB->bbFlags & BBF_LOOP_CALL1))
7541     {
7542         srcBB->bbFlags &= ~BBF_NEEDS_GCPOLL;
7543     }
7544 }
7545
7546 /*****************************************************************************
7547  *
7548  *  Mark which loops are guaranteed to execute a call.
7549  */
7550
7551 void Compiler::fgLoopCallMark()
7552 {
7553     BasicBlock* block;
7554
7555     /* If we've already marked all the block, bail */
7556
7557     if (fgLoopCallMarked)
7558     {
7559         return;
7560     }
7561
7562     fgLoopCallMarked = true;
7563
7564     /* Walk the blocks, looking for backward edges */
7565
7566     for (block = fgFirstBB; block; block = block->bbNext)
7567     {
7568         switch (block->bbJumpKind)
7569         {
7570             case BBJ_COND:
7571             case BBJ_CALLFINALLY:
7572             case BBJ_ALWAYS:
7573             case BBJ_EHCATCHRET:
7574                 fgLoopCallTest(block, block->bbJumpDest);
7575                 break;
7576
7577             case BBJ_SWITCH:
7578
7579                 unsigned jumpCnt;
7580                 jumpCnt = block->bbJumpSwt->bbsCount;
7581                 BasicBlock** jumpPtr;
7582                 jumpPtr = block->bbJumpSwt->bbsDstTab;
7583
7584                 do
7585                 {
7586                     fgLoopCallTest(block, *jumpPtr);
7587                 } while (++jumpPtr, --jumpCnt);
7588
7589                 break;
7590
7591             default:
7592                 break;
7593         }
7594     }
7595 }
7596
7597 /*****************************************************************************
7598  *
7599  *  Note the fact that the given block is a loop header.
7600  */
7601
7602 inline void Compiler::fgMarkLoopHead(BasicBlock* block)
7603 {
7604 #ifdef DEBUG
7605     if (verbose)
7606     {
7607         printf("fgMarkLoopHead: Checking loop head block BB%02u: ", block->bbNum);
7608     }
7609 #endif
7610
7611     /* Have we decided to generate fully interruptible code already? */
7612
7613     if (genInterruptible)
7614     {
7615 #ifdef DEBUG
7616         if (verbose)
7617         {
7618             printf("method is already fully interruptible\n");
7619         }
7620 #endif
7621         return;
7622     }
7623
7624     /* Is the loop head block known to execute a method call? */
7625
7626     if (block->bbFlags & BBF_GC_SAFE_POINT)
7627     {
7628 #ifdef DEBUG
7629         if (verbose)
7630         {
7631             printf("this block will execute a call\n");
7632         }
7633 #endif
7634         // single block loops that contain GC safe points don't need polls.
7635         block->bbFlags &= ~BBF_NEEDS_GCPOLL;
7636         return;
7637     }
7638
7639     /* Are dominator sets available? */
7640
7641     if (fgDomsComputed)
7642     {
7643         /* Make sure that we know which loops will always execute calls */
7644
7645         if (!fgLoopCallMarked)
7646         {
7647             fgLoopCallMark();
7648         }
7649
7650         /* Will every trip through our loop execute a call? */
7651
7652         if (block->bbFlags & BBF_LOOP_CALL1)
7653         {
7654 #ifdef DEBUG
7655             if (verbose)
7656             {
7657                 printf("this block dominates a block that will execute a call\n");
7658             }
7659 #endif
7660             return;
7661         }
7662     }
7663
7664     /*
7665      *  We have to make this method fully interruptible since we can not
7666      *  ensure that this loop will execute a call every time it loops.
7667      *
7668      *  We'll also need to generate a full register map for this method.
7669      */
7670
7671     assert(!codeGen->isGCTypeFixed());
7672
7673     if (!compCanEncodePtrArgCntMax())
7674     {
7675 #ifdef DEBUG
7676         if (verbose)
7677         {
7678             printf("a callsite with more than 1023 pushed args exists\n");
7679         }
7680 #endif
7681         return;
7682     }
7683
7684 #ifdef DEBUG
7685     if (verbose)
7686     {
7687         printf("no guaranteed callsite exits, marking method as fully interruptible\n");
7688     }
7689 #endif
7690
7691     // only enable fully interruptible code for if we're hijacking.
7692     if (GCPOLL_NONE == opts.compGCPollType)
7693     {
7694         genInterruptible = true;
7695     }
7696 }
7697
7698 GenTree* Compiler::fgGetCritSectOfStaticMethod()
7699 {
7700     noway_assert(!compIsForInlining());
7701
7702     noway_assert(info.compIsStatic); // This method should only be called for static methods.
7703
7704     GenTree* tree = nullptr;
7705
7706     CORINFO_LOOKUP_KIND kind = info.compCompHnd->getLocationOfThisType(info.compMethodHnd);
7707
7708     if (!kind.needsRuntimeLookup)
7709     {
7710         void *critSect = nullptr, **pCrit = nullptr;
7711         critSect = info.compCompHnd->getMethodSync(info.compMethodHnd, (void**)&pCrit);
7712         noway_assert((!critSect) != (!pCrit));
7713
7714         tree = gtNewIconEmbHndNode(critSect, pCrit, GTF_ICON_METHOD_HDL, info.compMethodHnd);
7715     }
7716     else
7717     {
7718         // Collectible types requires that for shared generic code, if we use the generic context paramter
7719         // that we report it. (This is a conservative approach, we could detect some cases particularly when the
7720         // context parameter is this that we don't need the eager reporting logic.)
7721         lvaGenericsContextUseCount++;
7722
7723         switch (kind.runtimeLookupKind)
7724         {
7725             case CORINFO_LOOKUP_THISOBJ:
7726             {
7727                 noway_assert(!"Should never get this for static method.");
7728                 break;
7729             }
7730
7731             case CORINFO_LOOKUP_CLASSPARAM:
7732             {
7733                 // In this case, the hidden param is the class handle.
7734                 tree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL);
7735                 break;
7736             }
7737
7738             case CORINFO_LOOKUP_METHODPARAM:
7739             {
7740                 // In this case, the hidden param is the method handle.
7741                 tree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL);
7742                 // Call helper CORINFO_HELP_GETCLASSFROMMETHODPARAM to get the class handle
7743                 // from the method handle.
7744                 tree = gtNewHelperCallNode(CORINFO_HELP_GETCLASSFROMMETHODPARAM, TYP_I_IMPL, gtNewArgList(tree));
7745                 break;
7746             }
7747
7748             default:
7749             {
7750                 noway_assert(!"Unknown LOOKUP_KIND");
7751                 break;
7752             }
7753         }
7754
7755         noway_assert(tree); // tree should now contain the CORINFO_CLASS_HANDLE for the exact class.
7756
7757         // Given the class handle, get the pointer to the Monitor.
7758         tree = gtNewHelperCallNode(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, TYP_I_IMPL, gtNewArgList(tree));
7759     }
7760
7761     noway_assert(tree);
7762     return tree;
7763 }
7764
7765 #if FEATURE_EH_FUNCLETS
7766
7767 /*****************************************************************************
7768  *
7769  *  Add monitor enter/exit calls for synchronized methods, and a try/fault
7770  *  to ensure the 'exit' is called if the 'enter' was successful. On x86, we
7771  *  generate monitor enter/exit calls and tell the VM the code location of
7772  *  these calls. When an exception occurs between those locations, the VM
7773  *  automatically releases the lock. For non-x86 platforms, the JIT is
7774  *  responsible for creating a try/finally to protect the monitor enter/exit,
7775  *  and the VM doesn't need to know anything special about the method during
7776  *  exception processing -- it's just a normal try/finally.
7777  *
7778  *  We generate the following code:
7779  *
7780  *      void Foo()
7781  *      {
7782  *          unsigned byte acquired = 0;
7783  *          try {
7784  *              JIT_MonEnterWorker(<lock object>, &acquired);
7785  *
7786  *              *** all the preexisting user code goes here ***
7787  *
7788  *              JIT_MonExitWorker(<lock object>, &acquired);
7789  *          } fault {
7790  *              JIT_MonExitWorker(<lock object>, &acquired);
7791  *         }
7792  *      L_return:
7793  *         ret
7794  *      }
7795  *
7796  *  If the lock is actually acquired, then the 'acquired' variable is set to 1
7797  *  by the helper call. During normal exit, the finally is called, 'acquired'
7798  *  is 1, and the lock is released. If an exception occurs before the lock is
7799  *  acquired, but within the 'try' (extremely unlikely, but possible), 'acquired'
7800  *  will be 0, and the monitor exit call will quickly return without attempting
7801  *  to release the lock. Otherwise, 'acquired' will be 1, and the lock will be
7802  *  released during exception processing.
7803  *
7804  *  For synchronized methods, we generate a single return block.
7805  *  We can do this without creating additional "step" blocks because "ret" blocks
7806  *  must occur at the top-level (of the original code), not nested within any EH
7807  *  constructs. From the CLI spec, 12.4.2.8.2.3 "ret": "Shall not be enclosed in any
7808  *  protected block, filter, or handler." Also, 3.57: "The ret instruction cannot be
7809  *  used to transfer control out of a try, filter, catch, or finally block. From within
7810  *  a try or catch, use the leave instruction with a destination of a ret instruction
7811  *  that is outside all enclosing exception blocks."
7812  *
7813  *  In addition, we can add a "fault" at the end of a method and be guaranteed that no
7814  *  control falls through. From the CLI spec, section 12.4 "Control flow": "Control is not
7815  *  permitted to simply fall through the end of a method. All paths shall terminate with one
7816  *  of these instructions: ret, throw, jmp, or (tail. followed by call, calli, or callvirt)."
7817  *
7818  *  We only need to worry about "ret" and "throw", as the CLI spec prevents any other
7819  *  alternatives. Section 15.4.3.3 "Implementation information" states about exiting
7820  *  synchronized methods: "Exiting a synchronized method using a tail. call shall be
7821  *  implemented as though the tail. had not been specified." Section 3.37 "jmp" states:
7822  *  "The jmp instruction cannot be used to transferred control out of a try, filter,
7823  *  catch, fault or finally block; or out of a synchronized region." And, "throw" will
7824  *  be handled naturally; no additional work is required.
7825  */
7826
7827 void Compiler::fgAddSyncMethodEnterExit()
7828 {
7829     assert((info.compFlags & CORINFO_FLG_SYNCH) != 0);
7830
7831     // We need to do this transformation before funclets are created.
7832     assert(!fgFuncletsCreated);
7833
7834     // Assume we don't need to update the bbPreds lists.
7835     assert(!fgComputePredsDone);
7836
7837 #if !FEATURE_EH
7838     // If we don't support EH, we can't add the EH needed by synchronized methods.
7839     // Of course, we could simply ignore adding the EH constructs, since we don't
7840     // support exceptions being thrown in this mode, but we would still need to add
7841     // the monitor enter/exit, and that doesn't seem worth it for this minor case.
7842     // By the time EH is working, we can just enable the whole thing.
7843     NYI("No support for synchronized methods");
7844 #endif // !FEATURE_EH
7845
7846     // Create a scratch first BB where we can put the new variable initialization.
7847     // Don't put the scratch BB in the protected region.
7848
7849     fgEnsureFirstBBisScratch();
7850
7851     // Create a block for the start of the try region, where the monitor enter call
7852     // will go.
7853
7854     assert(fgFirstBB->bbFallsThrough());
7855
7856     BasicBlock* tryBegBB  = fgNewBBafter(BBJ_NONE, fgFirstBB, false);
7857     BasicBlock* tryNextBB = tryBegBB->bbNext;
7858     BasicBlock* tryLastBB = fgLastBB;
7859
7860     // If we have profile data the new block will inherit the next block's weight
7861     if (tryNextBB->hasProfileWeight())
7862     {
7863         tryBegBB->inheritWeight(tryNextBB);
7864     }
7865
7866     // Create a block for the fault.
7867
7868     assert(!tryLastBB->bbFallsThrough());
7869     BasicBlock* faultBB = fgNewBBafter(BBJ_EHFINALLYRET, tryLastBB, false);
7870
7871     assert(tryLastBB->bbNext == faultBB);
7872     assert(faultBB->bbNext == nullptr);
7873     assert(faultBB == fgLastBB);
7874
7875     { // Scope the EH region creation
7876
7877         // Add the new EH region at the end, since it is the least nested,
7878         // and thus should be last.
7879
7880         EHblkDsc* newEntry;
7881         unsigned  XTnew = compHndBBtabCount;
7882
7883         newEntry = fgAddEHTableEntry(XTnew);
7884
7885         // Initialize the new entry
7886
7887         newEntry->ebdHandlerType = EH_HANDLER_FAULT;
7888
7889         newEntry->ebdTryBeg  = tryBegBB;
7890         newEntry->ebdTryLast = tryLastBB;
7891
7892         newEntry->ebdHndBeg  = faultBB;
7893         newEntry->ebdHndLast = faultBB;
7894
7895         newEntry->ebdTyp = 0; // unused for fault
7896
7897         newEntry->ebdEnclosingTryIndex = EHblkDsc::NO_ENCLOSING_INDEX;
7898         newEntry->ebdEnclosingHndIndex = EHblkDsc::NO_ENCLOSING_INDEX;
7899
7900         newEntry->ebdTryBegOffset    = tryBegBB->bbCodeOffs;
7901         newEntry->ebdTryEndOffset    = tryLastBB->bbCodeOffsEnd;
7902         newEntry->ebdFilterBegOffset = 0;
7903         newEntry->ebdHndBegOffset    = 0; // handler doesn't correspond to any IL
7904         newEntry->ebdHndEndOffset    = 0; // handler doesn't correspond to any IL
7905
7906         // Set some flags on the new region. This is the same as when we set up
7907         // EH regions in fgFindBasicBlocks(). Note that the try has no enclosing
7908         // handler, and the fault has no enclosing try.
7909
7910         tryBegBB->bbFlags |= BBF_HAS_LABEL | BBF_DONT_REMOVE | BBF_TRY_BEG | BBF_IMPORTED;
7911
7912         faultBB->bbFlags |= BBF_HAS_LABEL | BBF_DONT_REMOVE | BBF_IMPORTED;
7913         faultBB->bbCatchTyp = BBCT_FAULT;
7914
7915         tryBegBB->setTryIndex(XTnew);
7916         tryBegBB->clearHndIndex();
7917
7918         faultBB->clearTryIndex();
7919         faultBB->setHndIndex(XTnew);
7920
7921         // Walk the user code blocks and set all blocks that don't already have a try handler
7922         // to point to the new try handler.
7923
7924         BasicBlock* tmpBB;
7925         for (tmpBB = tryBegBB->bbNext; tmpBB != faultBB; tmpBB = tmpBB->bbNext)
7926         {
7927             if (!tmpBB->hasTryIndex())
7928             {
7929                 tmpBB->setTryIndex(XTnew);
7930             }
7931         }
7932
7933         // Walk the EH table. Make every EH entry that doesn't already have an enclosing
7934         // try index mark this new entry as their enclosing try index.
7935
7936         unsigned  XTnum;
7937         EHblkDsc* HBtab;
7938
7939         for (XTnum = 0, HBtab = compHndBBtab; XTnum < XTnew; XTnum++, HBtab++)
7940         {
7941             if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
7942             {
7943                 HBtab->ebdEnclosingTryIndex =
7944                     (unsigned short)XTnew; // This EH region wasn't previously nested, but now it is.
7945             }
7946         }
7947
7948 #ifdef DEBUG
7949         if (verbose)
7950         {
7951             JITDUMP("Synchronized method - created additional EH descriptor EH#%u for try/fault wrapping monitor "
7952                     "enter/exit\n",
7953                     XTnew);
7954             fgDispBasicBlocks();
7955             fgDispHandlerTab();
7956         }
7957
7958         fgVerifyHandlerTab();
7959 #endif // DEBUG
7960     }
7961
7962     // Create a 'monitor acquired' boolean (actually, an unsigned byte: 1 = acquired, 0 = not acquired).
7963
7964     var_types typeMonAcquired = TYP_UBYTE;
7965     this->lvaMonAcquired      = lvaGrabTemp(true DEBUGARG("Synchronized method monitor acquired boolean"));
7966
7967     lvaTable[lvaMonAcquired].lvType = typeMonAcquired;
7968
7969     { // Scope the variables of the variable initialization
7970
7971         // Initialize the 'acquired' boolean.
7972
7973         GenTree* zero     = gtNewZeroConNode(genActualType(typeMonAcquired));
7974         GenTree* varNode  = gtNewLclvNode(lvaMonAcquired, typeMonAcquired);
7975         GenTree* initNode = gtNewAssignNode(varNode, zero);
7976
7977         fgInsertStmtAtEnd(fgFirstBB, initNode);
7978
7979 #ifdef DEBUG
7980         if (verbose)
7981         {
7982             printf("\nSynchronized method - Add 'acquired' initialization in first block %s\n",
7983                    fgFirstBB->dspToString());
7984             gtDispTree(initNode);
7985             printf("\n");
7986         }
7987 #endif
7988     }
7989
7990     // Make a copy of the 'this' pointer to be used in the handler so it does not inhibit enregistration
7991     // of all uses of the variable.
7992     unsigned lvaCopyThis = 0;
7993     if (!info.compIsStatic)
7994     {
7995         lvaCopyThis                  = lvaGrabTemp(true DEBUGARG("Synchronized method monitor acquired boolean"));
7996         lvaTable[lvaCopyThis].lvType = TYP_REF;
7997
7998         GenTree* thisNode = gtNewLclvNode(info.compThisArg, TYP_REF);
7999         GenTree* copyNode = gtNewLclvNode(lvaCopyThis, TYP_REF);
8000         GenTree* initNode = gtNewAssignNode(copyNode, thisNode);
8001
8002         fgInsertStmtAtEnd(tryBegBB, initNode);
8003     }
8004
8005     fgCreateMonitorTree(lvaMonAcquired, info.compThisArg, tryBegBB, true /*enter*/);
8006
8007     // exceptional case
8008     fgCreateMonitorTree(lvaMonAcquired, lvaCopyThis, faultBB, false /*exit*/);
8009
8010     // non-exceptional cases
8011     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
8012     {
8013         if (block->bbJumpKind == BBJ_RETURN)
8014         {
8015             fgCreateMonitorTree(lvaMonAcquired, info.compThisArg, block, false /*exit*/);
8016         }
8017     }
8018 }
8019
8020 // fgCreateMonitorTree: Create tree to execute a monitor enter or exit operation for synchronized methods
8021 //    lvaMonAcquired: lvaNum of boolean variable that tracks if monitor has been acquired.
8022 //    lvaThisVar: lvaNum of variable being used as 'this' pointer, may not be the original one.  Is only used for
8023 //    nonstatic methods
8024 //    block: block to insert the tree in.  It is inserted at the end or in the case of a return, immediately before the
8025 //    GT_RETURN
8026 //    enter: whether to create a monitor enter or exit
8027
8028 GenTree* Compiler::fgCreateMonitorTree(unsigned lvaMonAcquired, unsigned lvaThisVar, BasicBlock* block, bool enter)
8029 {
8030     // Insert the expression "enter/exitCrit(this, &acquired)" or "enter/exitCrit(handle, &acquired)"
8031
8032     var_types typeMonAcquired = TYP_UBYTE;
8033     GenTree*  varNode         = gtNewLclvNode(lvaMonAcquired, typeMonAcquired);
8034     GenTree*  varAddrNode     = gtNewOperNode(GT_ADDR, TYP_BYREF, varNode);
8035     GenTree*  tree;
8036
8037     if (info.compIsStatic)
8038     {
8039         tree = fgGetCritSectOfStaticMethod();
8040         tree = gtNewHelperCallNode(enter ? CORINFO_HELP_MON_ENTER_STATIC : CORINFO_HELP_MON_EXIT_STATIC, TYP_VOID,
8041                                    gtNewArgList(tree, varAddrNode));
8042     }
8043     else
8044     {
8045         tree = gtNewLclvNode(lvaThisVar, TYP_REF);
8046         tree = gtNewHelperCallNode(enter ? CORINFO_HELP_MON_ENTER : CORINFO_HELP_MON_EXIT, TYP_VOID,
8047                                    gtNewArgList(tree, varAddrNode));
8048     }
8049
8050 #ifdef DEBUG
8051     if (verbose)
8052     {
8053         printf("\nSynchronized method - Add monitor %s call to block %s\n", enter ? "enter" : "exit",
8054                block->dspToString());
8055         gtDispTree(tree);
8056         printf("\n");
8057     }
8058 #endif
8059
8060     if (block->bbJumpKind == BBJ_RETURN && block->lastStmt()->gtStmtExpr->gtOper == GT_RETURN)
8061     {
8062         GenTree* retNode = block->lastStmt()->gtStmtExpr;
8063         GenTree* retExpr = retNode->gtOp.gtOp1;
8064
8065         if (retExpr != nullptr)
8066         {
8067             // have to insert this immediately before the GT_RETURN so we transform:
8068             // ret(...) ->
8069             // ret(comma(comma(tmp=...,call mon_exit), tmp)
8070             //
8071             //
8072             // Before morph stage, it is possible to have a case of GT_RETURN(TYP_LONG, op1) where op1's type is
8073             // TYP_STRUCT (of 8-bytes) and op1 is call node. See the big comment block in impReturnInstruction()
8074             // for details for the case where info.compRetType is not the same as info.compRetNativeType.  For
8075             // this reason pass compMethodInfo->args.retTypeClass which is guaranteed to be a valid class handle
8076             // if the return type is a value class.  Note that fgInsertCommFormTemp() in turn uses this class handle
8077             // if the type of op1 is TYP_STRUCT to perform lvaSetStruct() on the new temp that is created, which
8078             // in turn passes it to VM to know the size of value type.
8079             GenTree* temp = fgInsertCommaFormTemp(&retNode->gtOp.gtOp1, info.compMethodInfo->args.retTypeClass);
8080
8081             GenTree* lclVar                 = retNode->gtOp.gtOp1->gtOp.gtOp2;
8082             retNode->gtOp.gtOp1->gtOp.gtOp2 = gtNewOperNode(GT_COMMA, retExpr->TypeGet(), tree, lclVar);
8083         }
8084         else
8085         {
8086             // Insert this immediately before the GT_RETURN
8087             fgInsertStmtNearEnd(block, tree);
8088         }
8089     }
8090     else
8091     {
8092         fgInsertStmtAtEnd(block, tree);
8093     }
8094
8095     return tree;
8096 }
8097
8098 // Convert a BBJ_RETURN block in a synchronized method to a BBJ_ALWAYS.
8099 // We've previously added a 'try' block around the original program code using fgAddSyncMethodEnterExit().
8100 // Thus, we put BBJ_RETURN blocks inside a 'try'. In IL this is illegal. Instead, we would
8101 // see a 'leave' inside a 'try' that would get transformed into BBJ_CALLFINALLY/BBJ_ALWAYS blocks
8102 // during importing, and the BBJ_ALWAYS would point at an outer block with the BBJ_RETURN.
8103 // Here, we mimic some of the logic of importing a LEAVE to get the same effect for synchronized methods.
8104 void Compiler::fgConvertSyncReturnToLeave(BasicBlock* block)
8105 {
8106     assert(!fgFuncletsCreated);
8107     assert(info.compFlags & CORINFO_FLG_SYNCH);
8108     assert(genReturnBB != nullptr);
8109     assert(genReturnBB != block);
8110     assert(fgReturnCount <= 1); // We have a single return for synchronized methods
8111     assert(block->bbJumpKind == BBJ_RETURN);
8112     assert((block->bbFlags & BBF_HAS_JMP) == 0);
8113     assert(block->hasTryIndex());
8114     assert(!block->hasHndIndex());
8115     assert(compHndBBtabCount >= 1);
8116
8117     unsigned tryIndex = block->getTryIndex();
8118     assert(tryIndex == compHndBBtabCount - 1); // The BBJ_RETURN must be at the top-level before we inserted the
8119                                                // try/finally, which must be the last EH region.
8120
8121     EHblkDsc* ehDsc = ehGetDsc(tryIndex);
8122     assert(ehDsc->ebdEnclosingTryIndex ==
8123            EHblkDsc::NO_ENCLOSING_INDEX); // There are no enclosing regions of the BBJ_RETURN block
8124     assert(ehDsc->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
8125
8126     // Convert the BBJ_RETURN to BBJ_ALWAYS, jumping to genReturnBB.
8127     block->bbJumpKind = BBJ_ALWAYS;
8128     block->bbJumpDest = genReturnBB;
8129     block->bbJumpDest->bbRefs++;
8130
8131 #ifdef DEBUG
8132     if (verbose)
8133     {
8134         printf("Synchronized method - convert block BB%02u to BBJ_ALWAYS [targets BB%02u]\n", block->bbNum,
8135                block->bbJumpDest->bbNum);
8136     }
8137 #endif
8138 }
8139
8140 #endif // FEATURE_EH_FUNCLETS
8141
8142 //------------------------------------------------------------------------
8143 // fgAddReversePInvokeEnterExit: Add enter/exit calls for reverse PInvoke methods
8144 //
8145 // Arguments:
8146 //      None.
8147 //
8148 // Return Value:
8149 //      None.
8150
8151 void Compiler::fgAddReversePInvokeEnterExit()
8152 {
8153     assert(opts.IsReversePInvoke());
8154
8155     lvaReversePInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Reverse Pinvoke FrameVar"));
8156
8157     LclVarDsc* varDsc   = &lvaTable[lvaReversePInvokeFrameVar];
8158     varDsc->lvType      = TYP_BLK;
8159     varDsc->lvExactSize = eeGetEEInfo()->sizeOfReversePInvokeFrame;
8160
8161     GenTree* tree;
8162
8163     // Add enter pinvoke exit callout at the start of prolog
8164
8165     tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));
8166
8167     tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, TYP_VOID, gtNewArgList(tree));
8168
8169     fgEnsureFirstBBisScratch();
8170
8171     fgInsertStmtAtBeg(fgFirstBB, tree);
8172
8173 #ifdef DEBUG
8174     if (verbose)
8175     {
8176         printf("\nReverse PInvoke method - Add reverse pinvoke enter in first basic block %s\n",
8177                fgFirstBB->dspToString());
8178         gtDispTree(tree);
8179         printf("\n");
8180     }
8181 #endif
8182
8183     // Add reverse pinvoke exit callout at the end of epilog
8184
8185     tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));
8186
8187     tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, TYP_VOID, gtNewArgList(tree));
8188
8189     assert(genReturnBB != nullptr);
8190
8191     fgInsertStmtNearEnd(genReturnBB, tree);
8192
8193 #ifdef DEBUG
8194     if (verbose)
8195     {
8196         printf("\nReverse PInvoke method - Add reverse pinvoke exit in return basic block %s\n",
8197                genReturnBB->dspToString());
8198         gtDispTree(tree);
8199         printf("\n");
8200     }
8201 #endif
8202 }
8203
8204 /*****************************************************************************
8205  *
8206  *  Return 'true' if there is more than one BBJ_RETURN block.
8207  */
8208
8209 bool Compiler::fgMoreThanOneReturnBlock()
8210 {
8211     unsigned retCnt = 0;
8212
8213     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
8214     {
8215         if (block->bbJumpKind == BBJ_RETURN)
8216         {
8217             retCnt++;
8218             if (retCnt > 1)
8219             {
8220                 return true;
8221             }
8222         }
8223     }
8224
8225     return false;
8226 }
8227
8228 namespace
8229 {
8230 // Define a helper class for merging return blocks (which we do when the input has
8231 // more than the limit for this configuration).
8232 //
8233 // Notes: sets fgReturnCount, genReturnBB, and genReturnLocal.
8234 class MergedReturns
8235 {
8236 public:
8237 #ifdef JIT32_GCENCODER
8238
8239     // X86 GC encoding has a hard limit of SET_EPILOGCNT_MAX epilogs.
8240     const static unsigned ReturnCountHardLimit = SET_EPILOGCNT_MAX;
8241 #else  // JIT32_GCENCODER
8242
8243     // We currently apply a hard limit of '4' to all other targets (see
8244     // the other uses of SET_EPILOGCNT_MAX), though it would be good
8245     // to revisit that decision based on CQ analysis.
8246     const static unsigned ReturnCountHardLimit = 4;
8247 #endif // JIT32_GCENCODER
8248
8249 private:
8250     Compiler* comp;
8251
8252     // As we discover returns, we'll record them in `returnBlocks`, until
8253     // the limit is reached, at which point we'll keep track of the merged
8254     // return blocks in `returnBlocks`.
8255     BasicBlock* returnBlocks[ReturnCountHardLimit];
8256
8257     // Each constant value returned gets its own merged return block that
8258     // returns that constant (up to the limit on number of returns); in
8259     // `returnConstants` we track the constant values returned by these
8260     // merged constant return blocks.
8261     INT64 returnConstants[ReturnCountHardLimit];
8262
8263     // Indicators of where in the lexical block list we'd like to place
8264     // each constant return block.
8265     BasicBlock* insertionPoints[ReturnCountHardLimit];
8266
8267     // Number of return blocks allowed
8268     PhasedVar<unsigned> maxReturns;
8269
8270     // Flag to keep track of when we've hit the limit of returns and are
8271     // actively merging returns together.
8272     bool mergingReturns = false;
8273
8274 public:
8275     MergedReturns(Compiler* comp) : comp(comp)
8276     {
8277         comp->fgReturnCount = 0;
8278     }
8279
8280     void SetMaxReturns(unsigned value)
8281     {
8282         maxReturns = value;
8283         maxReturns.MarkAsReadOnly();
8284     }
8285
8286     //------------------------------------------------------------------------
8287     // Record: Make note of a return block in the input program.
8288     //
8289     // Arguments:
8290     //    returnBlock - Block in the input that has jump kind BBJ_RETURN
8291     //
8292     // Notes:
8293     //    Updates fgReturnCount appropriately, and generates a merged return
8294     //    block if necessary.  If a constant merged return block is used,
8295     //    `returnBlock` is rewritten to jump to it.  If a non-constant return
8296     //    block is used, `genReturnBB` is set to that block, and `genReturnLocal`
8297     //    is set to the lclvar that it returns; morph will need to rewrite
8298     //    `returnBlock` to set the local and jump to the return block in such
8299     //    cases, which it will do after some key transformations like rewriting
8300     //    tail calls and calls that return to hidden buffers.  In either of these
8301     //    cases, `fgReturnCount` and the merged return block's profile information
8302     //    will be updated to reflect or anticipate the rewrite of `returnBlock`.
8303     //
8304     void Record(BasicBlock* returnBlock)
8305     {
8306         // Add this return to our tally
8307         unsigned oldReturnCount = comp->fgReturnCount++;
8308
8309         if (!mergingReturns)
8310         {
8311             if (oldReturnCount < maxReturns)
8312             {
8313                 // No need to merge just yet; simply record this return.
8314                 returnBlocks[oldReturnCount] = returnBlock;
8315                 return;
8316             }
8317
8318             // We'e reached our threshold
8319             mergingReturns = true;
8320
8321             // Merge any returns we've already identified
8322             for (unsigned i = 0, searchLimit = 0; i < oldReturnCount; ++i)
8323             {
8324                 BasicBlock* mergedReturnBlock = Merge(returnBlocks[i], searchLimit);
8325                 if (returnBlocks[searchLimit] == mergedReturnBlock)
8326                 {
8327                     // We've added a new block to the searchable set
8328                     ++searchLimit;
8329                 }
8330             }
8331         }
8332
8333         // We have too many returns, so merge this one in.
8334         // Search limit is new return count minus one (to exclude this block).
8335         unsigned searchLimit = comp->fgReturnCount - 1;
8336         Merge(returnBlock, searchLimit);
8337     }
8338
8339     //------------------------------------------------------------------------
8340     // EagerCreate: Force creation of a non-constant merged return block `genReturnBB`.
8341     //
8342     // Return Value:
8343     //    The newly-created block which returns `genReturnLocal`.
8344     //
8345     BasicBlock* EagerCreate()
8346     {
8347         mergingReturns = true;
8348         return Merge(nullptr, 0);
8349     }
8350
8351     //------------------------------------------------------------------------
8352     // PlaceReturns: Move any generated const return blocks to an appropriate
8353     //     spot in the lexical block list.
8354     //
8355     // Notes:
8356     //    The goal is to set things up favorably for a reasonable layout without
8357     //    putting too much burden on fgReorderBlocks; in particular, since that
8358     //    method doesn't (currently) shuffle non-profile, non-rare code to create
8359     //    fall-through and reduce gotos, this method places each const return
8360     //    block immediately after its last predecessor, so that the flow from
8361     //    there to it can become fallthrough without requiring any motion to be
8362     //    performed by fgReorderBlocks.
8363     //
8364     void PlaceReturns()
8365     {
8366         if (!mergingReturns)
8367         {
8368             // No returns generated => no returns to place.
8369             return;
8370         }
8371
8372         for (unsigned index = 0; index < comp->fgReturnCount; ++index)
8373         {
8374             BasicBlock* returnBlock    = returnBlocks[index];
8375             BasicBlock* genReturnBlock = comp->genReturnBB;
8376             if (returnBlock == genReturnBlock)
8377             {
8378                 continue;
8379             }
8380
8381             BasicBlock* insertionPoint = insertionPoints[index];
8382             assert(insertionPoint != nullptr);
8383
8384             comp->fgUnlinkBlock(returnBlock);
8385             comp->fgMoveBlocksAfter(returnBlock, returnBlock, insertionPoint);
8386             // Treat the merged return block as belonging to the same EH region
8387             // as the insertion point block, to make sure we don't break up
8388             // EH regions; since returning a constant won't throw, this won't
8389             // affect program behavior.
8390             comp->fgExtendEHRegionAfter(insertionPoint);
8391         }
8392     }
8393
8394 private:
8395     //------------------------------------------------------------------------
8396     // CreateReturnBB: Create a basic block to serve as a merged return point, stored to
8397     //    `returnBlocks` at the given index, and optionally returning the given constant.
8398     //
8399     // Arguments:
8400     //    index - Index into `returnBlocks` to store the new block into.
8401     //    returnConst - Constant that the new block should return; may be nullptr to
8402     //      indicate that the new merged return is for the non-constant case, in which
8403     //      case, if the method's return type is non-void, `comp->genReturnLocal` will
8404     //      be initialized to a new local of the appropriate type, and the new block will
8405     //      return it.
8406     //
8407     // Return Value:
8408     //    The new merged return block.
8409     //
8410     BasicBlock* CreateReturnBB(unsigned index, GenTreeIntConCommon* returnConst = nullptr)
8411     {
8412         BasicBlock* newReturnBB = comp->fgNewBBinRegion(BBJ_RETURN);
8413         newReturnBB->bbRefs     = 1; // bbRefs gets update later, for now it should be 1
8414         comp->fgReturnCount++;
8415
8416         newReturnBB->bbFlags |= BBF_INTERNAL;
8417
8418         noway_assert(newReturnBB->bbNext == nullptr);
8419
8420 #ifdef DEBUG
8421         if (comp->verbose)
8422         {
8423             printf("\n newReturnBB [BB%02u] created\n", newReturnBB->bbNum);
8424         }
8425 #endif
8426
8427         // We have profile weight, the weight is zero, and the block is run rarely,
8428         // until we prove otherwise by merging other returns into this one.
8429         newReturnBB->bbFlags |= (BBF_PROF_WEIGHT | BBF_RUN_RARELY);
8430         newReturnBB->bbWeight = 0;
8431
8432         GenTree* returnExpr;
8433
8434         if (returnConst != nullptr)
8435         {
8436             returnExpr             = comp->gtNewOperNode(GT_RETURN, returnConst->gtType, returnConst);
8437             returnConstants[index] = returnConst->IntegralValue();
8438         }
8439         else if (comp->compMethodHasRetVal())
8440         {
8441             // There is a return value, so create a temp for it.  Real returns will store the value in there and
8442             // it'll be reloaded by the single return.
8443             unsigned returnLocalNum   = comp->lvaGrabTemp(true DEBUGARG("Single return block return value"));
8444             comp->genReturnLocal      = returnLocalNum;
8445             LclVarDsc& returnLocalDsc = comp->lvaTable[returnLocalNum];
8446
8447             if (comp->compMethodReturnsNativeScalarType())
8448             {
8449                 returnLocalDsc.lvType = genActualType(comp->info.compRetNativeType);
8450             }
8451             else if (comp->compMethodReturnsRetBufAddr())
8452             {
8453                 returnLocalDsc.lvType = TYP_BYREF;
8454             }
8455             else if (comp->compMethodReturnsMultiRegRetType())
8456             {
8457                 returnLocalDsc.lvType = TYP_STRUCT;
8458                 comp->lvaSetStruct(returnLocalNum, comp->info.compMethodInfo->args.retTypeClass, true);
8459                 returnLocalDsc.lvIsMultiRegRet = true;
8460             }
8461             else
8462             {
8463                 assert(!"unreached");
8464             }
8465
8466             if (varTypeIsFloating(returnLocalDsc.lvType))
8467             {
8468                 comp->compFloatingPointUsed = true;
8469             }
8470
8471             if (!varTypeIsFloating(comp->info.compRetType))
8472             {
8473                 returnLocalDsc.setPrefReg(REG_INTRET, comp);
8474             }
8475 #ifdef REG_FLOATRET
8476             else
8477             {
8478                 returnLocalDsc.setPrefReg(REG_FLOATRET, comp);
8479             }
8480 #endif
8481
8482 #ifdef DEBUG
8483             // This temporary should not be converted to a double in stress mode,
8484             // because we introduce assigns to it after the stress conversion
8485             returnLocalDsc.lvKeepType = 1;
8486 #endif
8487
8488             GenTree* retTemp = comp->gtNewLclvNode(returnLocalNum, returnLocalDsc.TypeGet());
8489
8490             // make sure copy prop ignores this node (make sure it always does a reload from the temp).
8491             retTemp->gtFlags |= GTF_DONT_CSE;
8492             returnExpr = comp->gtNewOperNode(GT_RETURN, retTemp->gtType, retTemp);
8493         }
8494         else
8495         {
8496             // return void
8497             noway_assert(comp->info.compRetType == TYP_VOID || varTypeIsStruct(comp->info.compRetType));
8498             comp->genReturnLocal = BAD_VAR_NUM;
8499
8500             returnExpr = new (comp, GT_RETURN) GenTreeOp(GT_RETURN, TYP_VOID);
8501         }
8502
8503         // Add 'return' expression to the return block
8504         comp->fgInsertStmtAtEnd(newReturnBB, returnExpr);
8505         // Flag that this 'return' was generated by return merging so that subsequent
8506         // return block morhping will know to leave it alone.
8507         returnExpr->gtFlags |= GTF_RET_MERGED;
8508
8509 #ifdef DEBUG
8510         if (comp->verbose)
8511         {
8512             printf("\nmergeReturns statement tree ");
8513             Compiler::printTreeID(returnExpr);
8514             printf(" added to genReturnBB %s\n", newReturnBB->dspToString());
8515             comp->gtDispTree(returnExpr);
8516             printf("\n");
8517         }
8518 #endif
8519         assert(index < maxReturns);
8520         returnBlocks[index] = newReturnBB;
8521         return newReturnBB;
8522     }
8523
8524     //------------------------------------------------------------------------
8525     // Merge: Find or create an appropriate merged return block for the given input block.
8526     //
8527     // Arguments:
8528     //    returnBlock - Return block from the input program to find a merged return for.
8529     //                  May be nullptr to indicate that new block suitable for non-constant
8530     //                  returns should be generated but no existing block modified.
8531     //    searchLimit - Blocks in `returnBlocks` up to but not including index `searchLimit`
8532     //                  will be checked to see if we already have an appropriate merged return
8533     //                  block for this case.  If a new block must be created, it will be stored
8534     //                  to `returnBlocks` at index `searchLimit`.
8535     //
8536     // Return Value:
8537     //    Merged return block suitable for handling this return value.  May be newly-created
8538     //    or pre-existing.
8539     //
8540     // Notes:
8541     //    If a constant-valued merged return block is used, `returnBlock` will be rewritten to
8542     //    jump to the merged return block and its `GT_RETURN` statement will be removed.  If
8543     //    a non-constant-valued merged return block is used, `genReturnBB` and `genReturnLocal`
8544     //    will be set so that Morph can perform that rewrite, which it will do after some key
8545     //    transformations like rewriting tail calls and calls that return to hidden buffers.
8546     //    In either of these cases, `fgReturnCount` and the merged return block's profile
8547     //    information will be updated to reflect or anticipate the rewrite of `returnBlock`.
8548     //
8549     BasicBlock* Merge(BasicBlock* returnBlock, unsigned searchLimit)
8550     {
8551         assert(mergingReturns);
8552
8553         BasicBlock* mergedReturnBlock = nullptr;
8554
8555         // Do not look for mergable constant returns in debug codegen as
8556         // we may lose track of sequence points.
8557         if ((returnBlock != nullptr) && (maxReturns > 1) && !comp->opts.compDbgCode)
8558         {
8559             // Check to see if this is a constant return so that we can search
8560             // for and/or create a constant return block for it.
8561
8562             GenTreeIntConCommon* retConst = GetReturnConst(returnBlock);
8563             if (retConst != nullptr)
8564             {
8565                 // We have a constant.  Now find or create a corresponding return block.
8566
8567                 unsigned    index;
8568                 BasicBlock* constReturnBlock = FindConstReturnBlock(retConst, searchLimit, &index);
8569
8570                 if (constReturnBlock == nullptr)
8571                 {
8572                     // We didn't find a const return block.  See if we have space left
8573                     // to make one.
8574
8575                     // We have already allocated `searchLimit` slots.
8576                     unsigned slotsReserved = searchLimit;
8577                     if (comp->genReturnBB == nullptr)
8578                     {
8579                         // We haven't made a non-const return yet, so we have to reserve
8580                         // a slot for one.
8581                         ++slotsReserved;
8582                     }
8583
8584                     if (slotsReserved < maxReturns)
8585                     {
8586                         // We have enough space to allocate a slot for this constant.
8587                         constReturnBlock = CreateReturnBB(searchLimit, retConst);
8588                     }
8589                 }
8590
8591                 if (constReturnBlock != nullptr)
8592                 {
8593                     // Found a constant merged return block.
8594                     mergedReturnBlock = constReturnBlock;
8595
8596                     // Change BBJ_RETURN to BBJ_ALWAYS targeting const return block.
8597                     assert((comp->info.compFlags & CORINFO_FLG_SYNCH) == 0);
8598                     returnBlock->bbJumpKind = BBJ_ALWAYS;
8599                     returnBlock->bbJumpDest = constReturnBlock;
8600
8601                     // Remove GT_RETURN since constReturnBlock returns the constant.
8602                     assert(returnBlock->lastStmt()->gtStmtExpr->OperIs(GT_RETURN));
8603                     assert(returnBlock->lastStmt()->gtStmtExpr->gtGetOp1()->IsIntegralConst());
8604                     comp->fgRemoveStmt(returnBlock, returnBlock->lastStmt());
8605
8606                     // Using 'returnBlock' as the insertion point for 'mergedReturnBlock'
8607                     // will give it a chance to use fallthrough rather than BBJ_ALWAYS.
8608                     // Resetting this after each merge ensures that any branches to the
8609                     // merged return block are lexically forward.
8610
8611                     insertionPoints[index] = returnBlock;
8612                 }
8613             }
8614         }
8615
8616         if (mergedReturnBlock == nullptr)
8617         {
8618             // No constant return block for this return; use the general one.
8619             mergedReturnBlock = comp->genReturnBB;
8620             if (mergedReturnBlock == nullptr)
8621             {
8622                 // No general merged return for this function yet; create one.
8623                 // There had better still be room left in the array.
8624                 assert(searchLimit < maxReturns);
8625                 mergedReturnBlock = CreateReturnBB(searchLimit);
8626                 comp->genReturnBB = mergedReturnBlock;
8627                 // Downstream code expects the `genReturnBB` to always remain
8628                 // once created, so that it can redirect flow edges to it.
8629                 mergedReturnBlock->bbFlags |= BBF_DONT_REMOVE;
8630             }
8631         }
8632
8633         if (returnBlock != nullptr)
8634         {
8635             // Propagate profile weight and related annotations to the merged block.
8636             // Return weight should never exceed entry weight, so cap it to avoid nonsensical
8637             // hot returns in synthetic profile settings.
8638             mergedReturnBlock->bbWeight =
8639                 min(mergedReturnBlock->bbWeight + returnBlock->bbWeight, comp->fgFirstBB->bbWeight);
8640             if (!returnBlock->hasProfileWeight())
8641             {
8642                 mergedReturnBlock->bbFlags &= ~BBF_PROF_WEIGHT;
8643             }
8644             if (mergedReturnBlock->bbWeight > 0)
8645             {
8646                 mergedReturnBlock->bbFlags &= ~BBF_RUN_RARELY;
8647             }
8648
8649             // Update fgReturnCount to reflect or anticipate that `returnBlock` will no longer
8650             // be a return point.
8651             comp->fgReturnCount--;
8652         }
8653
8654         return mergedReturnBlock;
8655     }
8656
8657     //------------------------------------------------------------------------
8658     // GetReturnConst: If the given block returns an integral constant, return the
8659     //     GenTreeIntConCommon that represents the constant.
8660     //
8661     // Arguments:
8662     //    returnBlock - Block whose return value is to be inspected.
8663     //
8664     // Return Value:
8665     //    GenTreeIntCommon that is the argument of `returnBlock`'s `GT_RETURN` if
8666     //    such exists; nullptr otherwise.
8667     //
8668     static GenTreeIntConCommon* GetReturnConst(BasicBlock* returnBlock)
8669     {
8670         GenTreeStmt* lastStmt = returnBlock->lastStmt();
8671         if (lastStmt == nullptr)
8672         {
8673             return nullptr;
8674         }
8675
8676         GenTree* lastExpr = lastStmt->gtStmtExpr;
8677         if (!lastExpr->OperIs(GT_RETURN))
8678         {
8679             return nullptr;
8680         }
8681
8682         GenTree* retExpr = lastExpr->gtGetOp1();
8683         if ((retExpr == nullptr) || !retExpr->IsIntegralConst())
8684         {
8685             return nullptr;
8686         }
8687
8688         return retExpr->AsIntConCommon();
8689     }
8690
8691     //------------------------------------------------------------------------
8692     // FindConstReturnBlock: Scan the already-created merged return blocks, up to `searchLimit`,
8693     //     and return the one corresponding to the given const expression if it exists.
8694     //
8695     // Arguments:
8696     //    constExpr - GenTreeIntCommon representing the constant return value we're
8697     //        searching for.
8698     //    searchLimit - Check `returnBlocks`/`returnConstants` up to but not including
8699     //        this index.
8700     //    index - [out] Index of return block in the `returnBlocks` array, if found;
8701     //        searchLimit otherwise.
8702     //
8703     // Return Value:
8704     //    A block that returns the same constant, if one is found; otherwise nullptr.
8705     //
8706     BasicBlock* FindConstReturnBlock(GenTreeIntConCommon* constExpr, unsigned searchLimit, unsigned* index)
8707     {
8708         INT64 constVal = constExpr->IntegralValue();
8709
8710         for (unsigned i = 0; i < searchLimit; ++i)
8711         {
8712             // Need to check both for matching const val and for genReturnBB
8713             // because genReturnBB is used for non-constant returns and its
8714             // corresponding entry in the returnConstants array is garbage.
8715             if (returnConstants[i] == constVal)
8716             {
8717                 BasicBlock* returnBlock = returnBlocks[i];
8718
8719                 if (returnBlock == comp->genReturnBB)
8720                 {
8721                     // This is the block used for non-constant returns, so
8722                     // its returnConstants entry is just garbage; don't be
8723                     // fooled.
8724                     continue;
8725                 }
8726
8727                 *index = i;
8728                 return returnBlock;
8729             }
8730         }
8731
8732         *index = searchLimit;
8733         return nullptr;
8734     }
8735 };
8736 }
8737
8738 /*****************************************************************************
8739 *
8740 *  Add any internal blocks/trees we may need
8741 */
8742
8743 void Compiler::fgAddInternal()
8744 {
8745     noway_assert(!compIsForInlining());
8746
8747     // The backend requires a scratch BB into which it can safely insert a P/Invoke method prolog if one is
8748     // required. Create it here.
8749     if (info.compCallUnmanaged != 0)
8750     {
8751         fgEnsureFirstBBisScratch();
8752         fgFirstBB->bbFlags |= BBF_DONT_REMOVE;
8753     }
8754
8755     /*
8756     <BUGNUM> VSW441487 </BUGNUM>
8757
8758     The "this" pointer is implicitly used in the following cases:
8759     1. Locking of synchronized methods
8760     2. Dictionary access of shared generics code
8761     3. If a method has "catch(FooException<T>)", the EH code accesses "this" to determine T.
8762     4. Initializing the type from generic methods which require precise cctor semantics
8763     5. Verifier does special handling of "this" in the .ctor
8764
8765     However, we might overwrite it with a "starg 0".
8766     In this case, we will redirect all "ldarg(a)/starg(a) 0" to a temp lvaTable[lvaArg0Var]
8767     */
8768
8769     if (!info.compIsStatic)
8770     {
8771         if (lvaArg0Var != info.compThisArg)
8772         {
8773             // When we're using the general encoder, we mark compThisArg address-taken to ensure that it is not
8774             // enregistered (since the decoder always reports a stack location for "this" for generics
8775             // context vars).
8776             bool lva0CopiedForGenericsCtxt;
8777 #ifndef JIT32_GCENCODER
8778             lva0CopiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0);
8779 #else  // JIT32_GCENCODER
8780             lva0CopiedForGenericsCtxt          = false;
8781 #endif // JIT32_GCENCODER
8782             noway_assert(lva0CopiedForGenericsCtxt || !lvaTable[info.compThisArg].lvAddrExposed);
8783             noway_assert(!lvaTable[info.compThisArg].lvHasILStoreOp);
8784             noway_assert(lvaTable[lvaArg0Var].lvAddrExposed || lvaTable[lvaArg0Var].lvHasILStoreOp ||
8785                          lva0CopiedForGenericsCtxt);
8786
8787             var_types thisType = lvaTable[info.compThisArg].TypeGet();
8788
8789             // Now assign the original input "this" to the temp
8790
8791             GenTree* tree;
8792
8793             tree = gtNewLclvNode(lvaArg0Var, thisType);
8794
8795             tree = gtNewAssignNode(tree,                                     // dst
8796                                    gtNewLclvNode(info.compThisArg, thisType) // src
8797                                    );
8798
8799             /* Create a new basic block and stick the assignment in it */
8800
8801             fgEnsureFirstBBisScratch();
8802
8803             fgInsertStmtAtEnd(fgFirstBB, tree);
8804
8805 #ifdef DEBUG
8806             if (verbose)
8807             {
8808                 printf("\nCopy \"this\" to lvaArg0Var in first basic block %s\n", fgFirstBB->dspToString());
8809                 gtDispTree(tree);
8810                 printf("\n");
8811             }
8812 #endif
8813         }
8814     }
8815
8816     // Grab a temp for the security object.
8817     // (Note: opts.compDbgEnC currently also causes the security object to be generated. See Compiler::compCompile)
8818     if (opts.compNeedSecurityCheck)
8819     {
8820         noway_assert(lvaSecurityObject == BAD_VAR_NUM);
8821         lvaSecurityObject                  = lvaGrabTempWithImplicitUse(false DEBUGARG("security check"));
8822         lvaTable[lvaSecurityObject].lvType = TYP_REF;
8823     }
8824
8825     // Merge return points if required or beneficial
8826     MergedReturns merger(this);
8827
8828 #if FEATURE_EH_FUNCLETS
8829     // Add the synchronized method enter/exit calls and try/finally protection. Note
8830     // that this must happen before the one BBJ_RETURN block is created below, so the
8831     // BBJ_RETURN block gets placed at the top-level, not within an EH region. (Otherwise,
8832     // we'd have to be really careful when creating the synchronized method try/finally
8833     // not to include the BBJ_RETURN block.)
8834     if ((info.compFlags & CORINFO_FLG_SYNCH) != 0)
8835     {
8836         fgAddSyncMethodEnterExit();
8837     }
8838 #endif // FEATURE_EH_FUNCLETS
8839
8840     //
8841     //  We will generate just one epilog (return block)
8842     //   when we are asked to generate enter/leave callbacks
8843     //   or for methods with PInvoke
8844     //   or for methods calling into unmanaged code
8845     //   or for synchronized methods.
8846     //
8847     BasicBlock* lastBlockBeforeGenReturns = fgLastBB;
8848     if (compIsProfilerHookNeeded() || (info.compCallUnmanaged != 0) || opts.IsReversePInvoke() ||
8849         ((info.compFlags & CORINFO_FLG_SYNCH) != 0))
8850     {
8851         // We will generate only one return block
8852         // We will transform the BBJ_RETURN blocks
8853         //  into jumps to the one return block
8854         //
8855         merger.SetMaxReturns(1);
8856
8857         // Eagerly create the genReturnBB since the lowering of these constructs
8858         // will expect to find it.
8859         BasicBlock* mergedReturn = merger.EagerCreate();
8860         assert(mergedReturn == genReturnBB);
8861         // Assume weight equal to entry weight for this BB.
8862         mergedReturn->bbFlags &= ~BBF_PROF_WEIGHT;
8863         mergedReturn->bbWeight = fgFirstBB->bbWeight;
8864         if (mergedReturn->bbWeight > 0)
8865         {
8866             mergedReturn->bbFlags &= ~BBF_RUN_RARELY;
8867         }
8868     }
8869     else
8870     {
8871         //
8872         // We are allowed to have multiple individual exits
8873         // However we can still decide to have a single return
8874         //
8875         if (compCodeOpt() == SMALL_CODE)
8876         {
8877             // For the Small_Code case we always generate a
8878             // single return block when we have multiple
8879             // return points
8880             //
8881             merger.SetMaxReturns(1);
8882         }
8883         else
8884         {
8885             merger.SetMaxReturns(MergedReturns::ReturnCountHardLimit);
8886         }
8887     }
8888
8889     // Visit the BBJ_RETURN blocks and merge as necessary.
8890
8891     for (BasicBlock* block = fgFirstBB; block != lastBlockBeforeGenReturns->bbNext; block = block->bbNext)
8892     {
8893         if ((block->bbJumpKind == BBJ_RETURN) && ((block->bbFlags & BBF_HAS_JMP) == 0))
8894         {
8895             merger.Record(block);
8896         }
8897     }
8898
8899     merger.PlaceReturns();
8900
8901     if (info.compCallUnmanaged != 0)
8902     {
8903         // The P/Invoke helpers only require a frame variable, so only allocate the
8904         // TCB variable if we're not using them.
8905         if (!opts.ShouldUsePInvokeHelpers())
8906         {
8907             info.compLvFrameListRoot = lvaGrabTemp(false DEBUGARG("Pinvoke FrameListRoot"));
8908         }
8909
8910         lvaInlinedPInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Pinvoke FrameVar"));
8911
8912         LclVarDsc* varDsc = &lvaTable[lvaInlinedPInvokeFrameVar];
8913         varDsc->addPrefReg(RBM_PINVOKE_TCB, this);
8914         varDsc->lvType = TYP_BLK;
8915         // Make room for the inlined frame.
8916         varDsc->lvExactSize = eeGetEEInfo()->inlinedCallFrameInfo.size;
8917 #if FEATURE_FIXED_OUT_ARGS
8918         // Grab and reserve space for TCB, Frame regs used in PInvoke epilog to pop the inlined frame.
8919         // See genPInvokeMethodEpilog() for use of the grabbed var. This is only necessary if we are
8920         // not using the P/Invoke helpers.
8921         if (!opts.ShouldUsePInvokeHelpers() && compJmpOpUsed)
8922         {
8923             lvaPInvokeFrameRegSaveVar = lvaGrabTempWithImplicitUse(false DEBUGARG("PInvokeFrameRegSave Var"));
8924             varDsc                    = &lvaTable[lvaPInvokeFrameRegSaveVar];
8925             varDsc->lvType            = TYP_BLK;
8926             varDsc->lvExactSize       = 2 * REGSIZE_BYTES;
8927         }
8928 #endif
8929     }
8930
8931     // Do we need to insert a "JustMyCode" callback?
8932
8933     CORINFO_JUST_MY_CODE_HANDLE* pDbgHandle = nullptr;
8934     CORINFO_JUST_MY_CODE_HANDLE  dbgHandle  = nullptr;
8935     if (opts.compDbgCode && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB))
8936     {
8937         dbgHandle = info.compCompHnd->getJustMyCodeHandle(info.compMethodHnd, &pDbgHandle);
8938     }
8939
8940 #ifdef _TARGET_ARM64_
8941     // TODO-ARM64-NYI: don't do just-my-code
8942     dbgHandle  = nullptr;
8943     pDbgHandle = nullptr;
8944 #endif // _TARGET_ARM64_
8945
8946     noway_assert(!dbgHandle || !pDbgHandle);
8947
8948     if (dbgHandle || pDbgHandle)
8949     {
8950         GenTree* embNode        = gtNewIconEmbHndNode(dbgHandle, pDbgHandle, GTF_ICON_TOKEN_HDL, info.compMethodHnd);
8951         GenTree* guardCheckVal  = gtNewOperNode(GT_IND, TYP_INT, embNode);
8952         GenTree* guardCheckCond = gtNewOperNode(GT_EQ, TYP_INT, guardCheckVal, gtNewZeroConNode(TYP_INT));
8953         guardCheckCond->gtFlags |= GTF_RELOP_QMARK;
8954
8955         // Create the callback which will yield the final answer
8956
8957         GenTree* callback = gtNewHelperCallNode(CORINFO_HELP_DBG_IS_JUST_MY_CODE, TYP_VOID);
8958         callback          = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), callback);
8959
8960         // Stick the conditional call at the start of the method
8961
8962         fgEnsureFirstBBisScratch();
8963         fgInsertStmtAtEnd(fgFirstBB, gtNewQmarkNode(TYP_VOID, guardCheckCond, callback));
8964     }
8965
8966     /* Do we need to call out for security ? */
8967
8968     if (tiSecurityCalloutNeeded)
8969     {
8970         // We must have grabbed this local.
8971         noway_assert(opts.compNeedSecurityCheck);
8972         noway_assert(lvaSecurityObject != BAD_VAR_NUM);
8973
8974         GenTree* tree;
8975
8976         /* Insert the expression "call JIT_Security_Prolog(MethodHnd, &SecurityObject)" */
8977
8978         tree = gtNewIconEmbMethHndNode(info.compMethodHnd);
8979
8980         tree = gtNewHelperCallNode(info.compCompHnd->getSecurityPrologHelper(info.compMethodHnd), TYP_VOID,
8981                                    gtNewArgList(tree, gtNewOperNode(GT_ADDR, TYP_BYREF,
8982                                                                     gtNewLclvNode(lvaSecurityObject, TYP_REF))));
8983
8984         /* Create a new basic block and stick the call in it */
8985
8986         fgEnsureFirstBBisScratch();
8987
8988         fgInsertStmtAtEnd(fgFirstBB, tree);
8989
8990 #ifdef DEBUG
8991         if (verbose)
8992         {
8993             printf("\ntiSecurityCalloutNeeded - Add call JIT_Security_Prolog(%08p) statement ",
8994                    dspPtr(info.compMethodHnd));
8995             printTreeID(tree);
8996             printf(" in first basic block %s\n", fgFirstBB->dspToString());
8997             gtDispTree(tree);
8998             printf("\n");
8999         }
9000 #endif
9001     }
9002
9003 #if !FEATURE_EH_FUNCLETS
9004
9005     /* Is this a 'synchronized' method? */
9006
9007     if (info.compFlags & CORINFO_FLG_SYNCH)
9008     {
9009         GenTree* tree = NULL;
9010
9011         /* Insert the expression "enterCrit(this)" or "enterCrit(handle)" */
9012
9013         if (info.compIsStatic)
9014         {
9015             tree = fgGetCritSectOfStaticMethod();
9016
9017             tree = gtNewHelperCallNode(CORINFO_HELP_MON_ENTER_STATIC, TYP_VOID, gtNewArgList(tree));
9018         }
9019         else
9020         {
9021             noway_assert(lvaTable[info.compThisArg].lvType == TYP_REF);
9022
9023             tree = gtNewLclvNode(info.compThisArg, TYP_REF);
9024
9025             tree = gtNewHelperCallNode(CORINFO_HELP_MON_ENTER, TYP_VOID, gtNewArgList(tree));
9026         }
9027
9028         /* Create a new basic block and stick the call in it */
9029
9030         fgEnsureFirstBBisScratch();
9031
9032         fgInsertStmtAtEnd(fgFirstBB, tree);
9033
9034 #ifdef DEBUG
9035         if (verbose)
9036         {
9037             printf("\nSynchronized method - Add enterCrit statement in first basic block %s\n",
9038                    fgFirstBB->dspToString());
9039             gtDispTree(tree);
9040             printf("\n");
9041         }
9042 #endif
9043
9044         /* We must be generating a single exit point for this to work */
9045
9046         noway_assert(genReturnBB != nullptr);
9047
9048         /* Create the expression "exitCrit(this)" or "exitCrit(handle)" */
9049
9050         if (info.compIsStatic)
9051         {
9052             tree = fgGetCritSectOfStaticMethod();
9053
9054             tree = gtNewHelperCallNode(CORINFO_HELP_MON_EXIT_STATIC, TYP_VOID, gtNewArgList(tree));
9055         }
9056         else
9057         {
9058             tree = gtNewLclvNode(info.compThisArg, TYP_REF);
9059
9060             tree = gtNewHelperCallNode(CORINFO_HELP_MON_EXIT, TYP_VOID, gtNewArgList(tree));
9061         }
9062
9063         fgInsertStmtNearEnd(genReturnBB, tree);
9064
9065 #ifdef DEBUG
9066         if (verbose)
9067         {
9068             printf("\nSynchronized method - Add exit expression ");
9069             printTreeID(tree);
9070             printf("\n");
9071         }
9072 #endif
9073
9074         // Reset cookies used to track start and end of the protected region in synchronized methods
9075         syncStartEmitCookie = NULL;
9076         syncEndEmitCookie   = NULL;
9077     }
9078
9079 #endif // !FEATURE_EH_FUNCLETS
9080
9081     /* Do we need to do runtime call out to check the security? */
9082
9083     if (tiRuntimeCalloutNeeded)
9084     {
9085         GenTree* tree;
9086
9087         /* Insert the expression "call verificationRuntimeCheck(MethodHnd)" */
9088
9089         tree = gtNewIconEmbMethHndNode(info.compMethodHnd);
9090
9091         tree = gtNewHelperCallNode(CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, TYP_VOID, gtNewArgList(tree));
9092
9093         /* Create a new basic block and stick the call in it */
9094
9095         fgEnsureFirstBBisScratch();
9096
9097         fgInsertStmtAtEnd(fgFirstBB, tree);
9098
9099 #ifdef DEBUG
9100         if (verbose)
9101         {
9102             printf("\ntiRuntimeCalloutNeeded - Call verificationRuntimeCheck(%08p) statement in first basic block %s\n",
9103                    dspPtr(info.compMethodHnd), fgFirstBB->dspToString());
9104             gtDispTree(tree);
9105             printf("\n");
9106         }
9107 #endif
9108     }
9109
9110     if (opts.IsReversePInvoke())
9111     {
9112         fgAddReversePInvokeEnterExit();
9113     }
9114
9115 #ifdef DEBUG
9116     if (verbose)
9117     {
9118         printf("\n*************** After fgAddInternal()\n");
9119         fgDispBasicBlocks();
9120         fgDispHandlerTab();
9121     }
9122 #endif
9123 }
9124
9125 /*****************************************************************************
9126  *
9127  *  Create a new statement from tree and wire the links up.
9128  */
9129 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTree* tree, BasicBlock* block, IL_OFFSETX offs)
9130 {
9131     GenTreeStmt* stmt = gtNewStmt(tree, offs);
9132
9133     if (fgStmtListThreaded)
9134     {
9135         gtSetStmtInfo(stmt);
9136         fgSetStmtSeq(stmt);
9137     }
9138
9139 #if DEBUG
9140     if (block != nullptr)
9141     {
9142         fgDebugCheckNodeLinks(block, stmt);
9143     }
9144 #endif
9145
9146     return stmt;
9147 }
9148
9149 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTree* tree)
9150 {
9151     return fgNewStmtFromTree(tree, nullptr, BAD_IL_OFFSET);
9152 }
9153
9154 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTree* tree, BasicBlock* block)
9155 {
9156     return fgNewStmtFromTree(tree, block, BAD_IL_OFFSET);
9157 }
9158
9159 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTree* tree, IL_OFFSETX offs)
9160 {
9161     return fgNewStmtFromTree(tree, nullptr, offs);
9162 }
9163
9164 //------------------------------------------------------------------------
9165 // fgFindBlockILOffset: Given a block, find the IL offset corresponding to the first statement
9166 //      in the block with a legal IL offset. Skip any leading statements that have BAD_IL_OFFSET.
9167 //      If no statement has an initialized statement offset (including the case where there are
9168 //      no statements in the block), then return BAD_IL_OFFSET. This function is used when
9169 //      blocks are split or modified, and we want to maintain the IL offset as much as possible
9170 //      to preserve good debugging behavior.
9171 //
9172 // Arguments:
9173 //      block - The block to check.
9174 //
9175 // Return Value:
9176 //      The first good IL offset of a statement in the block, or BAD_IL_OFFSET if such an IL offset
9177 //      cannot be found.
9178 //
9179 IL_OFFSET Compiler::fgFindBlockILOffset(BasicBlock* block)
9180 {
9181     // This function searches for IL offsets in statement nodes, so it can't be used in LIR. We
9182     // could have a similar function for LIR that searches for GT_IL_OFFSET nodes.
9183     assert(!block->IsLIR());
9184
9185     for (GenTree* stmt = block->bbTreeList; stmt != nullptr; stmt = stmt->gtNext)
9186     {
9187         assert(stmt->IsStatement());
9188         if (stmt->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET)
9189         {
9190             return jitGetILoffs(stmt->gtStmt.gtStmtILoffsx);
9191         }
9192     }
9193
9194     return BAD_IL_OFFSET;
9195 }
9196
9197 //------------------------------------------------------------------------------
9198 // fgSplitBlockAtEnd - split the given block into two blocks.
9199 //                   All code in the block stays in the original block.
9200 //                   Control falls through from original to new block, and
9201 //                   the new block is returned.
9202 //------------------------------------------------------------------------------
9203 BasicBlock* Compiler::fgSplitBlockAtEnd(BasicBlock* curr)
9204 {
9205     // We'd like to use fgNewBBafter(), but we need to update the preds list before linking in the new block.
9206     // (We need the successors of 'curr' to be correct when we do this.)
9207     BasicBlock* newBlock = bbNewBasicBlock(curr->bbJumpKind);
9208
9209     // Start the new block with no refs. When we set the preds below, this will get updated correctly.
9210     newBlock->bbRefs = 0;
9211
9212     // For each successor of the original block, set the new block as their predecessor.
9213     // Note we are using the "rational" version of the successor iterator that does not hide the finallyret arcs.
9214     // Without these arcs, a block 'b' may not be a member of succs(preds(b))
9215     if (curr->bbJumpKind != BBJ_SWITCH)
9216     {
9217         unsigned numSuccs = curr->NumSucc(this);
9218         for (unsigned i = 0; i < numSuccs; i++)
9219         {
9220             BasicBlock* succ = curr->GetSucc(i, this);
9221             if (succ != newBlock)
9222             {
9223                 JITDUMP("BB%02u previous predecessor was BB%02u, now is BB%02u\n", succ->bbNum, curr->bbNum,
9224                         newBlock->bbNum);
9225                 fgReplacePred(succ, curr, newBlock);
9226             }
9227         }
9228
9229         newBlock->bbJumpDest = curr->bbJumpDest;
9230         curr->bbJumpDest     = nullptr;
9231     }
9232     else
9233     {
9234         // In the case of a switch statement there's more complicated logic in order to wire up the predecessor lists
9235         // but fortunately there's an existing method that implements this functionality.
9236         newBlock->bbJumpSwt = curr->bbJumpSwt;
9237
9238         fgChangeSwitchBlock(curr, newBlock);
9239
9240         curr->bbJumpSwt = nullptr;
9241     }
9242
9243     newBlock->inheritWeight(curr);
9244
9245     // Set the new block's flags. Note that the new block isn't BBF_INTERNAL unless the old block is.
9246     newBlock->bbFlags = curr->bbFlags;
9247
9248     // Remove flags that the new block can't have.
9249     newBlock->bbFlags &= ~(BBF_TRY_BEG | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1 | BBF_HAS_LABEL |
9250                            BBF_JMP_TARGET | BBF_FUNCLET_BEG | BBF_LOOP_PREHEADER | BBF_KEEP_BBJ_ALWAYS);
9251
9252     // Remove the GC safe bit on the new block. It seems clear that if we split 'curr' at the end,
9253     // such that all the code is left in 'curr', and 'newBlock' just gets the control flow, then
9254     // both 'curr' and 'newBlock' could accurately retain an existing GC safe bit. However, callers
9255     // use this function to split blocks in the middle, or at the beginning, and they don't seem to
9256     // be careful about updating this flag appropriately. So, removing the GC safe bit is simply
9257     // conservative: some functions might end up being fully interruptible that could be partially
9258     // interruptible if we exercised more care here.
9259     newBlock->bbFlags &= ~BBF_GC_SAFE_POINT;
9260
9261 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9262     newBlock->bbFlags &= ~(BBF_FINALLY_TARGET);
9263 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9264
9265     // The new block has no code, so we leave bbCodeOffs/bbCodeOffsEnd set to BAD_IL_OFFSET. If a caller
9266     // puts code in the block, then it needs to update these.
9267
9268     // Insert the new block in the block list after the 'curr' block.
9269     fgInsertBBafter(curr, newBlock);
9270     fgExtendEHRegionAfter(curr); // The new block is in the same EH region as the old block.
9271
9272     // Remove flags from the old block that are no longer possible.
9273     curr->bbFlags &= ~(BBF_HAS_JMP | BBF_RETLESS_CALL);
9274
9275     // Default to fallthru, and add the arc for that.
9276     curr->bbJumpKind = BBJ_NONE;
9277     fgAddRefPred(newBlock, curr);
9278
9279     return newBlock;
9280 }
9281
9282 //------------------------------------------------------------------------------
9283 // fgSplitBlockAfterStatement - Split the given block, with all code after
9284 //                              the given statement going into the second block.
9285 //------------------------------------------------------------------------------
9286 BasicBlock* Compiler::fgSplitBlockAfterStatement(BasicBlock* curr, GenTree* stmt)
9287 {
9288     assert(!curr->IsLIR()); // No statements in LIR, so you can't use this function.
9289
9290     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
9291
9292     if (stmt)
9293     {
9294         newBlock->bbTreeList = stmt->gtNext;
9295         if (newBlock->bbTreeList)
9296         {
9297             newBlock->bbTreeList->gtPrev = curr->bbTreeList->gtPrev;
9298         }
9299         curr->bbTreeList->gtPrev = stmt;
9300         stmt->gtNext             = nullptr;
9301
9302         // Update the IL offsets of the blocks to match the split.
9303
9304         assert(newBlock->bbCodeOffs == BAD_IL_OFFSET);
9305         assert(newBlock->bbCodeOffsEnd == BAD_IL_OFFSET);
9306
9307         // curr->bbCodeOffs remains the same
9308         newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
9309
9310         IL_OFFSET splitPointILOffset = fgFindBlockILOffset(newBlock);
9311
9312         curr->bbCodeOffsEnd  = splitPointILOffset;
9313         newBlock->bbCodeOffs = splitPointILOffset;
9314     }
9315     else
9316     {
9317         assert(curr->bbTreeList == nullptr); // if no tree was given then it better be an empty block
9318     }
9319
9320     return newBlock;
9321 }
9322
9323 //------------------------------------------------------------------------------
9324 // fgSplitBlockAfterNode - Split the given block, with all code after
9325 //                         the given node going into the second block.
9326 //                         This function is only used in LIR.
9327 //------------------------------------------------------------------------------
9328 BasicBlock* Compiler::fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node)
9329 {
9330     assert(curr->IsLIR());
9331
9332     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
9333
9334     if (node != nullptr)
9335     {
9336         LIR::Range& currBBRange = LIR::AsRange(curr);
9337
9338         if (node != currBBRange.LastNode())
9339         {
9340             LIR::Range nodesToMove = currBBRange.Remove(node->gtNext, currBBRange.LastNode());
9341             LIR::AsRange(newBlock).InsertAtBeginning(std::move(nodesToMove));
9342         }
9343
9344         // Update the IL offsets of the blocks to match the split.
9345
9346         assert(newBlock->bbCodeOffs == BAD_IL_OFFSET);
9347         assert(newBlock->bbCodeOffsEnd == BAD_IL_OFFSET);
9348
9349         // curr->bbCodeOffs remains the same
9350         newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
9351
9352         // Search backwards from the end of the current block looking for the IL offset to use
9353         // for the end IL offset for the original block.
9354         IL_OFFSET                   splitPointILOffset = BAD_IL_OFFSET;
9355         LIR::Range::ReverseIterator riter;
9356         LIR::Range::ReverseIterator riterEnd;
9357         for (riter = currBBRange.rbegin(), riterEnd = currBBRange.rend(); riter != riterEnd; ++riter)
9358         {
9359             if ((*riter)->gtOper == GT_IL_OFFSET)
9360             {
9361                 GenTreeStmt* stmt = (*riter)->AsStmt();
9362                 if (stmt->gtStmtILoffsx != BAD_IL_OFFSET)
9363                 {
9364                     splitPointILOffset = jitGetILoffs(stmt->gtStmtILoffsx);
9365                     break;
9366                 }
9367             }
9368         }
9369
9370         curr->bbCodeOffsEnd = splitPointILOffset;
9371
9372         // Also use this as the beginning offset of the next block. Presumably we could/should
9373         // look to see if the first node is a GT_IL_OFFSET node, and use that instead.
9374         newBlock->bbCodeOffs = splitPointILOffset;
9375     }
9376     else
9377     {
9378         assert(curr->bbTreeList == nullptr); // if no node was given then it better be an empty block
9379     }
9380
9381     return newBlock;
9382 }
9383
9384 //------------------------------------------------------------------------------
9385 // fgSplitBlockAtBeginning - Split the given block into two blocks.
9386 //                         Control falls through from original to new block,
9387 //                         and the new block is returned.
9388 //                         All code in the original block goes into the new block
9389 //------------------------------------------------------------------------------
9390 BasicBlock* Compiler::fgSplitBlockAtBeginning(BasicBlock* curr)
9391 {
9392     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
9393
9394     newBlock->bbTreeList = curr->bbTreeList;
9395     curr->bbTreeList     = nullptr;
9396
9397     // The new block now has all the code, and the old block has none. Update the
9398     // IL offsets for the block to reflect this.
9399
9400     newBlock->bbCodeOffs    = curr->bbCodeOffs;
9401     newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
9402
9403     curr->bbCodeOffs    = BAD_IL_OFFSET;
9404     curr->bbCodeOffsEnd = BAD_IL_OFFSET;
9405
9406     return newBlock;
9407 }
9408
9409 //------------------------------------------------------------------------
9410 // fgSplitEdge: Splits the edge between a block 'curr' and its successor 'succ' by creating a new block
9411 //              that replaces 'succ' as a successor of 'curr', and which branches unconditionally
9412 //              to (or falls through to) 'succ'. Note that for a BBJ_COND block 'curr',
9413 //              'succ' might be the fall-through path or the branch path from 'curr'.
9414 //
9415 // Arguments:
9416 //    curr - A block which branches conditionally to 'succ'
9417 //    succ - The target block
9418 //
9419 // Return Value:
9420 //    Returns a new block, that is a successor of 'curr' and which branches unconditionally to 'succ'
9421 //
9422 // Assumptions:
9423 //    'curr' must have a bbJumpKind of BBJ_COND or BBJ_SWITCH
9424 //
9425 // Notes:
9426 //    The returned block is empty.
9427
9428 BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ)
9429 {
9430     assert(curr->bbJumpKind == BBJ_COND || curr->bbJumpKind == BBJ_SWITCH);
9431     assert(fgGetPredForBlock(succ, curr) != nullptr);
9432
9433     BasicBlock* newBlock;
9434     if (succ == curr->bbNext)
9435     {
9436         // The successor is the fall-through path of a BBJ_COND, or
9437         // an immediately following block of a BBJ_SWITCH (which has
9438         // no fall-through path). For this case, simply insert a new
9439         // fall-through block after 'curr'.
9440         newBlock = fgNewBBafter(BBJ_NONE, curr, true /*extendRegion*/);
9441     }
9442     else
9443     {
9444         newBlock = fgNewBBinRegion(BBJ_ALWAYS, curr, curr->isRunRarely());
9445         // The new block always jumps to 'succ'
9446         newBlock->bbJumpDest = succ;
9447     }
9448     newBlock->bbFlags |= (curr->bbFlags & succ->bbFlags & (BBF_BACKWARD_JUMP));
9449
9450     JITDUMP("Splitting edge from BB%02u to BB%02u; adding BB%02u\n", curr->bbNum, succ->bbNum, newBlock->bbNum);
9451
9452     if (curr->bbJumpKind == BBJ_COND)
9453     {
9454         fgReplacePred(succ, curr, newBlock);
9455         if (curr->bbJumpDest == succ)
9456         {
9457             // Now 'curr' jumps to newBlock
9458             curr->bbJumpDest = newBlock;
9459             newBlock->bbFlags |= BBF_JMP_TARGET;
9460         }
9461         fgAddRefPred(newBlock, curr);
9462     }
9463     else
9464     {
9465         assert(curr->bbJumpKind == BBJ_SWITCH);
9466
9467         // newBlock replaces 'succ' in the switch.
9468         fgReplaceSwitchJumpTarget(curr, newBlock, succ);
9469
9470         // And 'succ' has 'newBlock' as a new predecessor.
9471         fgAddRefPred(succ, newBlock);
9472     }
9473
9474     // This isn't accurate, but it is complex to compute a reasonable number so just assume that we take the
9475     // branch 50% of the time.
9476     newBlock->inheritWeightPercentage(curr, 50);
9477
9478     // The bbLiveIn and bbLiveOut are both equal to the bbLiveIn of 'succ'
9479     if (fgLocalVarLivenessDone)
9480     {
9481         VarSetOps::Assign(this, newBlock->bbLiveIn, succ->bbLiveIn);
9482         VarSetOps::Assign(this, newBlock->bbLiveOut, succ->bbLiveIn);
9483     }
9484
9485     return newBlock;
9486 }
9487
9488 /*****************************************************************************/
9489 /*****************************************************************************/
9490
9491 void Compiler::fgFindOperOrder()
9492 {
9493 #ifdef DEBUG
9494     if (verbose)
9495     {
9496         printf("*************** In fgFindOperOrder()\n");
9497     }
9498 #endif
9499
9500     BasicBlock*  block;
9501     GenTreeStmt* stmt;
9502
9503     /* Walk the basic blocks and for each statement determine
9504      * the evaluation order, cost, FP levels, etc... */
9505
9506     for (block = fgFirstBB; block; block = block->bbNext)
9507     {
9508         compCurBB = block;
9509         for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
9510         {
9511             /* Recursively process the statement */
9512
9513             compCurStmt = stmt;
9514             gtSetStmtInfo(stmt);
9515         }
9516     }
9517 }
9518
9519 //------------------------------------------------------------------------
9520 // fgSimpleLowering: do full walk of all IR, lowering selected operations
9521 // and computing lvaOutgoingArgumentAreaSize.
9522 //
9523 // Notes:
9524 //    Lowers GT_ARR_LENGTH, GT_ARR_BOUNDS_CHECK, and GT_SIMD_CHK.
9525 //
9526 //    For target ABIs with fixed out args area, computes upper bound on
9527 //    the size of this area from the calls in the IR.
9528 //
9529 //    Outgoing arg area size is computed here because we want to run it
9530 //    after optimization (in case calls are removed) and need to look at
9531 //    all possible calls in the method.
9532
9533 void Compiler::fgSimpleLowering()
9534 {
9535 #if FEATURE_FIXED_OUT_ARGS
9536     unsigned outgoingArgSpaceSize = 0;
9537 #endif // FEATURE_FIXED_OUT_ARGS
9538
9539     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
9540     {
9541         // Walk the statement trees in this basic block.
9542         compCurBB = block; // Used in fgRngChkTarget.
9543
9544         LIR::Range& range = LIR::AsRange(block);
9545         for (GenTree* tree : range)
9546         {
9547             switch (tree->OperGet())
9548             {
9549                 case GT_ARR_LENGTH:
9550                 {
9551                     GenTreeArrLen* arrLen = tree->AsArrLen();
9552                     GenTree*       arr    = arrLen->gtArrLen.ArrRef();
9553                     GenTree*       add;
9554                     GenTree*       con;
9555
9556                     /* Create the expression "*(array_addr + ArrLenOffs)" */
9557
9558                     noway_assert(arr->gtNext == tree);
9559
9560                     noway_assert(arrLen->ArrLenOffset() == offsetof(CORINFO_Array, length) ||
9561                                  arrLen->ArrLenOffset() == offsetof(CORINFO_String, stringLen));
9562
9563                     if ((arr->gtOper == GT_CNS_INT) && (arr->gtIntCon.gtIconVal == 0))
9564                     {
9565                         // If the array is NULL, then we should get a NULL reference
9566                         // exception when computing its length.  We need to maintain
9567                         // an invariant where there is no sum of two constants node, so
9568                         // let's simply return an indirection of NULL.
9569
9570                         add = arr;
9571                     }
9572                     else
9573                     {
9574                         con             = gtNewIconNode(arrLen->ArrLenOffset(), TYP_I_IMPL);
9575                         con->gtRsvdRegs = RBM_NONE;
9576
9577                         add             = gtNewOperNode(GT_ADD, TYP_REF, arr, con);
9578                         add->gtRsvdRegs = arr->gtRsvdRegs;
9579
9580                         range.InsertAfter(arr, con, add);
9581                     }
9582
9583                     // Change to a GT_IND.
9584                     tree->ChangeOperUnchecked(GT_IND);
9585
9586                     tree->gtOp.gtOp1 = add;
9587                     break;
9588                 }
9589
9590                 case GT_ARR_BOUNDS_CHECK:
9591 #ifdef FEATURE_SIMD
9592                 case GT_SIMD_CHK:
9593 #endif // FEATURE_SIMD
9594 #ifdef FEATURE_HW_INTRINSICS
9595                 case GT_HW_INTRINSIC_CHK:
9596 #endif // FEATURE_HW_INTRINSICS
9597                 {
9598                     // Add in a call to an error routine.
9599                     fgSetRngChkTarget(tree, false);
9600                     break;
9601                 }
9602
9603 #if FEATURE_FIXED_OUT_ARGS
9604                 case GT_CALL:
9605                 {
9606                     GenTreeCall* call = tree->AsCall();
9607                     // Fast tail calls use the caller-supplied scratch
9608                     // space so have no impact on this method's outgoing arg size.
9609                     if (!call->IsFastTailCall())
9610                     {
9611                         // Update outgoing arg size to handle this call
9612                         const unsigned thisCallOutAreaSize = call->fgArgInfo->GetOutArgSize();
9613                         assert(thisCallOutAreaSize >= MIN_ARG_AREA_FOR_CALL);
9614
9615                         if (thisCallOutAreaSize > outgoingArgSpaceSize)
9616                         {
9617                             outgoingArgSpaceSize = thisCallOutAreaSize;
9618                             JITDUMP("Bumping outgoingArgSpaceSize to %u for call [%06d]\n", outgoingArgSpaceSize,
9619                                     dspTreeID(tree));
9620                         }
9621                         else
9622                         {
9623                             JITDUMP("outgoingArgSpaceSize %u sufficient for call [%06d], which needs %u\n",
9624                                     outgoingArgSpaceSize, dspTreeID(tree), thisCallOutAreaSize);
9625                         }
9626                     }
9627                     else
9628                     {
9629                         JITDUMP("outgoingArgSpaceSize not impacted by fast tail call [%06d]\n", dspTreeID(tree));
9630                     }
9631                     break;
9632                 }
9633 #endif // FEATURE_FIXED_OUT_ARGS
9634
9635                 default:
9636                 {
9637                     // No other operators need processing.
9638                     break;
9639                 }
9640             } // switch on oper
9641         }     // foreach tree
9642     }         // foreach BB
9643
9644 #if FEATURE_FIXED_OUT_ARGS
9645     // Finish computing the outgoing args area size
9646     //
9647     // Need to make sure the MIN_ARG_AREA_FOR_CALL space is added to the frame if:
9648     // 1. there are calls to THROW_HEPLPER methods.
9649     // 2. we are generating profiling Enter/Leave/TailCall hooks. This will ensure
9650     //    that even methods without any calls will have outgoing arg area space allocated.
9651     //
9652     // An example for these two cases is Windows Amd64, where the ABI requires to have 4 slots for
9653     // the outgoing arg space if the method makes any calls.
9654     if (outgoingArgSpaceSize < MIN_ARG_AREA_FOR_CALL)
9655     {
9656         if (compUsesThrowHelper || compIsProfilerHookNeeded())
9657         {
9658             outgoingArgSpaceSize = MIN_ARG_AREA_FOR_CALL;
9659             JITDUMP("Bumping outgoingArgSpaceSize to %u for throw helper or profile hook", outgoingArgSpaceSize);
9660         }
9661     }
9662
9663     // If a function has localloc, we will need to move the outgoing arg space when the
9664     // localloc happens. When we do this, we need to maintain stack alignment. To avoid
9665     // leaving alignment-related holes when doing this move, make sure the outgoing
9666     // argument space size is a multiple of the stack alignment by aligning up to the next
9667     // stack alignment boundary.
9668     if (compLocallocUsed)
9669     {
9670         outgoingArgSpaceSize = (unsigned)roundUp(outgoingArgSpaceSize, STACK_ALIGN);
9671         JITDUMP("Bumping outgoingArgSpaceSize to %u for localloc", outgoingArgSpaceSize);
9672     }
9673
9674     // Publish the final value and mark it as read only so any update
9675     // attempt later will cause an assert.
9676     lvaOutgoingArgSpaceSize = outgoingArgSpaceSize;
9677     lvaOutgoingArgSpaceSize.MarkAsReadOnly();
9678
9679 #endif // FEATURE_FIXED_OUT_ARGS
9680
9681 #ifdef DEBUG
9682     if (verbose && fgRngChkThrowAdded)
9683     {
9684         printf("\nAfter fgSimpleLowering() added some RngChk throw blocks");
9685         fgDispBasicBlocks();
9686         fgDispHandlerTab();
9687         printf("\n");
9688     }
9689 #endif
9690 }
9691
9692 /*****************************************************************************
9693  */
9694
9695 void Compiler::fgUpdateRefCntForClone(BasicBlock* addedToBlock, GenTree* clonedTree)
9696 {
9697     assert(clonedTree->gtOper != GT_STMT);
9698
9699     if (lvaLocalVarRefCounted)
9700     {
9701         compCurBB = addedToBlock;
9702         IncLclVarRefCountsVisitor::WalkTree(this, clonedTree);
9703     }
9704 }
9705
9706 /*****************************************************************************
9707  */
9708
9709 void Compiler::fgUpdateRefCntForExtract(GenTree* wholeTree, GenTree* keptTree)
9710 {
9711     if (lvaLocalVarRefCounted)
9712     {
9713         /*  Update the refCnts of removed lcl vars - The problem is that
9714          *  we have to consider back the side effects trees so we first
9715          *  increment all refCnts for side effects then decrement everything
9716          *  in the statement
9717          */
9718         if (keptTree)
9719         {
9720             IncLclVarRefCountsVisitor::WalkTree(this, keptTree);
9721         }
9722
9723         DecLclVarRefCountsVisitor::WalkTree(this, wholeTree);
9724     }
9725 }
9726
9727 VARSET_VALRET_TP Compiler::fgGetVarBits(GenTree* tree)
9728 {
9729     VARSET_TP varBits(VarSetOps::MakeEmpty(this));
9730
9731     assert(tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_LCL_FLD || tree->gtOper == GT_REG_VAR);
9732
9733     unsigned int lclNum = tree->gtLclVarCommon.gtLclNum;
9734     LclVarDsc*   varDsc = lvaTable + lclNum;
9735     if (varDsc->lvTracked)
9736     {
9737         VarSetOps::AddElemD(this, varBits, varDsc->lvVarIndex);
9738     }
9739     // We have to check type of root tree, not Local Var descriptor because
9740     // for legacy backend we promote TYP_STRUCT to TYP_INT if it is an unused or
9741     // independently promoted non-argument struct local.
9742     // For more details see Compiler::raAssignVars() method.
9743     else if (tree->gtType == TYP_STRUCT && varDsc->lvPromoted)
9744     {
9745         assert(varDsc->lvType == TYP_STRUCT);
9746         for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i)
9747         {
9748             noway_assert(lvaTable[i].lvIsStructField);
9749             if (lvaTable[i].lvTracked)
9750             {
9751                 unsigned varIndex = lvaTable[i].lvVarIndex;
9752                 noway_assert(varIndex < lvaTrackedCount);
9753                 VarSetOps::AddElemD(this, varBits, varIndex);
9754             }
9755         }
9756     }
9757     return varBits;
9758 }
9759
9760 /*****************************************************************************
9761  *
9762  *  Find and remove any basic blocks that are useless (e.g. they have not been
9763  *  imported because they are not reachable, or they have been optimized away).
9764  */
9765
9766 void Compiler::fgRemoveEmptyBlocks()
9767 {
9768     BasicBlock* cur;
9769     BasicBlock* nxt;
9770
9771     /* If we remove any blocks, we'll have to do additional work */
9772
9773     unsigned removedBlks = 0;
9774
9775     for (cur = fgFirstBB; cur != nullptr; cur = nxt)
9776     {
9777         /* Get hold of the next block (in case we delete 'cur') */
9778
9779         nxt = cur->bbNext;
9780
9781         /* Should this block be removed? */
9782
9783         if (!(cur->bbFlags & BBF_IMPORTED))
9784         {
9785             noway_assert(cur->isEmpty());
9786
9787             if (ehCanDeleteEmptyBlock(cur))
9788             {
9789                 /* Mark the block as removed */
9790
9791                 cur->bbFlags |= BBF_REMOVED;
9792
9793                 /* Remember that we've removed a block from the list */
9794
9795                 removedBlks++;
9796
9797 #ifdef DEBUG
9798                 if (verbose)
9799                 {
9800                     printf("BB%02u was not imported, marked as removed (%d)\n", cur->bbNum, removedBlks);
9801                 }
9802 #endif // DEBUG
9803
9804                 /* Drop the block from the list */
9805
9806                 fgUnlinkBlock(cur);
9807             }
9808             else
9809             {
9810                 // We were prevented from deleting this block by EH normalization. Mark the block as imported.
9811                 cur->bbFlags |= BBF_IMPORTED;
9812             }
9813         }
9814     }
9815
9816     /* If no blocks were removed, we're done */
9817
9818     if (removedBlks == 0)
9819     {
9820         return;
9821     }
9822
9823     /*  Update all references in the exception handler table.
9824      *  Mark the new blocks as non-removable.
9825      *
9826      *  We may have made the entire try block unreachable.
9827      *  Check for this case and remove the entry from the EH table.
9828      */
9829
9830     unsigned  XTnum;
9831     EHblkDsc* HBtab;
9832     INDEBUG(unsigned delCnt = 0;)
9833
9834     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
9835     {
9836     AGAIN:
9837         /* If the beginning of the try block was not imported, we
9838          * need to remove the entry from the EH table. */
9839
9840         if (HBtab->ebdTryBeg->bbFlags & BBF_REMOVED)
9841         {
9842             noway_assert(!(HBtab->ebdTryBeg->bbFlags & BBF_IMPORTED));
9843 #ifdef DEBUG
9844             if (verbose)
9845             {
9846                 printf("Beginning of try block (BB%02u) not imported "
9847                        "- remove index #%u from the EH table\n",
9848                        HBtab->ebdTryBeg->bbNum, XTnum + delCnt);
9849             }
9850             delCnt++;
9851 #endif // DEBUG
9852
9853             fgRemoveEHTableEntry(XTnum);
9854
9855             if (XTnum < compHndBBtabCount)
9856             {
9857                 // There are more entries left to process, so do more. Note that
9858                 // HBtab now points to the next entry, that we copied down to the
9859                 // current slot. XTnum also stays the same.
9860                 goto AGAIN;
9861             }
9862
9863             break; // no more entries (we deleted the last one), so exit the loop
9864         }
9865
9866 /* At this point we know we have a valid try block */
9867
9868 #ifdef DEBUG
9869         assert(HBtab->ebdTryBeg->bbFlags & BBF_IMPORTED);
9870         assert(HBtab->ebdTryBeg->bbFlags & BBF_DONT_REMOVE);
9871
9872         assert(HBtab->ebdHndBeg->bbFlags & BBF_IMPORTED);
9873         assert(HBtab->ebdHndBeg->bbFlags & BBF_DONT_REMOVE);
9874
9875         if (HBtab->HasFilter())
9876         {
9877             assert(HBtab->ebdFilter->bbFlags & BBF_IMPORTED);
9878             assert(HBtab->ebdFilter->bbFlags & BBF_DONT_REMOVE);
9879         }
9880 #endif // DEBUG
9881
9882         fgSkipRmvdBlocks(HBtab);
9883     } /* end of the for loop over XTnum */
9884
9885     // Renumber the basic blocks
9886     JITDUMP("\nRenumbering the basic blocks for fgRemoveEmptyBlocks\n");
9887     fgRenumberBlocks();
9888
9889 #ifdef DEBUG
9890     fgVerifyHandlerTab();
9891 #endif // DEBUG
9892 }
9893
9894 /*****************************************************************************
9895  *
9896  * Remove a useless statement from a basic block.
9897  * The default is to decrement ref counts of included vars
9898  *
9899  */
9900
9901 void Compiler::fgRemoveStmt(BasicBlock* block,
9902                             GenTree*    node,
9903                             // whether to decrement ref counts for tracked vars in statement
9904                             bool updateRefCount)
9905 {
9906     noway_assert(node);
9907     assert(fgOrder == FGOrderTree);
9908
9909     GenTreeStmt* tree = block->firstStmt();
9910     GenTreeStmt* stmt = node->AsStmt();
9911
9912 #ifdef DEBUG
9913     if (verbose &&
9914         stmt->gtStmtExpr->gtOper != GT_NOP) // Don't print if it is a GT_NOP. Too much noise from the inliner.
9915     {
9916         printf("\nRemoving statement ");
9917         printTreeID(stmt);
9918         printf(" in BB%02u as useless:\n", block->bbNum);
9919         gtDispTree(stmt);
9920     }
9921 #endif // DEBUG
9922
9923     if (opts.compDbgCode && stmt->gtPrev != stmt && stmt->gtStmtILoffsx != BAD_IL_OFFSET)
9924     {
9925         /* TODO: For debuggable code, should we remove significant
9926            statement boundaries. Or should we leave a GT_NO_OP in its place? */
9927     }
9928
9929     /* Is it the first statement in the list? */
9930
9931     GenTreeStmt* firstStmt = block->firstStmt();
9932     if (firstStmt == stmt)
9933     {
9934         if (firstStmt->gtNext == nullptr)
9935         {
9936             assert(firstStmt == block->lastStmt());
9937
9938             /* this is the only statement - basic block becomes empty */
9939             block->bbTreeList = nullptr;
9940         }
9941         else
9942         {
9943             block->bbTreeList         = tree->gtNext;
9944             block->bbTreeList->gtPrev = tree->gtPrev;
9945         }
9946         goto DONE;
9947     }
9948
9949     /* Is it the last statement in the list? */
9950
9951     if (stmt == block->lastStmt())
9952     {
9953         stmt->gtPrev->gtNext      = nullptr;
9954         block->bbTreeList->gtPrev = stmt->gtPrev;
9955         goto DONE;
9956     }
9957
9958     tree = stmt->gtPrevStmt;
9959     noway_assert(tree);
9960
9961     tree->gtNext         = stmt->gtNext;
9962     stmt->gtNext->gtPrev = tree;
9963
9964 DONE:
9965     fgStmtRemoved = true;
9966
9967     noway_assert(!optValnumCSE_phase);
9968
9969     if (updateRefCount)
9970     {
9971         if (fgStmtListThreaded)
9972         {
9973             DecLclVarRefCountsVisitor::WalkTree(this, stmt->gtStmtExpr);
9974         }
9975     }
9976
9977 #ifdef DEBUG
9978     if (verbose)
9979     {
9980         if (block->bbTreeList == nullptr)
9981         {
9982             printf("\nBB%02u becomes empty", block->bbNum);
9983         }
9984         printf("\n");
9985     }
9986 #endif // DEBUG
9987 }
9988
9989 /******************************************************************************/
9990 // Returns true if the operator is involved in control-flow
9991 // TODO-Cleanup: Move this into genTreeKinds in genTree.h
9992
9993 inline bool OperIsControlFlow(genTreeOps oper)
9994 {
9995     switch (oper)
9996     {
9997         case GT_JTRUE:
9998         case GT_JCMP:
9999         case GT_JCC:
10000         case GT_SWITCH:
10001         case GT_LABEL:
10002
10003         case GT_CALL:
10004         case GT_JMP:
10005
10006         case GT_RETURN:
10007         case GT_RETFILT:
10008 #if !FEATURE_EH_FUNCLETS
10009         case GT_END_LFIN:
10010 #endif // !FEATURE_EH_FUNCLETS
10011             return true;
10012
10013         default:
10014             return false;
10015     }
10016 }
10017
10018 /******************************************************************************
10019  *  Tries to throw away a stmt. The statement can be anywhere in block->bbTreeList.
10020  *  Returns true if it did remove the statement.
10021  */
10022
10023 bool Compiler::fgCheckRemoveStmt(BasicBlock* block, GenTree* node)
10024 {
10025     if (opts.compDbgCode)
10026     {
10027         return false;
10028     }
10029
10030     GenTreeStmt* stmt = node->AsStmt();
10031
10032     GenTree*   tree = stmt->gtStmtExpr;
10033     genTreeOps oper = tree->OperGet();
10034
10035     if (OperIsControlFlow(oper) || GenTree::OperIsHWIntrinsic(oper) || oper == GT_NO_OP)
10036     {
10037         return false;
10038     }
10039
10040     // TODO: Use a recursive version of gtNodeHasSideEffects()
10041     if (tree->gtFlags & GTF_SIDE_EFFECT)
10042     {
10043         return false;
10044     }
10045
10046     fgRemoveStmt(block, stmt);
10047     return true;
10048 }
10049
10050 /****************************************************************************************************
10051  *
10052  *
10053  */
10054 bool Compiler::fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext)
10055 {
10056     if ((block == nullptr) || (bNext == nullptr))
10057     {
10058         return false;
10059     }
10060
10061     noway_assert(block->bbNext == bNext);
10062
10063     if (block->bbJumpKind != BBJ_NONE)
10064     {
10065         return false;
10066     }
10067
10068     // If the next block has multiple incoming edges, we can still compact if the first block is empty.
10069     // However, not if it is the beginning of a handler.
10070     if (bNext->countOfInEdges() != 1 &&
10071         (!block->isEmpty() || (block->bbFlags & BBF_FUNCLET_BEG) || (block->bbCatchTyp != BBCT_NONE)))
10072     {
10073         return false;
10074     }
10075
10076     if (bNext->bbFlags & BBF_DONT_REMOVE)
10077     {
10078         return false;
10079     }
10080
10081     // Don't compact the first block if it was specially created as a scratch block.
10082     if (fgBBisScratch(block))
10083     {
10084         return false;
10085     }
10086
10087 #if defined(_TARGET_ARM_)
10088     // We can't compact a finally target block, as we need to generate special code for such blocks during code
10089     // generation
10090     if ((bNext->bbFlags & BBF_FINALLY_TARGET) != 0)
10091         return false;
10092 #endif
10093
10094     // We don't want to compact blocks that are in different Hot/Cold regions
10095     //
10096     if (fgInDifferentRegions(block, bNext))
10097     {
10098         return false;
10099     }
10100
10101     // We cannot compact two blocks in different EH regions.
10102     //
10103     if (fgCanRelocateEHRegions)
10104     {
10105         if (!BasicBlock::sameEHRegion(block, bNext))
10106         {
10107             return false;
10108         }
10109     }
10110     // if there is a switch predecessor don't bother because we'd have to update the uniquesuccs as well
10111     // (if they are valid)
10112     for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext)
10113     {
10114         if (pred->flBlock->bbJumpKind == BBJ_SWITCH)
10115         {
10116             return false;
10117         }
10118     }
10119
10120     return true;
10121 }
10122
10123 /*****************************************************************************************************
10124  *
10125  *  Function called to compact two given blocks in the flowgraph
10126  *  Assumes that all necessary checks have been performed,
10127  *  i.e. fgCanCompactBlocks returns true.
10128  *
10129  *  Uses for this function - whenever we change links, insert blocks,...
10130  *  It will keep the flowgraph data in synch - bbNum, bbRefs, bbPreds
10131  */
10132
10133 void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext)
10134 {
10135     noway_assert(block != nullptr);
10136     noway_assert((block->bbFlags & BBF_REMOVED) == 0);
10137     noway_assert(block->bbJumpKind == BBJ_NONE);
10138
10139     noway_assert(bNext == block->bbNext);
10140     noway_assert(bNext != nullptr);
10141     noway_assert((bNext->bbFlags & BBF_REMOVED) == 0);
10142     noway_assert(bNext->countOfInEdges() == 1 || block->isEmpty());
10143     noway_assert(bNext->bbPreds);
10144
10145 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10146     noway_assert((bNext->bbFlags & BBF_FINALLY_TARGET) == 0);
10147 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10148
10149     // Make sure the second block is not the start of a TRY block or an exception handler
10150
10151     noway_assert(bNext->bbCatchTyp == BBCT_NONE);
10152     noway_assert((bNext->bbFlags & BBF_TRY_BEG) == 0);
10153     noway_assert((bNext->bbFlags & BBF_DONT_REMOVE) == 0);
10154
10155     /* both or none must have an exception handler */
10156     noway_assert(block->hasTryIndex() == bNext->hasTryIndex());
10157
10158 #ifdef DEBUG
10159     if (verbose)
10160     {
10161         printf("\nCompacting blocks BB%02u and BB%02u:\n", block->bbNum, bNext->bbNum);
10162     }
10163 #endif
10164
10165     if (bNext->countOfInEdges() > 1)
10166     {
10167         JITDUMP("Second block has multiple incoming edges\n");
10168
10169         assert(block->isEmpty());
10170         block->bbFlags |= BBF_JMP_TARGET;
10171         for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext)
10172         {
10173             fgReplaceJumpTarget(pred->flBlock, block, bNext);
10174
10175             if (pred->flBlock != block)
10176             {
10177                 fgAddRefPred(block, pred->flBlock);
10178             }
10179         }
10180         bNext->bbPreds = nullptr;
10181     }
10182     else
10183     {
10184         noway_assert(bNext->bbPreds->flNext == nullptr);
10185         noway_assert(bNext->bbPreds->flBlock == block);
10186     }
10187
10188     /* Start compacting - move all the statements in the second block to the first block */
10189
10190     // First move any phi definitions of the second block after the phi defs of the first.
10191     // TODO-CQ: This may be the wrong thing to do.  If we're compacting blocks, it's because a
10192     // control-flow choice was constant-folded away.  So probably phi's need to go away,
10193     // as well, in favor of one of the incoming branches.  Or at least be modified.
10194
10195     assert(block->IsLIR() == bNext->IsLIR());
10196     if (block->IsLIR())
10197     {
10198         LIR::Range& blockRange = LIR::AsRange(block);
10199         LIR::Range& nextRange  = LIR::AsRange(bNext);
10200
10201         // Does the next block have any phis?
10202         GenTree*           nextFirstNonPhi = nullptr;
10203         LIR::ReadOnlyRange nextPhis        = nextRange.PhiNodes();
10204         if (!nextPhis.IsEmpty())
10205         {
10206             GenTree* blockLastPhi = blockRange.LastPhiNode();
10207             nextFirstNonPhi       = nextPhis.LastNode()->gtNext;
10208
10209             LIR::Range phisToMove = nextRange.Remove(std::move(nextPhis));
10210             blockRange.InsertAfter(blockLastPhi, std::move(phisToMove));
10211         }
10212         else
10213         {
10214             nextFirstNonPhi = nextRange.FirstNode();
10215         }
10216
10217         // Does the block have any other code?
10218         if (nextFirstNonPhi != nullptr)
10219         {
10220             LIR::Range nextNodes = nextRange.Remove(nextFirstNonPhi, nextRange.LastNode());
10221             blockRange.InsertAtEnd(std::move(nextNodes));
10222         }
10223     }
10224     else
10225     {
10226         GenTree* blkNonPhi1   = block->FirstNonPhiDef();
10227         GenTree* bNextNonPhi1 = bNext->FirstNonPhiDef();
10228         GenTree* blkFirst     = block->firstStmt();
10229         GenTree* bNextFirst   = bNext->firstStmt();
10230
10231         // Does the second have any phis?
10232         if (bNextFirst != nullptr && bNextFirst != bNextNonPhi1)
10233         {
10234             GenTree* bNextLast = bNextFirst->gtPrev;
10235             assert(bNextLast->gtNext == nullptr);
10236
10237             // Does "blk" have phis?
10238             if (blkNonPhi1 != blkFirst)
10239             {
10240                 // Yes, has phis.
10241                 // Insert after the last phi of "block."
10242                 // First, bNextPhis after last phi of block.
10243                 GenTree* blkLastPhi;
10244                 if (blkNonPhi1 != nullptr)
10245                 {
10246                     blkLastPhi = blkNonPhi1->gtPrev;
10247                 }
10248                 else
10249                 {
10250                     blkLastPhi = blkFirst->gtPrev;
10251                 }
10252
10253                 blkLastPhi->gtNext = bNextFirst;
10254                 bNextFirst->gtPrev = blkLastPhi;
10255
10256                 // Now, rest of "block" after last phi of "bNext".
10257                 GenTree* bNextLastPhi = nullptr;
10258                 if (bNextNonPhi1 != nullptr)
10259                 {
10260                     bNextLastPhi = bNextNonPhi1->gtPrev;
10261                 }
10262                 else
10263                 {
10264                     bNextLastPhi = bNextFirst->gtPrev;
10265                 }
10266
10267                 bNextLastPhi->gtNext = blkNonPhi1;
10268                 if (blkNonPhi1 != nullptr)
10269                 {
10270                     blkNonPhi1->gtPrev = bNextLastPhi;
10271                 }
10272                 else
10273                 {
10274                     // block has no non phis, so make the last statement be the last added phi.
10275                     blkFirst->gtPrev = bNextLastPhi;
10276                 }
10277
10278                 // Now update the bbTreeList of "bNext".
10279                 bNext->bbTreeList = bNextNonPhi1;
10280                 if (bNextNonPhi1 != nullptr)
10281                 {
10282                     bNextNonPhi1->gtPrev = bNextLast;
10283                 }
10284             }
10285             else
10286             {
10287                 if (blkFirst != nullptr) // If "block" has no statements, fusion will work fine...
10288                 {
10289                     // First, bNextPhis at start of block.
10290                     GenTree* blkLast  = blkFirst->gtPrev;
10291                     block->bbTreeList = bNextFirst;
10292                     // Now, rest of "block" (if it exists) after last phi of "bNext".
10293                     GenTree* bNextLastPhi = nullptr;
10294                     if (bNextNonPhi1 != nullptr)
10295                     {
10296                         // There is a first non phi, so the last phi is before it.
10297                         bNextLastPhi = bNextNonPhi1->gtPrev;
10298                     }
10299                     else
10300                     {
10301                         // All the statements are phi defns, so the last one is the prev of the first.
10302                         bNextLastPhi = bNextFirst->gtPrev;
10303                     }
10304                     bNextFirst->gtPrev   = blkLast;
10305                     bNextLastPhi->gtNext = blkFirst;
10306                     blkFirst->gtPrev     = bNextLastPhi;
10307                     // Now update the bbTreeList of "bNext"
10308                     bNext->bbTreeList = bNextNonPhi1;
10309                     if (bNextNonPhi1 != nullptr)
10310                     {
10311                         bNextNonPhi1->gtPrev = bNextLast;
10312                     }
10313                 }
10314             }
10315         }
10316
10317         // Now proceed with the updated bbTreeLists.
10318         GenTree* stmtList1 = block->firstStmt();
10319         GenTree* stmtList2 = bNext->firstStmt();
10320
10321         /* the block may have an empty list */
10322
10323         if (stmtList1)
10324         {
10325             GenTree* stmtLast1 = block->lastStmt();
10326
10327             /* The second block may be a GOTO statement or something with an empty bbTreeList */
10328             if (stmtList2)
10329             {
10330                 GenTree* stmtLast2 = bNext->lastStmt();
10331
10332                 /* append list2 to list 1 */
10333
10334                 stmtLast1->gtNext = stmtList2;
10335                 stmtList2->gtPrev = stmtLast1;
10336                 stmtList1->gtPrev = stmtLast2;
10337             }
10338         }
10339         else
10340         {
10341             /* block was formerly empty and now has bNext's statements */
10342             block->bbTreeList = stmtList2;
10343         }
10344     }
10345
10346     // Note we could update the local variable weights here by
10347     // calling lvaMarkLocalVars, with the block and weight adjustment.
10348
10349     // If either block or bNext has a profile weight
10350     // or if both block and bNext have non-zero weights
10351     // then we select the highest weight block.
10352
10353     if (block->hasProfileWeight() || bNext->hasProfileWeight() || (block->bbWeight && bNext->bbWeight))
10354     {
10355         // We are keeping block so update its fields
10356         // when bNext has a greater weight
10357
10358         if (block->bbWeight < bNext->bbWeight)
10359         {
10360             block->bbWeight = bNext->bbWeight;
10361
10362             block->bbFlags |= (bNext->bbFlags & BBF_PROF_WEIGHT); // Set the profile weight flag (if necessary)
10363             if (block->bbWeight != 0)
10364             {
10365                 block->bbFlags &= ~BBF_RUN_RARELY; // Clear any RarelyRun flag
10366             }
10367         }
10368     }
10369     // otherwise if either block has a zero weight we select the zero weight
10370     else
10371     {
10372         noway_assert((block->bbWeight == BB_ZERO_WEIGHT) || (bNext->bbWeight == BB_ZERO_WEIGHT));
10373         block->bbWeight = BB_ZERO_WEIGHT;
10374         block->bbFlags |= BBF_RUN_RARELY; // Set the RarelyRun flag
10375     }
10376
10377     /* set the right links */
10378
10379     block->bbJumpKind = bNext->bbJumpKind;
10380     VarSetOps::AssignAllowUninitRhs(this, block->bbLiveOut, bNext->bbLiveOut);
10381
10382     // Update the beginning and ending IL offsets (bbCodeOffs and bbCodeOffsEnd).
10383     // Set the beginning IL offset to the minimum, and the ending offset to the maximum, of the respective blocks.
10384     // If one block has an unknown offset, we take the other block.
10385     // We are merging into 'block', so if its values are correct, just leave them alone.
10386     // TODO: we should probably base this on the statements within.
10387
10388     if (block->bbCodeOffs == BAD_IL_OFFSET)
10389     {
10390         block->bbCodeOffs = bNext->bbCodeOffs; // If they are both BAD_IL_OFFSET, this doesn't change anything.
10391     }
10392     else if (bNext->bbCodeOffs != BAD_IL_OFFSET)
10393     {
10394         // The are both valid offsets; compare them.
10395         if (block->bbCodeOffs > bNext->bbCodeOffs)
10396         {
10397             block->bbCodeOffs = bNext->bbCodeOffs;
10398         }
10399     }
10400
10401     if (block->bbCodeOffsEnd == BAD_IL_OFFSET)
10402     {
10403         block->bbCodeOffsEnd = bNext->bbCodeOffsEnd; // If they are both BAD_IL_OFFSET, this doesn't change anything.
10404     }
10405     else if (bNext->bbCodeOffsEnd != BAD_IL_OFFSET)
10406     {
10407         // The are both valid offsets; compare them.
10408         if (block->bbCodeOffsEnd < bNext->bbCodeOffsEnd)
10409         {
10410             block->bbCodeOffsEnd = bNext->bbCodeOffsEnd;
10411         }
10412     }
10413
10414     if (((block->bbFlags & BBF_INTERNAL) != 0) && ((bNext->bbFlags & BBF_INTERNAL) == 0))
10415     {
10416         // If 'block' is an internal block and 'bNext' isn't, then adjust the flags set on 'block'.
10417         block->bbFlags &= ~BBF_INTERNAL; // Clear the BBF_INTERNAL flag
10418         block->bbFlags |= BBF_IMPORTED;  // Set the BBF_IMPORTED flag
10419     }
10420
10421     /* Update the flags for block with those found in bNext */
10422
10423     block->bbFlags |= (bNext->bbFlags & BBF_COMPACT_UPD);
10424
10425     /* mark bNext as removed */
10426
10427     bNext->bbFlags |= BBF_REMOVED;
10428
10429     /* Unlink bNext and update all the marker pointers if necessary */
10430
10431     fgUnlinkRange(block->bbNext, bNext);
10432
10433     // If bNext was the last block of a try or handler, update the EH table.
10434
10435     ehUpdateForDeletedBlock(bNext);
10436
10437     /* If we're collapsing a block created after the dominators are
10438        computed, rename the block and reuse dominator information from
10439        the other block */
10440     if (fgDomsComputed && block->bbNum > fgDomBBcount)
10441     {
10442         BlockSetOps::Assign(this, block->bbReach, bNext->bbReach);
10443         BlockSetOps::ClearD(this, bNext->bbReach);
10444
10445         block->bbIDom = bNext->bbIDom;
10446         bNext->bbIDom = nullptr;
10447
10448         // In this case, there's no need to update the preorder and postorder numbering
10449         // since we're changing the bbNum, this makes the basic block all set.
10450         block->bbNum = bNext->bbNum;
10451     }
10452
10453     /* Set the jump targets */
10454
10455     switch (bNext->bbJumpKind)
10456     {
10457         case BBJ_CALLFINALLY:
10458             // Propagate RETLESS property
10459             block->bbFlags |= (bNext->bbFlags & BBF_RETLESS_CALL);
10460
10461             __fallthrough;
10462
10463         case BBJ_COND:
10464         case BBJ_ALWAYS:
10465         case BBJ_EHCATCHRET:
10466             block->bbJumpDest = bNext->bbJumpDest;
10467
10468             /* Update the predecessor list for 'bNext->bbJumpDest' */
10469             fgReplacePred(bNext->bbJumpDest, bNext, block);
10470
10471             /* Update the predecessor list for 'bNext->bbNext' if it is different than 'bNext->bbJumpDest' */
10472             if (bNext->bbJumpKind == BBJ_COND && bNext->bbJumpDest != bNext->bbNext)
10473             {
10474                 fgReplacePred(bNext->bbNext, bNext, block);
10475             }
10476             break;
10477
10478         case BBJ_NONE:
10479             /* Update the predecessor list for 'bNext->bbNext' */
10480             fgReplacePred(bNext->bbNext, bNext, block);
10481             break;
10482
10483         case BBJ_EHFILTERRET:
10484             fgReplacePred(bNext->bbJumpDest, bNext, block);
10485             break;
10486
10487         case BBJ_EHFINALLYRET:
10488         {
10489             unsigned  hndIndex = block->getHndIndex();
10490             EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
10491
10492             if (ehDsc->HasFinallyHandler()) // No need to do this for fault handlers
10493             {
10494                 BasicBlock* begBlk;
10495                 BasicBlock* endBlk;
10496                 ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
10497
10498                 BasicBlock* finBeg = ehDsc->ebdHndBeg;
10499
10500                 for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
10501                 {
10502                     if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
10503                     {
10504                         continue;
10505                     }
10506
10507                     noway_assert(bcall->isBBCallAlwaysPair());
10508                     fgReplacePred(bcall->bbNext, bNext, block);
10509                 }
10510             }
10511         }
10512         break;
10513
10514         case BBJ_THROW:
10515         case BBJ_RETURN:
10516             /* no jumps or fall through blocks to set here */
10517             break;
10518
10519         case BBJ_SWITCH:
10520             block->bbJumpSwt = bNext->bbJumpSwt;
10521             // We are moving the switch jump from bNext to block.  Examine the jump targets
10522             // of the BBJ_SWITCH at bNext and replace the predecessor to 'bNext' with ones to 'block'
10523             fgChangeSwitchBlock(bNext, block);
10524             break;
10525
10526         default:
10527             noway_assert(!"Unexpected bbJumpKind");
10528             break;
10529     }
10530
10531     fgUpdateLoopsAfterCompacting(block, bNext);
10532
10533 #if DEBUG
10534     if (verbose && 0)
10535     {
10536         printf("\nAfter compacting:\n");
10537         fgDispBasicBlocks(false);
10538     }
10539 #endif
10540
10541 #if DEBUG
10542     if (JitConfig.JitSlowDebugChecksEnabled() != 0)
10543     {
10544         // Make sure that the predecessor lists are accurate
10545         fgDebugCheckBBlist();
10546     }
10547 #endif // DEBUG
10548 }
10549
10550 void Compiler::fgUpdateLoopsAfterCompacting(BasicBlock* block, BasicBlock* bNext)
10551 {
10552     /* Check if the removed block is not part the loop table */
10553     noway_assert(bNext);
10554
10555     for (unsigned loopNum = 0; loopNum < optLoopCount; loopNum++)
10556     {
10557         /* Some loops may have been already removed by
10558          * loop unrolling or conditional folding */
10559
10560         if (optLoopTable[loopNum].lpFlags & LPFLG_REMOVED)
10561         {
10562             continue;
10563         }
10564
10565         /* Check the loop head (i.e. the block preceding the loop) */
10566
10567         if (optLoopTable[loopNum].lpHead == bNext)
10568         {
10569             optLoopTable[loopNum].lpHead = block;
10570         }
10571
10572         /* Check the loop bottom */
10573
10574         if (optLoopTable[loopNum].lpBottom == bNext)
10575         {
10576             optLoopTable[loopNum].lpBottom = block;
10577         }
10578
10579         /* Check the loop exit */
10580
10581         if (optLoopTable[loopNum].lpExit == bNext)
10582         {
10583             noway_assert(optLoopTable[loopNum].lpExitCnt == 1);
10584             optLoopTable[loopNum].lpExit = block;
10585         }
10586
10587         /* Check the loop entry */
10588
10589         if (optLoopTable[loopNum].lpEntry == bNext)
10590         {
10591             optLoopTable[loopNum].lpEntry = block;
10592         }
10593     }
10594 }
10595
10596 /*****************************************************************************************************
10597  *
10598  *  Function called to remove a block when it is unreachable.
10599  *
10600  *  This function cannot remove the first block.
10601  */
10602
10603 void Compiler::fgUnreachableBlock(BasicBlock* block)
10604 {
10605     // genReturnBB should never be removed, as we might have special hookups there.
10606     // Therefore, we should never come here to remove the statements in the genReturnBB block.
10607     // For example, <BUGNUM> in VSW 364383, </BUGNUM>
10608     // the profiler hookup needs to have the "void GT_RETURN" statement
10609     // to properly set the info.compProfilerCallback flag.
10610     noway_assert(block != genReturnBB);
10611
10612     if (block->bbFlags & BBF_REMOVED)
10613     {
10614         return;
10615     }
10616
10617 /* Removing an unreachable block */
10618
10619 #ifdef DEBUG
10620     if (verbose)
10621     {
10622         printf("\nRemoving unreachable BB%02u\n", block->bbNum);
10623     }
10624 #endif // DEBUG
10625
10626     noway_assert(block->bbPrev != nullptr); // Can use this function to remove the first block
10627
10628 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10629     assert(!block->bbPrev->isBBCallAlwaysPair()); // can't remove the BBJ_ALWAYS of a BBJ_CALLFINALLY / BBJ_ALWAYS pair
10630 #endif                                            // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10631
10632     /* First walk the statement trees in this basic block and delete each stmt */
10633
10634     /* Make the block publicly available */
10635     compCurBB = block;
10636
10637     if (block->IsLIR())
10638     {
10639         LIR::Range& blockRange = LIR::AsRange(block);
10640         if (!blockRange.IsEmpty())
10641         {
10642             blockRange.Delete(this, block, blockRange.FirstNode(), blockRange.LastNode());
10643         }
10644     }
10645     else
10646     {
10647         // TODO-Cleanup: I'm not sure why this happens -- if the block is unreachable, why does it have phis?
10648         // Anyway, remove any phis.
10649
10650         GenTree* firstNonPhi = block->FirstNonPhiDef();
10651         if (block->bbTreeList != firstNonPhi)
10652         {
10653             if (firstNonPhi != nullptr)
10654             {
10655                 firstNonPhi->gtPrev = block->lastStmt();
10656             }
10657             block->bbTreeList = firstNonPhi;
10658         }
10659
10660         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
10661         {
10662             fgRemoveStmt(block, stmt);
10663         }
10664         noway_assert(block->bbTreeList == nullptr);
10665     }
10666
10667     /* Next update the loop table and bbWeights */
10668     optUpdateLoopsBeforeRemoveBlock(block);
10669
10670     /* Mark the block as removed */
10671     block->bbFlags |= BBF_REMOVED;
10672
10673     /* update bbRefs and bbPreds for the blocks reached by this block */
10674     fgRemoveBlockAsPred(block);
10675 }
10676
10677 /*****************************************************************************************************
10678  *
10679  *  Function called to remove or morph a jump when we jump to the same
10680  *  block when both the condition is true or false.
10681  */
10682 void Compiler::fgRemoveConditionalJump(BasicBlock* block)
10683 {
10684     noway_assert(block->bbJumpKind == BBJ_COND && block->bbJumpDest == block->bbNext);
10685     assert(compRationalIRForm == block->IsLIR());
10686
10687     flowList* flow = fgGetPredForBlock(block->bbNext, block);
10688     noway_assert(flow->flDupCount == 2);
10689
10690     // Change the BBJ_COND to BBJ_NONE, and adjust the refCount and dupCount.
10691     block->bbJumpKind = BBJ_NONE;
10692     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
10693     --block->bbNext->bbRefs;
10694     --flow->flDupCount;
10695
10696 #ifdef DEBUG
10697     block->bbJumpDest = nullptr;
10698     if (verbose)
10699     {
10700         printf("Block BB%02u becoming a BBJ_NONE to BB%02u (jump target is the same whether the condition is true or "
10701                "false)\n",
10702                block->bbNum, block->bbNext->bbNum);
10703     }
10704 #endif
10705
10706     /* Remove the block jump condition */
10707
10708     if (block->IsLIR())
10709     {
10710         LIR::Range& blockRange = LIR::AsRange(block);
10711
10712         GenTree* test = blockRange.LastNode();
10713         assert(test->OperIsConditionalJump());
10714
10715         bool               isClosed;
10716         unsigned           sideEffects;
10717         LIR::ReadOnlyRange testRange = blockRange.GetTreeRange(test, &isClosed, &sideEffects);
10718
10719         // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable
10720         //            diffs compared to the existing backend.
10721         if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0))
10722         {
10723             // If the jump and its operands form a contiguous, side-effect-free range,
10724             // remove them.
10725             blockRange.Delete(this, block, std::move(testRange));
10726         }
10727         else
10728         {
10729             // Otherwise, just remove the jump node itself.
10730             blockRange.Remove(test, true);
10731         }
10732     }
10733     else
10734     {
10735         GenTreeStmt* test = block->lastStmt();
10736         GenTree*     tree = test->gtStmtExpr;
10737
10738         noway_assert(tree->gtOper == GT_JTRUE);
10739
10740         GenTree* sideEffList = nullptr;
10741
10742         if (tree->gtFlags & GTF_SIDE_EFFECT)
10743         {
10744             gtExtractSideEffList(tree, &sideEffList);
10745
10746             if (sideEffList)
10747             {
10748                 noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
10749 #ifdef DEBUG
10750                 if (verbose)
10751                 {
10752                     printf("Extracted side effects list from condition...\n");
10753                     gtDispTree(sideEffList);
10754                     printf("\n");
10755                 }
10756 #endif
10757             }
10758         }
10759
10760         // Delete the cond test or replace it with the side effect tree
10761         if (sideEffList == nullptr)
10762         {
10763             fgRemoveStmt(block, test);
10764         }
10765         else
10766         {
10767             test->gtStmtExpr = sideEffList;
10768
10769             fgMorphBlockStmt(block, test DEBUGARG("fgRemoveConditionalJump"));
10770         }
10771     }
10772 }
10773
10774 /*****************************************************************************************************
10775  *
10776  *  Function to return the last basic block in the main part of the function. With funclets, it is
10777  *  the block immediately before the first funclet.
10778  *  An inclusive end of the main method.
10779  */
10780
10781 BasicBlock* Compiler::fgLastBBInMainFunction()
10782 {
10783 #if FEATURE_EH_FUNCLETS
10784
10785     if (fgFirstFuncletBB != nullptr)
10786     {
10787         return fgFirstFuncletBB->bbPrev;
10788     }
10789
10790 #endif // FEATURE_EH_FUNCLETS
10791
10792     assert(fgLastBB->bbNext == nullptr);
10793
10794     return fgLastBB;
10795 }
10796
10797 /*****************************************************************************************************
10798  *
10799  *  Function to return the first basic block after the main part of the function. With funclets, it is
10800  *  the block of the first funclet.  Otherwise it is NULL if there are no funclets (fgLastBB->bbNext).
10801  *  This is equivalent to fgLastBBInMainFunction()->bbNext
10802  *  An exclusive end of the main method.
10803  */
10804
10805 BasicBlock* Compiler::fgEndBBAfterMainFunction()
10806 {
10807 #if FEATURE_EH_FUNCLETS
10808
10809     if (fgFirstFuncletBB != nullptr)
10810     {
10811         return fgFirstFuncletBB;
10812     }
10813
10814 #endif // FEATURE_EH_FUNCLETS
10815
10816     assert(fgLastBB->bbNext == nullptr);
10817
10818     return nullptr;
10819 }
10820
10821 // Removes the block from the bbPrev/bbNext chain
10822 // Updates fgFirstBB and fgLastBB if necessary
10823 // Does not update fgFirstFuncletBB or fgFirstColdBlock (fgUnlinkRange does)
10824
10825 void Compiler::fgUnlinkBlock(BasicBlock* block)
10826 {
10827     if (block->bbPrev)
10828     {
10829         block->bbPrev->bbNext = block->bbNext;
10830         if (block->bbNext)
10831         {
10832             block->bbNext->bbPrev = block->bbPrev;
10833         }
10834         else
10835         {
10836             fgLastBB = block->bbPrev;
10837         }
10838     }
10839     else
10840     {
10841         assert(block == fgFirstBB);
10842         assert(block != fgLastBB);
10843         assert((fgFirstBBScratch == nullptr) || (fgFirstBBScratch == fgFirstBB));
10844
10845         fgFirstBB         = block->bbNext;
10846         fgFirstBB->bbPrev = nullptr;
10847
10848         if (fgFirstBBScratch != nullptr)
10849         {
10850 #ifdef DEBUG
10851             // We had created an initial scratch BB, but now we're deleting it.
10852             if (verbose)
10853             {
10854                 printf("Unlinking scratch BB%02u\n", block->bbNum);
10855             }
10856 #endif // DEBUG
10857             fgFirstBBScratch = nullptr;
10858         }
10859     }
10860 }
10861
10862 /*****************************************************************************************************
10863  *
10864  *  Function called to unlink basic block range [bBeg .. bEnd] from the basic block list.
10865  *
10866  *  'bBeg' can't be the first block.
10867  */
10868
10869 void Compiler::fgUnlinkRange(BasicBlock* bBeg, BasicBlock* bEnd)
10870 {
10871     assert(bBeg != nullptr);
10872     assert(bEnd != nullptr);
10873
10874     BasicBlock* bPrev = bBeg->bbPrev;
10875     assert(bPrev != nullptr); // Can't unlink a range starting with the first block
10876
10877     bPrev->setNext(bEnd->bbNext);
10878
10879     /* If we removed the last block in the method then update fgLastBB */
10880     if (fgLastBB == bEnd)
10881     {
10882         fgLastBB = bPrev;
10883         noway_assert(fgLastBB->bbNext == nullptr);
10884     }
10885
10886     // If bEnd was the first Cold basic block update fgFirstColdBlock
10887     if (fgFirstColdBlock == bEnd)
10888     {
10889         fgFirstColdBlock = bPrev->bbNext;
10890     }
10891
10892 #if FEATURE_EH_FUNCLETS
10893 #ifdef DEBUG
10894     // You can't unlink a range that includes the first funclet block. A range certainly
10895     // can't cross the non-funclet/funclet region. And you can't unlink the first block
10896     // of the first funclet with this, either. (If that's necessary, it could be allowed
10897     // by updating fgFirstFuncletBB to bEnd->bbNext.)
10898     for (BasicBlock* tempBB = bBeg; tempBB != bEnd->bbNext; tempBB = tempBB->bbNext)
10899     {
10900         assert(tempBB != fgFirstFuncletBB);
10901     }
10902 #endif // DEBUG
10903 #endif // FEATURE_EH_FUNCLETS
10904 }
10905
10906 /*****************************************************************************************************
10907  *
10908  *  Function called to remove a basic block
10909  */
10910
10911 void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable)
10912 {
10913     BasicBlock* bPrev = block->bbPrev;
10914
10915     /* The block has to be either unreachable or empty */
10916
10917     PREFIX_ASSUME(block != nullptr);
10918
10919     JITDUMP("fgRemoveBlock BB%02u\n", block->bbNum);
10920
10921     // If we've cached any mappings from switch blocks to SwitchDesc's (which contain only the
10922     // *unique* successors of the switch block), invalidate that cache, since an entry in one of
10923     // the SwitchDescs might be removed.
10924     InvalidateUniqueSwitchSuccMap();
10925
10926     noway_assert((block == fgFirstBB) || (bPrev && (bPrev->bbNext == block)));
10927     noway_assert(!(block->bbFlags & BBF_DONT_REMOVE));
10928
10929     // Should never remove a genReturnBB, as we might have special hookups there.
10930     noway_assert(block != genReturnBB);
10931
10932 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10933     // Don't remove a finally target
10934     assert(!(block->bbFlags & BBF_FINALLY_TARGET));
10935 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10936
10937     if (unreachable)
10938     {
10939         PREFIX_ASSUME(bPrev != nullptr);
10940
10941         fgUnreachableBlock(block);
10942
10943         /* If this is the last basic block update fgLastBB */
10944         if (block == fgLastBB)
10945         {
10946             fgLastBB = bPrev;
10947         }
10948
10949 #if FEATURE_EH_FUNCLETS
10950         // If block was the fgFirstFuncletBB then set fgFirstFuncletBB to block->bbNext
10951         if (block == fgFirstFuncletBB)
10952         {
10953             fgFirstFuncletBB = block->bbNext;
10954         }
10955 #endif // FEATURE_EH_FUNCLETS
10956
10957         if (bPrev->bbJumpKind == BBJ_CALLFINALLY)
10958         {
10959             // bPrev CALL becomes RETLESS as the BBJ_ALWAYS block is unreachable
10960             bPrev->bbFlags |= BBF_RETLESS_CALL;
10961
10962 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10963             NO_WAY("No retless call finally blocks; need unwind target instead");
10964 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10965         }
10966         else if (bPrev->bbJumpKind == BBJ_ALWAYS && bPrev->bbJumpDest == block->bbNext &&
10967                  !(bPrev->bbFlags & BBF_KEEP_BBJ_ALWAYS) && (block != fgFirstColdBlock) &&
10968                  (block->bbNext != fgFirstColdBlock))
10969         {
10970             // previous block is a BBJ_ALWAYS to the next block: change to BBJ_NONE.
10971             // Note that we don't do it if bPrev follows a BBJ_CALLFINALLY block (BBF_KEEP_BBJ_ALWAYS),
10972             // because that would violate our invariant that BBJ_CALLFINALLY blocks are followed by
10973             // BBJ_ALWAYS blocks.
10974             bPrev->bbJumpKind = BBJ_NONE;
10975             bPrev->bbFlags &= ~BBF_NEEDS_GCPOLL;
10976         }
10977
10978         // If this is the first Cold basic block update fgFirstColdBlock
10979         if (block == fgFirstColdBlock)
10980         {
10981             fgFirstColdBlock = block->bbNext;
10982         }
10983
10984         /* Unlink this block from the bbNext chain */
10985         fgUnlinkBlock(block);
10986
10987         /* At this point the bbPreds and bbRefs had better be zero */
10988         noway_assert((block->bbRefs == 0) && (block->bbPreds == nullptr));
10989
10990         /*  A BBJ_CALLFINALLY is usually paired with a BBJ_ALWAYS.
10991          *  If we delete such a BBJ_CALLFINALLY we also delete the BBJ_ALWAYS
10992          */
10993         if (block->isBBCallAlwaysPair())
10994         {
10995             BasicBlock* leaveBlk = block->bbNext;
10996             noway_assert(leaveBlk->bbJumpKind == BBJ_ALWAYS);
10997
10998             leaveBlk->bbFlags &= ~BBF_DONT_REMOVE;
10999             leaveBlk->bbRefs  = 0;
11000             leaveBlk->bbPreds = nullptr;
11001
11002             fgRemoveBlock(leaveBlk, true);
11003
11004 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
11005             fgClearFinallyTargetBit(leaveBlk->bbJumpDest);
11006 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
11007         }
11008         else if (block->bbJumpKind == BBJ_RETURN)
11009         {
11010             fgRemoveReturnBlock(block);
11011         }
11012     }
11013     else // block is empty
11014     {
11015         noway_assert(block->isEmpty());
11016
11017         /* The block cannot follow a non-retless BBJ_CALLFINALLY (because we don't know who may jump to it) */
11018         noway_assert((bPrev == nullptr) || !bPrev->isBBCallAlwaysPair());
11019
11020         /* This cannot be the last basic block */
11021         noway_assert(block != fgLastBB);
11022
11023 #ifdef DEBUG
11024         if (verbose)
11025         {
11026             printf("Removing empty BB%02u\n", block->bbNum);
11027         }
11028 #endif // DEBUG
11029
11030 #ifdef DEBUG
11031         /* Some extra checks for the empty case */
11032
11033         switch (block->bbJumpKind)
11034         {
11035             case BBJ_NONE:
11036                 break;
11037
11038             case BBJ_ALWAYS:
11039                 /* Do not remove a block that jumps to itself - used for while (true){} */
11040                 noway_assert(block->bbJumpDest != block);
11041
11042                 /* Empty GOTO can be removed iff bPrev is BBJ_NONE */
11043                 noway_assert(bPrev && bPrev->bbJumpKind == BBJ_NONE);
11044                 break;
11045
11046             default:
11047                 noway_assert(!"Empty block of this type cannot be removed!");
11048                 break;
11049         }
11050 #endif // DEBUG
11051
11052         noway_assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS);
11053
11054         /* Who is the "real" successor of this block? */
11055
11056         BasicBlock* succBlock;
11057
11058         if (block->bbJumpKind == BBJ_ALWAYS)
11059         {
11060             succBlock = block->bbJumpDest;
11061         }
11062         else
11063         {
11064             succBlock = block->bbNext;
11065         }
11066
11067         bool skipUnmarkLoop = false;
11068
11069         // If block is the backedge for a loop and succBlock precedes block
11070         // then the succBlock becomes the new LOOP HEAD
11071         // NOTE: there's an assumption here that the blocks are numbered in increasing bbNext order.
11072         // NOTE 2: if fgDomsComputed is false, then we can't check reachability. However, if this is
11073         // the case, then the loop structures probably are also invalid, and shouldn't be used. This
11074         // can be the case late in compilation (such as Lower), where remnants of earlier created
11075         // structures exist, but haven't been maintained.
11076         if (block->isLoopHead() && (succBlock->bbNum <= block->bbNum))
11077         {
11078             succBlock->bbFlags |= BBF_LOOP_HEAD;
11079             if (fgDomsComputed && fgReachable(succBlock, block))
11080             {
11081                 /* Mark all the reachable blocks between 'succBlock' and 'block', excluding 'block' */
11082                 optMarkLoopBlocks(succBlock, block, true);
11083             }
11084         }
11085         else if (succBlock->isLoopHead() && bPrev && (succBlock->bbNum <= bPrev->bbNum))
11086         {
11087             skipUnmarkLoop = true;
11088         }
11089
11090         noway_assert(succBlock);
11091
11092         // If this is the first Cold basic block update fgFirstColdBlock
11093         if (block == fgFirstColdBlock)
11094         {
11095             fgFirstColdBlock = block->bbNext;
11096         }
11097
11098 #if FEATURE_EH_FUNCLETS
11099         // Update fgFirstFuncletBB if necessary
11100         if (block == fgFirstFuncletBB)
11101         {
11102             fgFirstFuncletBB = block->bbNext;
11103         }
11104 #endif // FEATURE_EH_FUNCLETS
11105
11106         /* First update the loop table and bbWeights */
11107         optUpdateLoopsBeforeRemoveBlock(block, skipUnmarkLoop);
11108
11109         /* Remove the block */
11110
11111         if (bPrev == nullptr)
11112         {
11113             /* special case if this is the first BB */
11114
11115             noway_assert(block == fgFirstBB);
11116
11117             /* Must be a fall through to next block */
11118
11119             noway_assert(block->bbJumpKind == BBJ_NONE);
11120
11121             /* old block no longer gets the extra ref count for being the first block */
11122             block->bbRefs--;
11123             succBlock->bbRefs++;
11124
11125             /* Set the new firstBB */
11126             fgUnlinkBlock(block);
11127
11128             /* Always treat the initial block as a jump target */
11129             fgFirstBB->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
11130         }
11131         else
11132         {
11133             fgUnlinkBlock(block);
11134         }
11135
11136         /* mark the block as removed and set the change flag */
11137
11138         block->bbFlags |= BBF_REMOVED;
11139
11140         /* Update bbRefs and bbPreds.
11141          * All blocks jumping to 'block' now jump to 'succBlock'.
11142          * First, remove 'block' from the predecessor list of succBlock.
11143          */
11144
11145         fgRemoveRefPred(succBlock, block);
11146
11147         for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
11148         {
11149             BasicBlock* predBlock = pred->flBlock;
11150
11151             /* Are we changing a loop backedge into a forward jump? */
11152
11153             if (block->isLoopHead() && (predBlock->bbNum >= block->bbNum) && (predBlock->bbNum <= succBlock->bbNum))
11154             {
11155                 /* First update the loop table and bbWeights */
11156                 optUpdateLoopsBeforeRemoveBlock(predBlock);
11157             }
11158
11159             /* If predBlock is a new predecessor, then add it to succBlock's
11160                predecessor's list. */
11161             if (predBlock->bbJumpKind != BBJ_SWITCH)
11162             {
11163                 // Even if the pred is not a switch, we could have a conditional branch
11164                 // to the fallthrough, so duplicate there could be preds
11165                 for (unsigned i = 0; i < pred->flDupCount; i++)
11166                 {
11167                     fgAddRefPred(succBlock, predBlock);
11168                 }
11169             }
11170
11171             /* change all jumps to the removed block */
11172             switch (predBlock->bbJumpKind)
11173             {
11174                 default:
11175                     noway_assert(!"Unexpected bbJumpKind in fgRemoveBlock()");
11176                     break;
11177
11178                 case BBJ_NONE:
11179                     noway_assert(predBlock == bPrev);
11180                     PREFIX_ASSUME(bPrev != nullptr);
11181
11182                     /* In the case of BBJ_ALWAYS we have to change the type of its predecessor */
11183                     if (block->bbJumpKind == BBJ_ALWAYS)
11184                     {
11185                         /* bPrev now becomes a BBJ_ALWAYS */
11186                         bPrev->bbJumpKind = BBJ_ALWAYS;
11187                         bPrev->bbJumpDest = succBlock;
11188                     }
11189                     break;
11190
11191                 case BBJ_COND:
11192                     /* The links for the direct predecessor case have already been updated above */
11193                     if (predBlock->bbJumpDest != block)
11194                     {
11195                         succBlock->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
11196                         break;
11197                     }
11198
11199                     /* Check if both side of the BBJ_COND now jump to the same block */
11200                     if (predBlock->bbNext == succBlock)
11201                     {
11202                         // Make sure we are replacing "block" with "succBlock" in predBlock->bbJumpDest.
11203                         noway_assert(predBlock->bbJumpDest == block);
11204                         predBlock->bbJumpDest = succBlock;
11205                         fgRemoveConditionalJump(predBlock);
11206                         break;
11207                     }
11208
11209                     /* Fall through for the jump case */
11210                     __fallthrough;
11211
11212                 case BBJ_CALLFINALLY:
11213                 case BBJ_ALWAYS:
11214                 case BBJ_EHCATCHRET:
11215                     noway_assert(predBlock->bbJumpDest == block);
11216                     predBlock->bbJumpDest = succBlock;
11217                     succBlock->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
11218                     break;
11219
11220                 case BBJ_SWITCH:
11221                     // Change any jumps from 'predBlock' (a BBJ_SWITCH) to 'block' to jump to 'succBlock'
11222                     //
11223                     // For the jump targets of 'predBlock' (a BBJ_SWITCH) that jump to 'block'
11224                     // remove the old predecessor at 'block' from 'predBlock'  and
11225                     // add the new predecessor at 'succBlock' from 'predBlock'
11226                     //
11227                     fgReplaceSwitchJumpTarget(predBlock, succBlock, block);
11228                     break;
11229             }
11230         }
11231     }
11232
11233     if (bPrev != nullptr)
11234     {
11235         switch (bPrev->bbJumpKind)
11236         {
11237             case BBJ_CALLFINALLY:
11238                 // If prev is a BBJ_CALLFINALLY it better be marked as RETLESS
11239                 noway_assert(bPrev->bbFlags & BBF_RETLESS_CALL);
11240                 break;
11241
11242             case BBJ_ALWAYS:
11243                 // Check for branch to next block. Just make sure the BBJ_ALWAYS block is not
11244                 // part of a BBJ_CALLFINALLY/BBJ_ALWAYS pair. We do this here and don't rely on fgUpdateFlowGraph
11245                 // because we can be called by ComputeDominators and it expects it to remove this jump to
11246                 // the next block. This is the safest fix. We should remove all this BBJ_CALLFINALLY/BBJ_ALWAYS
11247                 // pairing.
11248
11249                 if ((bPrev->bbJumpDest == bPrev->bbNext) &&
11250                     !fgInDifferentRegions(bPrev, bPrev->bbJumpDest)) // We don't remove a branch from Hot -> Cold
11251                 {
11252                     if ((bPrev == fgFirstBB) || !bPrev->bbPrev->isBBCallAlwaysPair())
11253                     {
11254                         // It's safe to change the jump type
11255                         bPrev->bbJumpKind = BBJ_NONE;
11256                         bPrev->bbFlags &= ~BBF_NEEDS_GCPOLL;
11257                     }
11258                 }
11259                 break;
11260
11261             case BBJ_COND:
11262                 /* Check for branch to next block */
11263                 if (bPrev->bbJumpDest == bPrev->bbNext)
11264                 {
11265                     fgRemoveConditionalJump(bPrev);
11266                 }
11267                 break;
11268
11269             default:
11270                 break;
11271         }
11272
11273         ehUpdateForDeletedBlock(block);
11274     }
11275 }
11276
11277 /*****************************************************************************
11278  *
11279  *  Function called to connect to block that previously had a fall through
11280  */
11281
11282 BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst)
11283 {
11284     BasicBlock* jmpBlk = nullptr;
11285
11286     /* If bSrc is non-NULL */
11287
11288     if (bSrc != nullptr)
11289     {
11290         /* If bSrc falls through to a block that is not bDst, we will insert a jump to bDst */
11291
11292         if (bSrc->bbFallsThrough() && (bSrc->bbNext != bDst))
11293         {
11294             switch (bSrc->bbJumpKind)
11295             {
11296
11297                 case BBJ_NONE:
11298                     bSrc->bbJumpKind = BBJ_ALWAYS;
11299                     bSrc->bbJumpDest = bDst;
11300                     bSrc->bbJumpDest->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
11301 #ifdef DEBUG
11302                     if (verbose)
11303                     {
11304                         printf("Block BB%02u ended with a BBJ_NONE, Changed to an unconditional jump to BB%02u\n",
11305                                bSrc->bbNum, bSrc->bbJumpDest->bbNum);
11306                     }
11307 #endif
11308                     break;
11309
11310                 case BBJ_CALLFINALLY:
11311                 case BBJ_COND:
11312
11313                     // Add a new block after bSrc which jumps to 'bDst'
11314                     jmpBlk = fgNewBBafter(BBJ_ALWAYS, bSrc, true);
11315
11316                     if (fgComputePredsDone)
11317                     {
11318                         fgAddRefPred(jmpBlk, bSrc, fgGetPredForBlock(bDst, bSrc));
11319                     }
11320
11321                     // When adding a new jmpBlk we will set the bbWeight and bbFlags
11322                     //
11323                     if (fgHaveValidEdgeWeights)
11324                     {
11325                         noway_assert(fgComputePredsDone);
11326
11327                         flowList* newEdge = fgGetPredForBlock(jmpBlk, bSrc);
11328
11329                         jmpBlk->bbWeight = (newEdge->flEdgeWeightMin + newEdge->flEdgeWeightMax) / 2;
11330                         if (bSrc->bbWeight == 0)
11331                         {
11332                             jmpBlk->bbWeight = 0;
11333                         }
11334
11335                         if (jmpBlk->bbWeight == 0)
11336                         {
11337                             jmpBlk->bbFlags |= BBF_RUN_RARELY;
11338                         }
11339
11340                         BasicBlock::weight_t weightDiff = (newEdge->flEdgeWeightMax - newEdge->flEdgeWeightMin);
11341                         BasicBlock::weight_t slop       = BasicBlock::GetSlopFraction(bSrc, bDst);
11342
11343                         //
11344                         // If the [min/max] values for our edge weight is within the slop factor
11345                         //  then we will set the BBF_PROF_WEIGHT flag for the block
11346                         //
11347                         if (weightDiff <= slop)
11348                         {
11349                             jmpBlk->bbFlags |= BBF_PROF_WEIGHT;
11350                         }
11351                     }
11352                     else
11353                     {
11354                         // We set the bbWeight to the smaller of bSrc->bbWeight or bDst->bbWeight
11355                         if (bSrc->bbWeight < bDst->bbWeight)
11356                         {
11357                             jmpBlk->bbWeight = bSrc->bbWeight;
11358                             jmpBlk->bbFlags |= (bSrc->bbFlags & BBF_RUN_RARELY);
11359                         }
11360                         else
11361                         {
11362                             jmpBlk->bbWeight = bDst->bbWeight;
11363                             jmpBlk->bbFlags |= (bDst->bbFlags & BBF_RUN_RARELY);
11364                         }
11365                     }
11366
11367                     jmpBlk->bbJumpDest = bDst;
11368                     jmpBlk->bbJumpDest->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
11369
11370                     if (fgComputePredsDone)
11371                     {
11372                         fgReplacePred(bDst, bSrc, jmpBlk);
11373                     }
11374                     else
11375                     {
11376                         jmpBlk->bbFlags |= BBF_IMPORTED;
11377                     }
11378
11379 #ifdef DEBUG
11380                     if (verbose)
11381                     {
11382                         printf("Added an unconditional jump to BB%02u after block BB%02u\n", jmpBlk->bbJumpDest->bbNum,
11383                                bSrc->bbNum);
11384                     }
11385 #endif // DEBUG
11386                     break;
11387
11388                 default:
11389                     noway_assert(!"Unexpected bbJumpKind");
11390                     break;
11391             }
11392         }
11393         else
11394         {
11395             // If bSrc is an unconditional branch to the next block
11396             // then change it to a BBJ_NONE block
11397             //
11398             if ((bSrc->bbJumpKind == BBJ_ALWAYS) && !(bSrc->bbFlags & BBF_KEEP_BBJ_ALWAYS) &&
11399                 (bSrc->bbJumpDest == bSrc->bbNext))
11400             {
11401                 bSrc->bbJumpKind = BBJ_NONE;
11402                 bSrc->bbFlags &= ~BBF_NEEDS_GCPOLL;
11403 #ifdef DEBUG
11404                 if (verbose)
11405                 {
11406                     printf("Changed an unconditional jump from BB%02u to the next block BB%02u into a BBJ_NONE block\n",
11407                            bSrc->bbNum, bSrc->bbNext->bbNum);
11408                 }
11409 #endif // DEBUG
11410             }
11411         }
11412     }
11413
11414     return jmpBlk;
11415 }
11416
11417 /*****************************************************************************
11418  Walk the flow graph, reassign block numbers to keep them in ascending order.
11419  Returns 'true' if any renumbering was actually done, OR if we change the
11420  maximum number of assigned basic blocks (this can happen if we do inlining,
11421  create a new, high-numbered block, then that block goes away. We go to
11422  renumber the blocks, none of them actually change number, but we shrink the
11423  maximum assigned block number. This affects the block set epoch).
11424 */
11425
11426 bool Compiler::fgRenumberBlocks()
11427 {
11428     // If we renumber the blocks the dominator information will be out-of-date
11429     if (fgDomsComputed)
11430     {
11431         noway_assert(!"Can't call Compiler::fgRenumberBlocks() when fgDomsComputed==true");
11432     }
11433
11434 #ifdef DEBUG
11435     if (verbose)
11436     {
11437         printf("\n*************** Before renumbering the basic blocks\n");
11438         fgDispBasicBlocks();
11439         fgDispHandlerTab();
11440     }
11441 #endif // DEBUG
11442
11443     bool        renumbered  = false;
11444     bool        newMaxBBNum = false;
11445     BasicBlock* block;
11446
11447     unsigned numStart = 1 + (compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : 0);
11448     unsigned num;
11449
11450     for (block = fgFirstBB, num = numStart; block != nullptr; block = block->bbNext, num++)
11451     {
11452         noway_assert((block->bbFlags & BBF_REMOVED) == 0);
11453
11454         if (block->bbNum != num)
11455         {
11456             renumbered = true;
11457 #ifdef DEBUG
11458             if (verbose)
11459             {
11460                 printf("Renumber BB%02u to BB%02u\n", block->bbNum, num);
11461             }
11462 #endif // DEBUG
11463             block->bbNum = num;
11464         }
11465
11466         if (block->bbNext == nullptr)
11467         {
11468             fgLastBB  = block;
11469             fgBBcount = num - numStart + 1;
11470             if (compIsForInlining())
11471             {
11472                 if (impInlineInfo->InlinerCompiler->fgBBNumMax != num)
11473                 {
11474                     impInlineInfo->InlinerCompiler->fgBBNumMax = num;
11475                     newMaxBBNum                                = true;
11476                 }
11477             }
11478             else
11479             {
11480                 if (fgBBNumMax != num)
11481                 {
11482                     fgBBNumMax  = num;
11483                     newMaxBBNum = true;
11484                 }
11485             }
11486         }
11487     }
11488
11489 #ifdef DEBUG
11490     if (verbose)
11491     {
11492         printf("\n*************** After renumbering the basic blocks\n");
11493         if (renumbered)
11494         {
11495             fgDispBasicBlocks();
11496             fgDispHandlerTab();
11497         }
11498         else
11499         {
11500             printf("=============== No blocks renumbered!\n");
11501         }
11502     }
11503 #endif // DEBUG
11504
11505     // Now update the BlockSet epoch, which depends on the block numbers.
11506     // If any blocks have been renumbered then create a new BlockSet epoch.
11507     // Even if we have not renumbered any blocks, we might still need to force
11508     // a new BlockSet epoch, for one of several reasons. If there are any new
11509     // blocks with higher numbers than the former maximum numbered block, then we
11510     // need a new epoch with a new size matching the new largest numbered block.
11511     // Also, if the number of blocks is different from the last time we set the
11512     // BlockSet epoch, then we need a new epoch. This wouldn't happen if we
11513     // renumbered blocks after every block addition/deletion, but it might be
11514     // the case that we can change the number of blocks, then set the BlockSet
11515     // epoch without renumbering, then change the number of blocks again, then
11516     // renumber.
11517     if (renumbered || newMaxBBNum)
11518     {
11519         NewBasicBlockEpoch();
11520
11521         // The key in the unique switch successor map is dependent on the block number, so invalidate that cache.
11522         InvalidateUniqueSwitchSuccMap();
11523     }
11524     else
11525     {
11526         EnsureBasicBlockEpoch();
11527     }
11528
11529     // Tell our caller if any blocks actually were renumbered.
11530     return renumbered || newMaxBBNum;
11531 }
11532
11533 /*****************************************************************************
11534  *
11535  *  Is the BasicBlock bJump a forward branch?
11536  *   Optionally bSrc can be supplied to indicate that
11537  *   bJump must be forward with respect to bSrc
11538  */
11539 bool Compiler::fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc /* = NULL */)
11540 {
11541     bool result = false;
11542
11543     if ((bJump->bbJumpKind == BBJ_COND) || (bJump->bbJumpKind == BBJ_ALWAYS))
11544     {
11545         BasicBlock* bDest = bJump->bbJumpDest;
11546         BasicBlock* bTemp = (bSrc == nullptr) ? bJump : bSrc;
11547
11548         while (true)
11549         {
11550             bTemp = bTemp->bbNext;
11551
11552             if (bTemp == nullptr)
11553             {
11554                 break;
11555             }
11556
11557             if (bTemp == bDest)
11558             {
11559                 result = true;
11560                 break;
11561             }
11562         }
11563     }
11564
11565     return result;
11566 }
11567
11568 /*****************************************************************************
11569  *
11570  *  Function called to expand the set of rarely run blocks
11571  */
11572
11573 bool Compiler::fgExpandRarelyRunBlocks()
11574 {
11575     bool result = false;
11576
11577 #ifdef DEBUG
11578     if (verbose)
11579     {
11580         printf("\n*************** In fgExpandRarelyRunBlocks()\n");
11581     }
11582
11583     const char* reason = nullptr;
11584 #endif
11585
11586     // We expand the number of rarely run blocks by observing
11587     // that a block that falls into or jumps to a rarely run block,
11588     // must itself be rarely run and when we have a conditional
11589     // jump in which both branches go to rarely run blocks then
11590     // the block must itself be rarely run
11591
11592     BasicBlock* block;
11593     BasicBlock* bPrev;
11594
11595     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
11596     {
11597         if (bPrev->isRunRarely())
11598         {
11599             continue;
11600         }
11601
11602         /* bPrev is known to be a normal block here */
11603         switch (bPrev->bbJumpKind)
11604         {
11605             case BBJ_ALWAYS:
11606
11607                 /* Is the jump target rarely run? */
11608                 if (bPrev->bbJumpDest->isRunRarely())
11609                 {
11610                     INDEBUG(reason = "Unconditional jump to a rarely run block";)
11611                     goto NEW_RARELY_RUN;
11612                 }
11613                 break;
11614
11615             case BBJ_CALLFINALLY:
11616
11617                 // Check for a BBJ_CALLFINALLY followed by a rarely run paired BBJ_ALWAYS
11618                 //
11619                 if (bPrev->isBBCallAlwaysPair())
11620                 {
11621                     /* Is the next block rarely run? */
11622                     if (block->isRunRarely())
11623                     {
11624                         INDEBUG(reason = "Call of finally followed by a rarely run block";)
11625                         goto NEW_RARELY_RUN;
11626                     }
11627                 }
11628                 break;
11629
11630             case BBJ_NONE:
11631
11632                 /* is fall through target rarely run? */
11633                 if (block->isRunRarely())
11634                 {
11635                     INDEBUG(reason = "Falling into a rarely run block";)
11636                     goto NEW_RARELY_RUN;
11637                 }
11638                 break;
11639
11640             case BBJ_COND:
11641
11642                 if (!block->isRunRarely())
11643                 {
11644                     continue;
11645                 }
11646
11647                 /* If both targets of the BBJ_COND are run rarely then don't reorder */
11648                 if (bPrev->bbJumpDest->isRunRarely())
11649                 {
11650                     /* bPrev should also be marked as run rarely */
11651                     if (!bPrev->isRunRarely())
11652                     {
11653                         INDEBUG(reason = "Both sides of a conditional jump are rarely run";)
11654
11655                     NEW_RARELY_RUN:
11656                         /* If the weight of the block was obtained from a profile run,
11657                            than it's more accurate than our static analysis */
11658                         if (bPrev->hasProfileWeight())
11659                         {
11660                             continue;
11661                         }
11662                         result = true;
11663
11664 #ifdef DEBUG
11665                         assert(reason != nullptr);
11666                         if (verbose)
11667                         {
11668                             printf("%s, marking BB%02u as rarely run\n", reason, bPrev->bbNum);
11669                         }
11670 #endif // DEBUG
11671
11672                         /* Must not have previously been marked */
11673                         noway_assert(!bPrev->isRunRarely());
11674
11675                         /* Mark bPrev as a new rarely run block */
11676                         bPrev->bbSetRunRarely();
11677
11678                         BasicBlock* bPrevPrev = nullptr;
11679                         BasicBlock* tmpbb;
11680
11681                         if ((bPrev->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)
11682                         {
11683                             // If we've got a BBJ_CALLFINALLY/BBJ_ALWAYS pair, treat the BBJ_CALLFINALLY as an
11684                             // additional predecessor for the BBJ_ALWAYS block
11685                             tmpbb = bPrev->bbPrev;
11686                             noway_assert(tmpbb != nullptr);
11687 #if FEATURE_EH_FUNCLETS
11688                             noway_assert(tmpbb->isBBCallAlwaysPair());
11689                             bPrevPrev = tmpbb;
11690 #else
11691                             if (tmpbb->bbJumpKind == BBJ_CALLFINALLY)
11692                             {
11693                                 bPrevPrev = tmpbb;
11694                             }
11695 #endif
11696                         }
11697
11698                         /* Now go back to it's earliest predecessor to see */
11699                         /* if it too should now be marked as rarely run    */
11700                         flowList* pred = bPrev->bbPreds;
11701
11702                         if ((pred != nullptr) || (bPrevPrev != nullptr))
11703                         {
11704                             // bPrevPrev will be set to the lexically
11705                             // earliest predecessor of bPrev.
11706
11707                             while (pred != nullptr)
11708                             {
11709                                 if (bPrevPrev == nullptr)
11710                                 {
11711                                     // Initially we select the first block in the bbPreds list
11712                                     bPrevPrev = pred->flBlock;
11713                                     continue;
11714                                 }
11715
11716                                 // Walk the flow graph lexically forward from pred->flBlock
11717                                 // if we find (block == bPrevPrev) then
11718                                 // pred->flBlock is an earlier predecessor.
11719                                 for (tmpbb = pred->flBlock; tmpbb != nullptr; tmpbb = tmpbb->bbNext)
11720                                 {
11721                                     if (tmpbb == bPrevPrev)
11722                                     {
11723                                         /* We found an ealier predecessor */
11724                                         bPrevPrev = pred->flBlock;
11725                                         break;
11726                                     }
11727                                     else if (tmpbb == bPrev)
11728                                     {
11729                                         // We have reached bPrev so stop walking
11730                                         // as this cannot be an earlier predecessor
11731                                         break;
11732                                     }
11733                                 }
11734
11735                                 // Onto the next predecessor
11736                                 pred = pred->flNext;
11737                             }
11738
11739                             // Walk the flow graph forward from bPrevPrev
11740                             // if we don't find (tmpbb == bPrev) then our candidate
11741                             // bPrevPrev is lexically after bPrev and we do not
11742                             // want to select it as our new block
11743
11744                             for (tmpbb = bPrevPrev; tmpbb != nullptr; tmpbb = tmpbb->bbNext)
11745                             {
11746                                 if (tmpbb == bPrev)
11747                                 {
11748                                     // Set up block back to the lexically
11749                                     // earliest predecessor of pPrev
11750
11751                                     block = bPrevPrev;
11752                                 }
11753                             }
11754                         }
11755                     }
11756                     break;
11757
11758                     default:
11759                         break;
11760                 }
11761         }
11762     }
11763
11764     // Now iterate over every block to see if we can prove that a block is rarely run
11765     // (i.e. when all predecessors to the block are rarely run)
11766     //
11767     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
11768     {
11769         // If block is not run rarely, then check to make sure that it has
11770         // at least one non-rarely run block.
11771
11772         if (!block->isRunRarely())
11773         {
11774             bool rare = true;
11775
11776             /* Make sure that block has at least one normal predecessor */
11777             for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
11778             {
11779                 /* Find the fall through predecessor, if any */
11780                 if (!pred->flBlock->isRunRarely())
11781                 {
11782                     rare = false;
11783                     break;
11784                 }
11785             }
11786
11787             if (rare)
11788             {
11789                 // If 'block' is the start of a handler or filter then we cannot make it
11790                 // rarely run because we may have an exceptional edge that
11791                 // branches here.
11792                 //
11793                 if (bbIsHandlerBeg(block))
11794                 {
11795                     rare = false;
11796                 }
11797             }
11798
11799             if (rare)
11800             {
11801                 block->bbSetRunRarely();
11802                 result = true;
11803
11804 #ifdef DEBUG
11805                 if (verbose)
11806                 {
11807                     printf("All branches to BB%02u are from rarely run blocks, marking as rarely run\n", block->bbNum);
11808                 }
11809 #endif // DEBUG
11810
11811                 // When marking a BBJ_CALLFINALLY as rarely run we also mark
11812                 // the BBJ_ALWAYS that comes after it as rarely run
11813                 //
11814                 if (block->isBBCallAlwaysPair())
11815                 {
11816                     BasicBlock* bNext = block->bbNext;
11817                     PREFIX_ASSUME(bNext != nullptr);
11818                     bNext->bbSetRunRarely();
11819 #ifdef DEBUG
11820                     if (verbose)
11821                     {
11822                         printf("Also marking the BBJ_ALWAYS at BB%02u as rarely run\n", bNext->bbNum);
11823                     }
11824 #endif // DEBUG
11825                 }
11826             }
11827         }
11828
11829         /* COMPACT blocks if possible */
11830         if (bPrev->bbJumpKind == BBJ_NONE)
11831         {
11832             if (fgCanCompactBlocks(bPrev, block))
11833             {
11834                 fgCompactBlocks(bPrev, block);
11835
11836                 block = bPrev;
11837                 continue;
11838             }
11839         }
11840         //
11841         // if bPrev->bbWeight is not based upon profile data we can adjust
11842         // the weights of bPrev and block
11843         //
11844         else if (bPrev->isBBCallAlwaysPair() &&          // we must have a BBJ_CALLFINALLY and BBK_ALWAYS pair
11845                  (bPrev->bbWeight != block->bbWeight) && // the weights are currently different
11846                  !bPrev->hasProfileWeight())             // and the BBJ_CALLFINALLY block is not using profiled
11847                                                          // weights
11848         {
11849             if (block->isRunRarely())
11850             {
11851                 bPrev->bbWeight =
11852                     block->bbWeight; // the BBJ_CALLFINALLY block now has the same weight as the BBJ_ALWAYS block
11853                 bPrev->bbFlags |= BBF_RUN_RARELY; // and is now rarely run
11854 #ifdef DEBUG
11855                 if (verbose)
11856                 {
11857                     printf("Marking the BBJ_CALLFINALLY block at BB%02u as rarely run because BB%02u is rarely run\n",
11858                            bPrev->bbNum, block->bbNum);
11859                 }
11860 #endif // DEBUG
11861             }
11862             else if (bPrev->isRunRarely())
11863             {
11864                 block->bbWeight =
11865                     bPrev->bbWeight; // the BBJ_ALWAYS block now has the same weight as the BBJ_CALLFINALLY block
11866                 block->bbFlags |= BBF_RUN_RARELY; // and is now rarely run
11867 #ifdef DEBUG
11868                 if (verbose)
11869                 {
11870                     printf("Marking the BBJ_ALWAYS block at BB%02u as rarely run because BB%02u is rarely run\n",
11871                            block->bbNum, bPrev->bbNum);
11872                 }
11873 #endif // DEBUG
11874             }
11875             else // Both blocks are hot, bPrev is known not to be using profiled weight
11876             {
11877                 bPrev->bbWeight =
11878                     block->bbWeight; // the BBJ_CALLFINALLY block now has the same weight as the BBJ_ALWAYS block
11879             }
11880             noway_assert(block->bbWeight == bPrev->bbWeight);
11881         }
11882     }
11883
11884     return result;
11885 }
11886
11887 /*****************************************************************************
11888  *
11889  *  Returns true if it is allowable (based upon the EH regions)
11890  *  to place block bAfter immediately after bBefore. It is allowable
11891  *  if the 'bBefore' and 'bAfter' blocks are in the exact same EH region.
11892  */
11893
11894 bool Compiler::fgEhAllowsMoveBlock(BasicBlock* bBefore, BasicBlock* bAfter)
11895 {
11896     return BasicBlock::sameEHRegion(bBefore, bAfter);
11897 }
11898
11899 /*****************************************************************************
11900  *
11901  *  Function called to move the range of blocks [bStart .. bEnd].
11902  *  The blocks are placed immediately after the insertAfterBlk.
11903  *  fgFirstFuncletBB is not updated; that is the responsibility of the caller, if necessary.
11904  */
11905
11906 void Compiler::fgMoveBlocksAfter(BasicBlock* bStart, BasicBlock* bEnd, BasicBlock* insertAfterBlk)
11907 {
11908     /* We have decided to insert the block(s) after 'insertAfterBlk' */
11909     CLANG_FORMAT_COMMENT_ANCHOR;
11910
11911 #ifdef DEBUG
11912     if (verbose)
11913     {
11914         printf("Relocated block%s [BB%02u..BB%02u] inserted after BB%02u%s\n", (bStart == bEnd) ? "" : "s",
11915                bStart->bbNum, bEnd->bbNum, insertAfterBlk->bbNum,
11916                (insertAfterBlk->bbNext == nullptr) ? " at the end of method" : "");
11917     }
11918 #endif // DEBUG
11919
11920     /* relink [bStart .. bEnd] into the flow graph */
11921
11922     bEnd->bbNext = insertAfterBlk->bbNext;
11923     if (insertAfterBlk->bbNext)
11924     {
11925         insertAfterBlk->bbNext->bbPrev = bEnd;
11926     }
11927     insertAfterBlk->setNext(bStart);
11928
11929     /* If insertAfterBlk was fgLastBB then update fgLastBB */
11930     if (insertAfterBlk == fgLastBB)
11931     {
11932         fgLastBB = bEnd;
11933         noway_assert(fgLastBB->bbNext == nullptr);
11934     }
11935 }
11936
11937 /*****************************************************************************
11938  *
11939  *  Function called to relocate a single range to the end of the method.
11940  *  Only an entire consecutive region can be moved and it will be kept together.
11941  *  Except for the first block, the range cannot have any blocks that jump into or out of the region.
11942  *  When successful we return the bLast block which is the last block that we relocated.
11943  *  When unsuccessful we return NULL.
11944
11945     =============================================================
11946     NOTE: This function can invalidate all pointers into the EH table, as well as change the size of the EH table!
11947     =============================================================
11948  */
11949
11950 BasicBlock* Compiler::fgRelocateEHRange(unsigned regionIndex, FG_RELOCATE_TYPE relocateType)
11951 {
11952     INDEBUG(const char* reason = "None";)
11953
11954     // Figure out the range of blocks we're going to move
11955
11956     unsigned    XTnum;
11957     EHblkDsc*   HBtab;
11958     BasicBlock* bStart  = nullptr;
11959     BasicBlock* bMiddle = nullptr;
11960     BasicBlock* bLast   = nullptr;
11961     BasicBlock* bPrev   = nullptr;
11962
11963 #if FEATURE_EH_FUNCLETS
11964     // We don't support moving try regions... yet?
11965     noway_assert(relocateType == FG_RELOCATE_HANDLER);
11966 #endif // FEATURE_EH_FUNCLETS
11967
11968     HBtab = ehGetDsc(regionIndex);
11969
11970     if (relocateType == FG_RELOCATE_TRY)
11971     {
11972         bStart = HBtab->ebdTryBeg;
11973         bLast  = HBtab->ebdTryLast;
11974     }
11975     else if (relocateType == FG_RELOCATE_HANDLER)
11976     {
11977         if (HBtab->HasFilter())
11978         {
11979             // The filter and handler funclets must be moved together, and remain contiguous.
11980             bStart  = HBtab->ebdFilter;
11981             bMiddle = HBtab->ebdHndBeg;
11982             bLast   = HBtab->ebdHndLast;
11983         }
11984         else
11985         {
11986             bStart = HBtab->ebdHndBeg;
11987             bLast  = HBtab->ebdHndLast;
11988         }
11989     }
11990
11991     // Our range must contain either all rarely run blocks or all non-rarely run blocks
11992     bool inTheRange = false;
11993     bool validRange = false;
11994
11995     BasicBlock* block;
11996
11997     noway_assert(bStart != nullptr && bLast != nullptr);
11998     if (bStart == fgFirstBB)
11999     {
12000         INDEBUG(reason = "can not relocate first block";)
12001         goto FAILURE;
12002     }
12003
12004 #if !FEATURE_EH_FUNCLETS
12005     // In the funclets case, we still need to set some information on the handler blocks
12006     if (bLast->bbNext == NULL)
12007     {
12008         INDEBUG(reason = "region is already at the end of the method";)
12009         goto FAILURE;
12010     }
12011 #endif // !FEATURE_EH_FUNCLETS
12012
12013     // Walk the block list for this purpose:
12014     // 1. Verify that all the blocks in the range are either all rarely run or not rarely run.
12015     // When creating funclets, we ignore the run rarely flag, as we need to be able to move any blocks
12016     // in the range.
12017     CLANG_FORMAT_COMMENT_ANCHOR;
12018
12019 #if !FEATURE_EH_FUNCLETS
12020     bool isRare;
12021     isRare = bStart->isRunRarely();
12022 #endif // !FEATURE_EH_FUNCLETS
12023     block = fgFirstBB;
12024     while (true)
12025     {
12026         if (block == bStart)
12027         {
12028             noway_assert(inTheRange == false);
12029             inTheRange = true;
12030         }
12031         else if (block == bLast->bbNext)
12032         {
12033             noway_assert(inTheRange == true);
12034             inTheRange = false;
12035             break; // we found the end, so we're done
12036         }
12037
12038         if (inTheRange)
12039         {
12040 #if !FEATURE_EH_FUNCLETS
12041             // Unless all blocks are (not) run rarely we must return false.
12042             if (isRare != block->isRunRarely())
12043             {
12044                 INDEBUG(reason = "this region contains both rarely run and non-rarely run blocks";)
12045                 goto FAILURE;
12046             }
12047 #endif // !FEATURE_EH_FUNCLETS
12048
12049             validRange = true;
12050         }
12051
12052         if (block == nullptr)
12053         {
12054             break;
12055         }
12056
12057         block = block->bbNext;
12058     }
12059     // Ensure that bStart .. bLast defined a valid range
12060     noway_assert((validRange == true) && (inTheRange == false));
12061
12062     bPrev = bStart->bbPrev;
12063     noway_assert(bPrev != nullptr); // Can't move a range that includes the first block of the function.
12064
12065     JITDUMP("Relocating %s range BB%02u..BB%02u (EH#%u) to end of BBlist\n",
12066             (relocateType == FG_RELOCATE_TRY) ? "try" : "handler", bStart->bbNum, bLast->bbNum, regionIndex);
12067
12068 #ifdef DEBUG
12069     if (verbose)
12070     {
12071         fgDispBasicBlocks();
12072         fgDispHandlerTab();
12073     }
12074
12075     if (!FEATURE_EH_FUNCLETS)
12076     {
12077         // This is really expensive, and quickly becomes O(n^n) with funclets
12078         // so only do it once after we've created them (see fgCreateFunclets)
12079         if (expensiveDebugCheckLevel >= 2)
12080         {
12081             fgDebugCheckBBlist();
12082         }
12083     }
12084 #endif // DEBUG
12085
12086 #if FEATURE_EH_FUNCLETS
12087
12088     bStart->bbFlags |= BBF_FUNCLET_BEG; // Mark the start block of the funclet
12089
12090     if (bMiddle != nullptr)
12091     {
12092         bMiddle->bbFlags |= BBF_FUNCLET_BEG; // Also mark the start block of a filter handler as a funclet
12093     }
12094
12095 #endif // FEATURE_EH_FUNCLETS
12096
12097     BasicBlock* bNext;
12098     bNext = bLast->bbNext;
12099
12100     /* Temporarily unlink [bStart .. bLast] from the flow graph */
12101     fgUnlinkRange(bStart, bLast);
12102
12103     BasicBlock* insertAfterBlk;
12104     insertAfterBlk = fgLastBB;
12105
12106 #if FEATURE_EH_FUNCLETS
12107
12108     // There are several cases we need to consider when moving an EH range.
12109     // If moving a range X, we must consider its relationship to every other EH
12110     // range A in the table. Note that each entry in the table represents both
12111     // a protected region and a handler region (possibly including a filter region
12112     // that must live before and adjacent to the handler region), so we must
12113     // consider try and handler regions independently. These are the cases:
12114     // 1. A is completely contained within X (where "completely contained" means
12115     //    that the 'begin' and 'last' parts of A are strictly between the 'begin'
12116     //    and 'end' parts of X, and aren't equal to either, for example, they don't
12117     //    share 'last' blocks). In this case, when we move X, A moves with it, and
12118     //    the EH table doesn't need to change.
12119     // 2. X is completely contained within A. In this case, X gets extracted from A,
12120     //    and the range of A shrinks, but because A is strictly within X, the EH
12121     //    table doesn't need to change.
12122     // 3. A and X have exactly the same range. In this case, A is moving with X and
12123     //    the EH table doesn't need to change.
12124     // 4. A and X share the 'last' block. There are two sub-cases:
12125     //    (a) A is a larger range than X (such that the beginning of A precedes the
12126     //        beginning of X): in this case, we are moving the tail of A. We set the
12127     //        'last' block of A to the the block preceding the beginning block of X.
12128     //    (b) A is a smaller range than X. Thus, we are moving the entirety of A along
12129     //        with X. In this case, nothing in the EH record for A needs to change.
12130     // 5. A and X share the 'beginning' block (but aren't the same range, as in #3).
12131     //    This can never happen here, because we are only moving handler ranges (we don't
12132     //    move try ranges), and handler regions cannot start at the beginning of a try
12133     //    range or handler range and be a subset.
12134     //
12135     // Note that A and X must properly nest for the table to be well-formed. For example,
12136     // the beginning of A can't be strictly within the range of X (that is, the beginning
12137     // of A isn't shared with the beginning of X) and the end of A outside the range.
12138
12139     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
12140     {
12141         if (XTnum != regionIndex) // we don't need to update our 'last' pointer
12142         {
12143             if (HBtab->ebdTryLast == bLast)
12144             {
12145                 // If we moved a set of blocks that were at the end of
12146                 // a different try region then we may need to update ebdTryLast
12147                 for (block = HBtab->ebdTryBeg; block != nullptr; block = block->bbNext)
12148                 {
12149                     if (block == bPrev)
12150                     {
12151                         // We were contained within it, so shrink its region by
12152                         // setting its 'last'
12153                         fgSetTryEnd(HBtab, bPrev);
12154                         break;
12155                     }
12156                     else if (block == HBtab->ebdTryLast->bbNext)
12157                     {
12158                         // bPrev does not come after the TryBeg, thus we are larger, and
12159                         // it is moving with us.
12160                         break;
12161                     }
12162                 }
12163             }
12164             if (HBtab->ebdHndLast == bLast)
12165             {
12166                 // If we moved a set of blocks that were at the end of
12167                 // a different handler region then we must update ebdHndLast
12168                 for (block = HBtab->ebdHndBeg; block != nullptr; block = block->bbNext)
12169                 {
12170                     if (block == bPrev)
12171                     {
12172                         fgSetHndEnd(HBtab, bPrev);
12173                         break;
12174                     }
12175                     else if (block == HBtab->ebdHndLast->bbNext)
12176                     {
12177                         // bPrev does not come after the HndBeg
12178                         break;
12179                     }
12180                 }
12181             }
12182         }
12183     } // end exception table iteration
12184
12185     // Insert the block(s) we are moving after fgLastBlock
12186     fgMoveBlocksAfter(bStart, bLast, insertAfterBlk);
12187
12188     if (fgFirstFuncletBB == nullptr) // The funclet region isn't set yet
12189     {
12190         fgFirstFuncletBB = bStart;
12191     }
12192     else
12193     {
12194         assert(fgFirstFuncletBB !=
12195                insertAfterBlk->bbNext); // We insert at the end, not at the beginning, of the funclet region.
12196     }
12197
12198     // These asserts assume we aren't moving try regions (which we might need to do). Only
12199     // try regions can have fall through into or out of the region.
12200
12201     noway_assert(!bPrev->bbFallsThrough()); // There can be no fall through into a filter or handler region
12202     noway_assert(!bLast->bbFallsThrough()); // There can be no fall through out of a handler region
12203
12204 #ifdef DEBUG
12205     if (verbose)
12206     {
12207         printf("Create funclets: moved region\n");
12208         fgDispHandlerTab();
12209     }
12210
12211     // We have to wait to do this until we've created all the additional regions
12212     // Because this relies on ebdEnclosingTryIndex and ebdEnclosingHndIndex
12213     if (!FEATURE_EH_FUNCLETS)
12214     {
12215         // This is really expensive, and quickly becomes O(n^n) with funclets
12216         // so only do it once after we've created them (see fgCreateFunclets)
12217         if (expensiveDebugCheckLevel >= 2)
12218         {
12219             fgDebugCheckBBlist();
12220         }
12221     }
12222 #endif // DEBUG
12223
12224 #else // FEATURE_EH_FUNCLETS
12225
12226     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
12227     {
12228         if (XTnum == regionIndex)
12229         {
12230             // Don't update our handler's Last info
12231             continue;
12232         }
12233
12234         if (HBtab->ebdTryLast == bLast)
12235         {
12236             // If we moved a set of blocks that were at the end of
12237             // a different try region then we may need to update ebdTryLast
12238             for (block = HBtab->ebdTryBeg; block != NULL; block = block->bbNext)
12239             {
12240                 if (block == bPrev)
12241                 {
12242                     fgSetTryEnd(HBtab, bPrev);
12243                     break;
12244                 }
12245                 else if (block == HBtab->ebdTryLast->bbNext)
12246                 {
12247                     // bPrev does not come after the TryBeg
12248                     break;
12249                 }
12250             }
12251         }
12252         if (HBtab->ebdHndLast == bLast)
12253         {
12254             // If we moved a set of blocks that were at the end of
12255             // a different handler region then we must update ebdHndLast
12256             for (block = HBtab->ebdHndBeg; block != NULL; block = block->bbNext)
12257             {
12258                 if (block == bPrev)
12259                 {
12260                     fgSetHndEnd(HBtab, bPrev);
12261                     break;
12262                 }
12263                 else if (block == HBtab->ebdHndLast->bbNext)
12264                 {
12265                     // bPrev does not come after the HndBeg
12266                     break;
12267                 }
12268             }
12269         }
12270     } // end exception table iteration
12271
12272     // We have decided to insert the block(s) after fgLastBlock
12273     fgMoveBlocksAfter(bStart, bLast, insertAfterBlk);
12274
12275     // If bPrev falls through, we will insert a jump to block
12276     fgConnectFallThrough(bPrev, bStart);
12277
12278     // If bLast falls through, we will insert a jump to bNext
12279     fgConnectFallThrough(bLast, bNext);
12280
12281 #endif // FEATURE_EH_FUNCLETS
12282
12283     goto DONE;
12284
12285 FAILURE:
12286
12287 #ifdef DEBUG
12288     if (verbose)
12289     {
12290         printf("*************** Failed fgRelocateEHRange(BB%02u..BB%02u) because %s\n", bStart->bbNum, bLast->bbNum,
12291                reason);
12292     }
12293 #endif // DEBUG
12294
12295     bLast = nullptr;
12296
12297 DONE:
12298
12299     return bLast;
12300 }
12301
12302 #if FEATURE_EH_FUNCLETS
12303
12304 #if defined(_TARGET_ARM_)
12305
12306 /*****************************************************************************
12307  * We just removed a BBJ_CALLFINALLY/BBJ_ALWAYS pair. If this was the only such pair
12308  * targeting the BBJ_ALWAYS target, then we need to clear the BBF_FINALLY_TARGET bit
12309  * so that target can also be removed. 'block' is the finally target. Since we just
12310  * removed the BBJ_ALWAYS, it better have the BBF_FINALLY_TARGET bit set.
12311  */
12312
12313 void Compiler::fgClearFinallyTargetBit(BasicBlock* block)
12314 {
12315     assert(fgComputePredsDone);
12316     assert((block->bbFlags & BBF_FINALLY_TARGET) != 0);
12317
12318     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
12319     {
12320         if (pred->flBlock->bbJumpKind == BBJ_ALWAYS && pred->flBlock->bbJumpDest == block)
12321         {
12322             BasicBlock* pPrev = pred->flBlock->bbPrev;
12323             if (pPrev != NULL)
12324             {
12325                 if (pPrev->bbJumpKind == BBJ_CALLFINALLY)
12326                 {
12327                     // We found a BBJ_CALLFINALLY / BBJ_ALWAYS that still points to this finally target
12328                     return;
12329                 }
12330             }
12331         }
12332     }
12333
12334     // Didn't find any BBJ_CALLFINALLY / BBJ_ALWAYS that still points here, so clear the bit
12335
12336     block->bbFlags &= ~BBF_FINALLY_TARGET;
12337 }
12338
12339 #endif // defined(_TARGET_ARM_)
12340
12341 /*****************************************************************************
12342  * Is this an intra-handler control flow edge?
12343  *
12344  * 'block' is the head block of a funclet/handler region, or .
12345  * 'predBlock' is a predecessor block of 'block' in the predecessor list.
12346  *
12347  * 'predBlock' can legally only be one of three things:
12348  * 1. in the same handler region (e.g., the source of a back-edge of a loop from
12349  *    'predBlock' to 'block'), including in nested regions within the handler,
12350  * 2. if 'block' begins a handler that is a filter-handler, 'predBlock' must be in the 'filter' region,
12351  * 3. for other handlers, 'predBlock' must be in the 'try' region corresponding to handler (or any
12352  *    region nested in the 'try' region).
12353  *
12354  * Note that on AMD64/ARM64, the BBJ_CALLFINALLY block that calls a finally handler is not
12355  * within the corresponding 'try' region: it is placed in the corresponding 'try' region's
12356  * parent (which might be the main function body). This is how it is represented to the VM
12357  * (with a special "cloned finally" EH table entry).
12358  *
12359  * Return 'true' for case #1, and 'false' otherwise.
12360  */
12361 bool Compiler::fgIsIntraHandlerPred(BasicBlock* predBlock, BasicBlock* block)
12362 {
12363     // Some simple preconditions (as stated above)
12364     assert(!fgFuncletsCreated);
12365     assert(fgGetPredForBlock(block, predBlock) != nullptr);
12366     assert(block->hasHndIndex());
12367
12368     EHblkDsc* xtab = ehGetDsc(block->getHndIndex());
12369
12370 #if FEATURE_EH_CALLFINALLY_THUNKS
12371     if (xtab->HasFinallyHandler())
12372     {
12373         assert((xtab->ebdHndBeg == block) || // The normal case
12374                ((xtab->ebdHndBeg->bbNext == block) &&
12375                 (xtab->ebdHndBeg->bbFlags & BBF_INTERNAL))); // After we've already inserted a header block, and we're
12376                                                              // trying to decide how to split up the predecessor edges.
12377         if (predBlock->bbJumpKind == BBJ_CALLFINALLY)
12378         {
12379             assert(predBlock->bbJumpDest == block);
12380
12381             // A BBJ_CALLFINALLY predecessor of the handler can only come from the corresponding try,
12382             // not from any EH clauses nested in this handler. However, we represent the BBJ_CALLFINALLY
12383             // as being in the 'try' region's parent EH region, which might be the main function body.
12384
12385             unsigned tryIndex = xtab->ebdEnclosingTryIndex;
12386             if (tryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
12387             {
12388                 assert(!predBlock->hasTryIndex());
12389             }
12390             else
12391             {
12392                 assert(predBlock->hasTryIndex());
12393                 assert(tryIndex == predBlock->getTryIndex());
12394                 assert(ehGetDsc(tryIndex)->InTryRegionBBRange(predBlock));
12395             }
12396             return false;
12397         }
12398     }
12399 #endif // FEATURE_EH_CALLFINALLY_THUNKS
12400
12401     assert(predBlock->hasHndIndex() || predBlock->hasTryIndex());
12402
12403     //   We could search the try region looking for predBlock by using bbInTryRegions
12404     // but that does a lexical search for the block, and then assumes funclets
12405     // have been created and does a lexical search of all funclets that were pulled
12406     // out of the parent try region.
12407     //   First, funclets haven't been created yet, and even if they had been, we shouldn't
12408     // have any funclet directly branching to another funclet (they have to return first).
12409     // So we can safely use CheckIsTryRegion instead of bbInTryRegions.
12410     //   Second, I believe the depth of any EH graph will on average be smaller than the
12411     // breadth of the blocks within a try body. Thus it is faster to get our answer by
12412     // looping outward over the region graph. However, I have added asserts, as a
12413     // precaution, to ensure both algorithms agree. The asserts also check that the only
12414     // way to reach the head of a funclet is from the corresponding try body or from
12415     // within the funclet (and *not* any nested funclets).
12416
12417     if (predBlock->hasTryIndex())
12418     {
12419         // Because the EH clauses are listed inside-out, any nested trys will be at a
12420         // lower index than the current try and if there's no enclosing try, tryIndex
12421         // will terminate at NO_ENCLOSING_INDEX
12422
12423         unsigned tryIndex = predBlock->getTryIndex();
12424         while (tryIndex < block->getHndIndex())
12425         {
12426             tryIndex = ehGetEnclosingTryIndex(tryIndex);
12427         }
12428         // tryIndex should enclose predBlock
12429         assert((tryIndex == EHblkDsc::NO_ENCLOSING_INDEX) || ehGetDsc(tryIndex)->InTryRegionBBRange(predBlock));
12430
12431         // At this point tryIndex is either block's handler's corresponding try body
12432         // or some outer try region that contains both predBlock & block or
12433         // NO_ENCLOSING_REGION (because there was no try body that encloses both).
12434         if (tryIndex == block->getHndIndex())
12435         {
12436             assert(xtab->InTryRegionBBRange(predBlock));
12437             assert(!xtab->InHndRegionBBRange(predBlock));
12438             return false;
12439         }
12440         // tryIndex should enclose block (and predBlock as previously asserted)
12441         assert((tryIndex == EHblkDsc::NO_ENCLOSING_INDEX) || ehGetDsc(tryIndex)->InTryRegionBBRange(block));
12442     }
12443     if (xtab->HasFilter())
12444     {
12445         // The block is a handler. Check if the pred block is from its filter. We only need to
12446         // check the end filter flag, as there is only a single filter for any handler, and we
12447         // already know predBlock is a predecessor of block.
12448         if (predBlock->bbJumpKind == BBJ_EHFILTERRET)
12449         {
12450             assert(!xtab->InHndRegionBBRange(predBlock));
12451             return false;
12452         }
12453     }
12454     // It is not in our try region (or filter), so it must be within this handler (or try bodies
12455     // within this handler)
12456     assert(!xtab->InTryRegionBBRange(predBlock));
12457     assert(xtab->InHndRegionBBRange(predBlock));
12458     return true;
12459 }
12460
12461 /*****************************************************************************
12462  * Does this block, first block of a handler region, have any predecessor edges
12463  * that are not from its corresponding try region?
12464  */
12465
12466 bool Compiler::fgAnyIntraHandlerPreds(BasicBlock* block)
12467 {
12468     assert(block->hasHndIndex());
12469     assert(fgFirstBlockOfHandler(block) == block); // this block is the first block of a handler
12470
12471     flowList* pred;
12472
12473     for (pred = block->bbPreds; pred; pred = pred->flNext)
12474     {
12475         BasicBlock* predBlock = pred->flBlock;
12476
12477         if (fgIsIntraHandlerPred(predBlock, block))
12478         {
12479             // We have a predecessor that is not from our try region
12480             return true;
12481         }
12482     }
12483
12484     return false;
12485 }
12486
12487 /*****************************************************************************
12488  * Introduce a new head block of the handler for the prolog to be put in, ahead
12489  * of the current handler head 'block'.
12490  * Note that this code has some similarities to fgCreateLoopPreHeader().
12491  */
12492
12493 void Compiler::fgInsertFuncletPrologBlock(BasicBlock* block)
12494 {
12495 #ifdef DEBUG
12496     if (verbose)
12497     {
12498         printf("\nCreating funclet prolog header for BB%02u\n", block->bbNum);
12499     }
12500 #endif
12501
12502     assert(block->hasHndIndex());
12503     assert(fgFirstBlockOfHandler(block) == block); // this block is the first block of a handler
12504
12505     /* Allocate a new basic block */
12506
12507     BasicBlock* newHead = bbNewBasicBlock(BBJ_NONE);
12508
12509     // In fgComputePreds() we set the BBF_JMP_TARGET and BBF_HAS_LABEL for all of the handler entry points
12510     //
12511     newHead->bbFlags |= (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL);
12512     newHead->inheritWeight(block);
12513     newHead->bbRefs = 0;
12514
12515     fgInsertBBbefore(block, newHead); // insert the new block in the block list
12516     fgExtendEHRegionBefore(block);    // Update the EH table to make the prolog block the first block in the block's EH
12517                                       // block.
12518
12519     // Distribute the pred list between newHead and block. Incoming edges coming from outside
12520     // the handler go to the prolog. Edges coming from with the handler are back-edges, and
12521     // go to the existing 'block'.
12522
12523     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
12524     {
12525         BasicBlock* predBlock = pred->flBlock;
12526         if (!fgIsIntraHandlerPred(predBlock, block))
12527         {
12528             // It's a jump from outside the handler; add it to the newHead preds list and remove
12529             // it from the block preds list.
12530
12531             switch (predBlock->bbJumpKind)
12532             {
12533                 case BBJ_CALLFINALLY:
12534                     noway_assert(predBlock->bbJumpDest == block);
12535                     predBlock->bbJumpDest = newHead;
12536                     fgRemoveRefPred(block, predBlock);
12537                     fgAddRefPred(newHead, predBlock);
12538                     break;
12539
12540                 default:
12541                     // The only way into the handler is via a BBJ_CALLFINALLY (to a finally handler), or
12542                     // via exception handling.
12543                     noway_assert(false);
12544                     break;
12545             }
12546         }
12547     }
12548
12549     assert(nullptr == fgGetPredForBlock(block, newHead));
12550     fgAddRefPred(block, newHead);
12551
12552     assert((newHead->bbFlags & (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL)) ==
12553            (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL));
12554 }
12555
12556 /*****************************************************************************
12557  *
12558  * Every funclet will have a prolog. That prolog will be inserted as the first instructions
12559  * in the first block of the funclet. If the prolog is also the head block of a loop, we
12560  * would end up with the prolog instructions being executed more than once.
12561  * Check for this by searching the predecessor list for loops, and create a new prolog header
12562  * block when needed. We detect a loop by looking for any predecessor that isn't in the
12563  * handler's try region, since the only way to get into a handler is via that try region.
12564  */
12565
12566 void Compiler::fgCreateFuncletPrologBlocks()
12567 {
12568     noway_assert(fgComputePredsDone);
12569     noway_assert(!fgDomsComputed); // this function doesn't maintain the dom sets
12570     assert(!fgFuncletsCreated);
12571
12572     bool      prologBlocksCreated = false;
12573     EHblkDsc* HBtabEnd;
12574     EHblkDsc* HBtab;
12575
12576     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
12577     {
12578         BasicBlock* head = HBtab->ebdHndBeg;
12579
12580         if (fgAnyIntraHandlerPreds(head))
12581         {
12582             // We need to create a new block in which to place the prolog, and split the existing
12583             // head block predecessor edges into those that should point to the prolog, and those
12584             // that shouldn't.
12585             //
12586             // It's arguable that we should just always do this, and not only when we "need to",
12587             // so there aren't two different code paths. However, it's unlikely to be necessary
12588             // for catch handlers because they have an incoming argument (the exception object)
12589             // that needs to get stored or saved, so back-arcs won't normally go to the head. It's
12590             // possible when writing in IL to generate a legal loop (e.g., push an Exception object
12591             // on the stack before jumping back to the catch head), but C# probably won't. This will
12592             // most commonly only be needed for finallys with a do/while loop at the top of the
12593             // finally.
12594             //
12595             // Note that we don't check filters. This might be a bug, but filters always have a filter
12596             // object live on entry, so it's at least unlikely (illegal?) that a loop edge targets the
12597             // filter head.
12598
12599             fgInsertFuncletPrologBlock(head);
12600             prologBlocksCreated = true;
12601         }
12602     }
12603
12604     if (prologBlocksCreated)
12605     {
12606         // If we've modified the graph, reset the 'modified' flag, since the dominators haven't
12607         // been computed.
12608         fgModified = false;
12609
12610 #if DEBUG
12611         if (verbose)
12612         {
12613             JITDUMP("\nAfter fgCreateFuncletPrologBlocks()");
12614             fgDispBasicBlocks();
12615             fgDispHandlerTab();
12616         }
12617
12618         fgVerifyHandlerTab();
12619         fgDebugCheckBBlist();
12620 #endif // DEBUG
12621     }
12622 }
12623
12624 /*****************************************************************************
12625  *
12626  *  Function to create funclets out of all EH catch/finally/fault blocks.
12627  *  We only move filter and handler blocks, not try blocks.
12628  */
12629
12630 void Compiler::fgCreateFunclets()
12631 {
12632     assert(!fgFuncletsCreated);
12633
12634 #ifdef DEBUG
12635     if (verbose)
12636     {
12637         printf("*************** In fgCreateFunclets()\n");
12638     }
12639 #endif
12640
12641     fgCreateFuncletPrologBlocks();
12642
12643     unsigned           XTnum;
12644     EHblkDsc*          HBtab;
12645     const unsigned int funcCnt = ehFuncletCount() + 1;
12646
12647     if (!FitsIn<unsigned short>(funcCnt))
12648     {
12649         IMPL_LIMITATION("Too many funclets");
12650     }
12651
12652     FuncInfoDsc* funcInfo = new (this, CMK_BasicBlock) FuncInfoDsc[funcCnt];
12653
12654     unsigned short funcIdx;
12655
12656     // Setup the root FuncInfoDsc and prepare to start associating
12657     // FuncInfoDsc's with their corresponding EH region
12658     memset((void*)funcInfo, 0, funcCnt * sizeof(FuncInfoDsc));
12659     assert(funcInfo[0].funKind == FUNC_ROOT);
12660     funcIdx = 1;
12661
12662     // Because we iterate from the top to the bottom of the compHndBBtab array, we are iterating
12663     // from most nested (innermost) to least nested (outermost) EH region. It would be reasonable
12664     // to iterate in the opposite order, but the order of funclets shouldn't matter.
12665     //
12666     // We move every handler region to the end of the function: each handler will become a funclet.
12667     //
12668     // Note that fgRelocateEHRange() can add new entries to the EH table. However, they will always
12669     // be added *after* the current index, so our iteration here is not invalidated.
12670     // It *can* invalidate the compHndBBtab pointer itself, though, if it gets reallocated!
12671
12672     for (XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
12673     {
12674         HBtab = ehGetDsc(XTnum); // must re-compute this every loop, since fgRelocateEHRange changes the table
12675         if (HBtab->HasFilter())
12676         {
12677             assert(funcIdx < funcCnt);
12678             funcInfo[funcIdx].funKind    = FUNC_FILTER;
12679             funcInfo[funcIdx].funEHIndex = (unsigned short)XTnum;
12680             funcIdx++;
12681         }
12682         assert(funcIdx < funcCnt);
12683         funcInfo[funcIdx].funKind    = FUNC_HANDLER;
12684         funcInfo[funcIdx].funEHIndex = (unsigned short)XTnum;
12685         HBtab->ebdFuncIndex          = funcIdx;
12686         funcIdx++;
12687         fgRelocateEHRange(XTnum, FG_RELOCATE_HANDLER);
12688     }
12689
12690     // We better have populated all of them by now
12691     assert(funcIdx == funcCnt);
12692
12693     // Publish
12694     compCurrFuncIdx   = 0;
12695     compFuncInfos     = funcInfo;
12696     compFuncInfoCount = (unsigned short)funcCnt;
12697
12698     fgFuncletsCreated = true;
12699
12700 #if DEBUG
12701     if (verbose)
12702     {
12703         JITDUMP("\nAfter fgCreateFunclets()");
12704         fgDispBasicBlocks();
12705         fgDispHandlerTab();
12706     }
12707
12708     fgVerifyHandlerTab();
12709     fgDebugCheckBBlist();
12710 #endif // DEBUG
12711 }
12712
12713 #else // !FEATURE_EH_FUNCLETS
12714
12715 /*****************************************************************************
12716  *
12717  *  Function called to relocate any and all EH regions.
12718  *  Only entire consecutive EH regions will be moved and they will be kept together.
12719  *  Except for the first block, the range can not have any blocks that jump into or out of the region.
12720  */
12721
12722 bool Compiler::fgRelocateEHRegions()
12723 {
12724     bool result = false; // Our return value
12725
12726 #ifdef DEBUG
12727     if (verbose)
12728         printf("*************** In fgRelocateEHRegions()\n");
12729 #endif
12730
12731     if (fgCanRelocateEHRegions)
12732     {
12733         unsigned  XTnum;
12734         EHblkDsc* HBtab;
12735
12736         for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
12737         {
12738             // Nested EH regions cannot be moved.
12739             // Also we don't want to relocate an EH region that has a filter
12740             if ((HBtab->ebdHandlerNestingLevel == 0) && !HBtab->HasFilter())
12741             {
12742                 bool movedTry = false;
12743 #if DEBUG
12744                 bool movedHnd = false;
12745 #endif // DEBUG
12746
12747                 // Only try to move the outermost try region
12748                 if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
12749                 {
12750                     // Move the entire try region if it can be moved
12751                     if (HBtab->ebdTryBeg->isRunRarely())
12752                     {
12753                         BasicBlock* bTryLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_TRY);
12754                         if (bTryLastBB != NULL)
12755                         {
12756                             result   = true;
12757                             movedTry = true;
12758                         }
12759                     }
12760 #if DEBUG
12761                     if (verbose && movedTry)
12762                     {
12763                         printf("\nAfter relocating an EH try region");
12764                         fgDispBasicBlocks();
12765                         fgDispHandlerTab();
12766
12767                         // Make sure that the predecessor lists are accurate
12768                         if (expensiveDebugCheckLevel >= 2)
12769                         {
12770                             fgDebugCheckBBlist();
12771                         }
12772                     }
12773 #endif // DEBUG
12774                 }
12775
12776                 // Currently it is not good to move the rarely run handler regions to the end of the method
12777                 // because fgDetermineFirstColdBlock() must put the start of any handler region in the hot
12778                 // section.
12779                 CLANG_FORMAT_COMMENT_ANCHOR;
12780
12781 #if 0
12782                 // Now try to move the entire handler region if it can be moved.
12783                 // Don't try to move a finally handler unless we already moved the try region.
12784                 if (HBtab->ebdHndBeg->isRunRarely() &&
12785                     !HBtab->ebdHndBeg->hasTryIndex() &&
12786                     (movedTry || !HBtab->HasFinallyHandler()))
12787                 {
12788                     BasicBlock* bHndLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_HANDLER);
12789                     if (bHndLastBB != NULL)
12790                     {
12791                         result   = true;
12792                         movedHnd = true;
12793                     }
12794                 }
12795 #endif // 0
12796
12797 #if DEBUG
12798                 if (verbose && movedHnd)
12799                 {
12800                     printf("\nAfter relocating an EH handler region");
12801                     fgDispBasicBlocks();
12802                     fgDispHandlerTab();
12803
12804                     // Make sure that the predecessor lists are accurate
12805                     if (expensiveDebugCheckLevel >= 2)
12806                     {
12807                         fgDebugCheckBBlist();
12808                     }
12809                 }
12810 #endif // DEBUG
12811             }
12812         }
12813     }
12814
12815 #if DEBUG
12816     fgVerifyHandlerTab();
12817
12818     if (verbose && result)
12819     {
12820         printf("\nAfter fgRelocateEHRegions()");
12821         fgDispBasicBlocks();
12822         fgDispHandlerTab();
12823         // Make sure that the predecessor lists are accurate
12824         fgDebugCheckBBlist();
12825     }
12826 #endif // DEBUG
12827
12828     return result;
12829 }
12830
12831 #endif // !FEATURE_EH_FUNCLETS
12832
12833 bool flowList::setEdgeWeightMinChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop)
12834 {
12835     bool result = false;
12836     if ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin))
12837     {
12838         flEdgeWeightMin = newWeight;
12839         result          = true;
12840     }
12841     else if (slop > 0)
12842     {
12843         // We allow for a small amount of inaccuracy in block weight counts.
12844         if (flEdgeWeightMax < newWeight)
12845         {
12846             // We have already determined that this edge's weight
12847             // is less than newWeight, so we just allow for the slop
12848             if (newWeight <= (flEdgeWeightMax + slop))
12849             {
12850                 result = true;
12851
12852                 if (flEdgeWeightMax != 0)
12853                 {
12854                     // We will raise flEdgeWeightMin and Max towards newWeight
12855                     flEdgeWeightMin = flEdgeWeightMax;
12856                     flEdgeWeightMax = newWeight;
12857                 }
12858
12859                 if (wbUsedSlop != nullptr)
12860                 {
12861                     *wbUsedSlop = true;
12862                 }
12863             }
12864         }
12865         else
12866         {
12867             assert(flEdgeWeightMin > newWeight);
12868
12869             // We have already determined that this edge's weight
12870             // is more than newWeight, so we just allow for the slop
12871             if ((newWeight + slop) >= flEdgeWeightMin)
12872             {
12873                 result = true;
12874
12875                 assert(flEdgeWeightMax != 0);
12876
12877                 // We will lower flEdgeWeightMin towards newWeight
12878                 flEdgeWeightMin = newWeight;
12879
12880                 if (wbUsedSlop != nullptr)
12881                 {
12882                     *wbUsedSlop = true;
12883                 }
12884             }
12885         }
12886
12887         // If we are returning true then we should have adjusted the range so that
12888         // the newWeight is in new range [Min..Max] or fgEdjeWeightMax is zero.
12889         // Also we should have set wbUsedSlop to true.
12890         if (result == true)
12891         {
12892             assert((flEdgeWeightMax == 0) || ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin)));
12893
12894             if (wbUsedSlop != nullptr)
12895             {
12896                 assert(*wbUsedSlop == true);
12897             }
12898         }
12899     }
12900
12901 #if DEBUG
12902     if (result == false)
12903     {
12904         result = false; // break here
12905     }
12906 #endif // DEBUG
12907
12908     return result;
12909 }
12910
12911 bool flowList::setEdgeWeightMaxChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop)
12912 {
12913     bool result = false;
12914     if ((newWeight >= flEdgeWeightMin) && (newWeight <= flEdgeWeightMax))
12915     {
12916         flEdgeWeightMax = newWeight;
12917         result          = true;
12918     }
12919     else if (slop > 0)
12920     {
12921         // We allow for a small amount of inaccuracy in block weight counts.
12922         if (flEdgeWeightMax < newWeight)
12923         {
12924             // We have already determined that this edge's weight
12925             // is less than newWeight, so we just allow for the slop
12926             if (newWeight <= (flEdgeWeightMax + slop))
12927             {
12928                 result = true;
12929
12930                 if (flEdgeWeightMax != 0)
12931                 {
12932                     // We will allow this to raise flEdgeWeightMax towards newWeight
12933                     flEdgeWeightMax = newWeight;
12934                 }
12935
12936                 if (wbUsedSlop != nullptr)
12937                 {
12938                     *wbUsedSlop = true;
12939                 }
12940             }
12941         }
12942         else
12943         {
12944             assert(flEdgeWeightMin > newWeight);
12945
12946             // We have already determined that this edge's weight
12947             // is more than newWeight, so we just allow for the slop
12948             if ((newWeight + slop) >= flEdgeWeightMin)
12949             {
12950                 result = true;
12951
12952                 assert(flEdgeWeightMax != 0);
12953
12954                 // We will allow this to lower flEdgeWeightMin and Max towards newWeight
12955                 flEdgeWeightMax = flEdgeWeightMin;
12956                 flEdgeWeightMin = newWeight;
12957
12958                 if (wbUsedSlop != nullptr)
12959                 {
12960                     *wbUsedSlop = true;
12961                 }
12962             }
12963         }
12964
12965         // If we are returning true then we should have adjusted the range so that
12966         // the newWeight is in new range [Min..Max] or fgEdjeWeightMax is zero
12967         // Also we should have set wbUsedSlop to true, unless it is NULL
12968         if (result == true)
12969         {
12970             assert((flEdgeWeightMax == 0) || ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin)));
12971
12972             assert((wbUsedSlop == nullptr) || (*wbUsedSlop == true));
12973         }
12974     }
12975
12976 #if DEBUG
12977     if (result == false)
12978     {
12979         result = false; // break here
12980     }
12981 #endif // DEBUG
12982
12983     return result;
12984 }
12985
12986 #ifdef DEBUG
12987 void Compiler::fgPrintEdgeWeights()
12988 {
12989     BasicBlock* bSrc;
12990     BasicBlock* bDst;
12991     flowList*   edge;
12992
12993     // Print out all of the edge weights
12994     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12995     {
12996         if (bDst->bbPreds != nullptr)
12997         {
12998             printf("    Edge weights into BB%02u :", bDst->bbNum);
12999             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13000             {
13001                 bSrc = edge->flBlock;
13002                 // This is the control flow edge (bSrc -> bDst)
13003
13004                 printf("BB%02u ", bSrc->bbNum);
13005
13006                 if (edge->flEdgeWeightMin < BB_MAX_WEIGHT)
13007                 {
13008                     printf("(%u", edge->flEdgeWeightMin);
13009                 }
13010                 else
13011                 {
13012                     printf("(MAX");
13013                 }
13014                 if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
13015                 {
13016                     if (edge->flEdgeWeightMax < BB_MAX_WEIGHT)
13017                     {
13018                         printf("..%u", edge->flEdgeWeightMax);
13019                     }
13020                     else
13021                     {
13022                         printf("..MAX");
13023                     }
13024                 }
13025                 printf(")");
13026                 if (edge->flNext != nullptr)
13027                 {
13028                     printf(", ");
13029                 }
13030             }
13031             printf("\n");
13032         }
13033     }
13034 }
13035 #endif // DEBUG
13036
13037 // return true if there is a possibility that the method has a loop (a backedge is present)
13038 bool Compiler::fgMightHaveLoop()
13039 {
13040     // Don't use a BlockSet for this temporary bitset of blocks: we don't want to have to call EnsureBasicBlockEpoch()
13041     // and potentially change the block epoch.
13042
13043     BitVecTraits blockVecTraits(fgBBNumMax + 1, this);
13044     BitVec       blocksSeen(BitVecOps::MakeEmpty(&blockVecTraits));
13045
13046     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
13047     {
13048         BitVecOps::AddElemD(&blockVecTraits, blocksSeen, block->bbNum);
13049
13050         for (BasicBlock* succ : block->GetAllSuccs(this))
13051         {
13052             if (BitVecOps::IsMember(&blockVecTraits, blocksSeen, succ->bbNum))
13053             {
13054                 return true;
13055             }
13056         }
13057     }
13058     return false;
13059 }
13060
13061 void Compiler::fgComputeEdgeWeights()
13062 {
13063 #ifdef DEBUG
13064     if (verbose)
13065     {
13066         printf("*************** In fgComputeEdgeWeights()\n");
13067     }
13068 #endif // DEBUG
13069
13070     if (fgIsUsingProfileWeights() == false)
13071     {
13072 #ifdef DEBUG
13073         if (verbose)
13074         {
13075             printf("fgComputeEdgeWeights() we do not have any profile data so we are not using the edge weights\n");
13076         }
13077 #endif // DEBUG
13078         fgHaveValidEdgeWeights = false;
13079         fgCalledCount          = BB_UNITY_WEIGHT;
13080     }
13081
13082 #if DEBUG
13083     if (verbose)
13084     {
13085         fgDispBasicBlocks();
13086         printf("\n");
13087     }
13088 #endif // DEBUG
13089
13090     BasicBlock* bSrc;
13091     BasicBlock* bDst;
13092     flowList*   edge;
13093     unsigned    iterations               = 0;
13094     unsigned    goodEdgeCountCurrent     = 0;
13095     unsigned    goodEdgeCountPrevious    = 0;
13096     bool        inconsistentProfileData  = false;
13097     bool        hasIncompleteEdgeWeights = false;
13098     unsigned    numEdges                 = 0;
13099     bool        usedSlop                 = false;
13100     bool        changed;
13101     bool        modified;
13102
13103     BasicBlock::weight_t returnWeight;
13104     BasicBlock::weight_t slop;
13105
13106     // If we have any blocks that did not have profile derived weight
13107     // we will try to fix their weight up here
13108     //
13109     modified = false;
13110     do // while (changed)
13111     {
13112         changed      = false;
13113         returnWeight = 0;
13114         iterations++;
13115
13116         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13117         {
13118             if (!bDst->hasProfileWeight() && (bDst->bbPreds != nullptr))
13119             {
13120                 BasicBlock* bOnlyNext;
13121
13122                 // This block does not have a profile derived weight
13123                 //
13124                 BasicBlock::weight_t newWeight = BB_MAX_WEIGHT;
13125
13126                 if (bDst->countOfInEdges() == 1)
13127                 {
13128                     // Only one block flows into bDst
13129                     bSrc = bDst->bbPreds->flBlock;
13130
13131                     // Does this block flow into only one other block
13132                     if (bSrc->bbJumpKind == BBJ_NONE)
13133                     {
13134                         bOnlyNext = bSrc->bbNext;
13135                     }
13136                     else if (bSrc->bbJumpKind == BBJ_ALWAYS)
13137                     {
13138                         bOnlyNext = bSrc->bbJumpDest;
13139                     }
13140                     else
13141                     {
13142                         bOnlyNext = nullptr;
13143                     }
13144
13145                     if ((bOnlyNext == bDst) && bSrc->hasProfileWeight())
13146                     {
13147                         // We know the exact weight of bDst
13148                         newWeight = bSrc->bbWeight;
13149                     }
13150                 }
13151
13152                 // Does this block flow into only one other block
13153                 if (bDst->bbJumpKind == BBJ_NONE)
13154                 {
13155                     bOnlyNext = bDst->bbNext;
13156                 }
13157                 else if (bDst->bbJumpKind == BBJ_ALWAYS)
13158                 {
13159                     bOnlyNext = bDst->bbJumpDest;
13160                 }
13161                 else
13162                 {
13163                     bOnlyNext = nullptr;
13164                 }
13165
13166                 if ((bOnlyNext != nullptr) && (bOnlyNext->bbPreds != nullptr))
13167                 {
13168                     // Does only one block flow into bOnlyNext
13169                     if (bOnlyNext->countOfInEdges() == 1)
13170                     {
13171                         noway_assert(bOnlyNext->bbPreds->flBlock == bDst);
13172
13173                         // We know the exact weight of bDst
13174                         newWeight = bOnlyNext->bbWeight;
13175                     }
13176                 }
13177
13178                 if ((newWeight != BB_MAX_WEIGHT) && (bDst->bbWeight != newWeight))
13179                 {
13180                     changed        = true;
13181                     modified       = true;
13182                     bDst->bbWeight = newWeight;
13183                     if (newWeight == 0)
13184                     {
13185                         bDst->bbFlags |= BBF_RUN_RARELY;
13186                     }
13187                     else
13188                     {
13189                         bDst->bbFlags &= ~BBF_RUN_RARELY;
13190                     }
13191                 }
13192             }
13193
13194             // Sum up the weights of all of the return blocks and throw blocks
13195             // This is used when we have a back-edge into block 1
13196             //
13197             if (bDst->hasProfileWeight() && ((bDst->bbJumpKind == BBJ_RETURN) || (bDst->bbJumpKind == BBJ_THROW)))
13198             {
13199                 returnWeight += bDst->bbWeight;
13200             }
13201         }
13202     }
13203     // Generally when we synthesize profile estimates we do it in a way where this algorithm will converge
13204     // but downstream opts that remove conditional branches may create a situation where this is not the case.
13205     // For instance a loop that becomes unreachable creates a sort of 'ring oscillator' (See test b539509)
13206     while (changed && iterations < 10);
13207
13208 #if DEBUG
13209     if (verbose && modified)
13210     {
13211         printf("fgComputeEdgeWeights() adjusted the weight of some blocks\n");
13212         fgDispBasicBlocks();
13213         printf("\n");
13214     }
13215 #endif
13216
13217     // When we are not using profile data we have already setup fgCalledCount
13218     // only set it here if we are using profile data
13219     //
13220     if (fgIsUsingProfileWeights())
13221     {
13222         BasicBlock* firstILBlock = fgFirstBB; // The first block for IL code (i.e. for the IL code at offset 0)
13223
13224         // Do we have an internal block as our first Block?
13225         if (firstILBlock->bbFlags & BBF_INTERNAL)
13226         {
13227             // Skip past any/all BBF_INTERNAL blocks that may have been added before the first real IL block.
13228             //
13229             while (firstILBlock->bbFlags & BBF_INTERNAL)
13230             {
13231                 firstILBlock = firstILBlock->bbNext;
13232             }
13233             // The 'firstILBlock' is now expected to have a profile-derived weight
13234             assert(firstILBlock->hasProfileWeight());
13235         }
13236
13237         // If the first block only has one ref then we use it's weight for fgCalledCount.
13238         // Otherwise we have backedge's into the first block, so instead we use the sum
13239         // of the return block weights for fgCalledCount.
13240         //
13241         // If the profile data has a 0 for the returnWeight
13242         // (i.e. the function never returns because it always throws)
13243         // then just use the first block weight rather than 0.
13244         //
13245         if ((firstILBlock->countOfInEdges() == 1) || (returnWeight == 0))
13246         {
13247             assert(firstILBlock->hasProfileWeight()); // This should always be a profile-derived weight
13248             fgCalledCount = firstILBlock->bbWeight;
13249         }
13250         else
13251         {
13252             fgCalledCount = returnWeight;
13253         }
13254
13255         // If we allocated a scratch block as the first BB then we need
13256         // to set its profile-derived weight to be fgCalledCount
13257         if (fgFirstBBisScratch())
13258         {
13259             fgFirstBB->setBBProfileWeight(fgCalledCount);
13260             if (fgFirstBB->bbWeight == 0)
13261             {
13262                 fgFirstBB->bbFlags |= BBF_RUN_RARELY;
13263             }
13264         }
13265
13266 #if DEBUG
13267         if (verbose)
13268         {
13269             printf("We are using the Profile Weights and fgCalledCount is %d.\n", fgCalledCount);
13270         }
13271 #endif
13272     }
13273
13274     // Now we will compute the initial flEdgeWeightMin and flEdgeWeightMax values
13275     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13276     {
13277         BasicBlock::weight_t bDstWeight = bDst->bbWeight;
13278
13279         // We subtract out the called count so that bDstWeight is
13280         // the sum of all edges that go into this block from this method.
13281         //
13282         if (bDst == fgFirstBB)
13283         {
13284             bDstWeight -= fgCalledCount;
13285         }
13286
13287         for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13288         {
13289             bool assignOK = true;
13290
13291             bSrc = edge->flBlock;
13292             // We are processing the control flow edge (bSrc -> bDst)
13293
13294             numEdges++;
13295
13296             //
13297             // If the bSrc or bDst blocks do not have exact profile weights
13298             // then we must reset any values that they currently have
13299             //
13300
13301             if (!bSrc->hasProfileWeight() || !bDst->hasProfileWeight())
13302             {
13303                 edge->flEdgeWeightMin = BB_ZERO_WEIGHT;
13304                 edge->flEdgeWeightMax = BB_MAX_WEIGHT;
13305             }
13306
13307             slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
13308             switch (bSrc->bbJumpKind)
13309             {
13310                 case BBJ_ALWAYS:
13311                 case BBJ_EHCATCHRET:
13312                 case BBJ_NONE:
13313                 case BBJ_CALLFINALLY:
13314                     // We know the exact edge weight
13315                     assignOK &= edge->setEdgeWeightMinChecked(bSrc->bbWeight, slop, &usedSlop);
13316                     assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, slop, &usedSlop);
13317                     break;
13318
13319                 case BBJ_COND:
13320                 case BBJ_SWITCH:
13321                 case BBJ_EHFINALLYRET:
13322                 case BBJ_EHFILTERRET:
13323                     if (edge->flEdgeWeightMax > bSrc->bbWeight)
13324                     {
13325                         // The maximum edge weight to block can't be greater than the weight of bSrc
13326                         assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, slop, &usedSlop);
13327                     }
13328                     break;
13329
13330                 default:
13331                     // We should never have an edge that starts from one of these jump kinds
13332                     noway_assert(!"Unexpected bbJumpKind");
13333                     break;
13334             }
13335
13336             // The maximum edge weight to block can't be greater than the weight of bDst
13337             if (edge->flEdgeWeightMax > bDstWeight)
13338             {
13339                 assignOK &= edge->setEdgeWeightMaxChecked(bDstWeight, slop, &usedSlop);
13340             }
13341
13342             if (!assignOK)
13343             {
13344                 // Here we have inconsistent profile data
13345                 inconsistentProfileData = true;
13346                 // No point in continuing
13347                 goto EARLY_EXIT;
13348             }
13349         }
13350     }
13351
13352     fgEdgeCount = numEdges;
13353
13354     iterations = 0;
13355
13356     do
13357     {
13358         iterations++;
13359         goodEdgeCountPrevious    = goodEdgeCountCurrent;
13360         goodEdgeCountCurrent     = 0;
13361         hasIncompleteEdgeWeights = false;
13362
13363         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13364         {
13365             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13366             {
13367                 bool assignOK = true;
13368
13369                 // We are processing the control flow edge (bSrc -> bDst)
13370                 bSrc = edge->flBlock;
13371
13372                 slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
13373                 if (bSrc->bbJumpKind == BBJ_COND)
13374                 {
13375                     int       diff;
13376                     flowList* otherEdge;
13377                     if (bSrc->bbNext == bDst)
13378                     {
13379                         otherEdge = fgGetPredForBlock(bSrc->bbJumpDest, bSrc);
13380                     }
13381                     else
13382                     {
13383                         otherEdge = fgGetPredForBlock(bSrc->bbNext, bSrc);
13384                     }
13385                     noway_assert(edge->flEdgeWeightMin <= edge->flEdgeWeightMax);
13386                     noway_assert(otherEdge->flEdgeWeightMin <= otherEdge->flEdgeWeightMax);
13387
13388                     // Adjust edge->flEdgeWeightMin up or adjust otherEdge->flEdgeWeightMax down
13389                     diff = ((int)bSrc->bbWeight) - ((int)edge->flEdgeWeightMin + (int)otherEdge->flEdgeWeightMax);
13390                     if (diff > 0)
13391                     {
13392                         assignOK &= edge->setEdgeWeightMinChecked(edge->flEdgeWeightMin + diff, slop, &usedSlop);
13393                     }
13394                     else if (diff < 0)
13395                     {
13396                         assignOK &=
13397                             otherEdge->setEdgeWeightMaxChecked(otherEdge->flEdgeWeightMax + diff, slop, &usedSlop);
13398                     }
13399
13400                     // Adjust otherEdge->flEdgeWeightMin up or adjust edge->flEdgeWeightMax down
13401                     diff = ((int)bSrc->bbWeight) - ((int)otherEdge->flEdgeWeightMin + (int)edge->flEdgeWeightMax);
13402                     if (diff > 0)
13403                     {
13404                         assignOK &=
13405                             otherEdge->setEdgeWeightMinChecked(otherEdge->flEdgeWeightMin + diff, slop, &usedSlop);
13406                     }
13407                     else if (diff < 0)
13408                     {
13409                         assignOK &= edge->setEdgeWeightMaxChecked(edge->flEdgeWeightMax + diff, slop, &usedSlop);
13410                     }
13411
13412                     if (!assignOK)
13413                     {
13414                         // Here we have inconsistent profile data
13415                         inconsistentProfileData = true;
13416                         // No point in continuing
13417                         goto EARLY_EXIT;
13418                     }
13419 #ifdef DEBUG
13420                     // Now edge->flEdgeWeightMin and otherEdge->flEdgeWeightMax) should add up to bSrc->bbWeight
13421                     diff = ((int)bSrc->bbWeight) - ((int)edge->flEdgeWeightMin + (int)otherEdge->flEdgeWeightMax);
13422                     noway_assert((-((int)slop) <= diff) && (diff <= ((int)slop)));
13423
13424                     // Now otherEdge->flEdgeWeightMin and edge->flEdgeWeightMax) should add up to bSrc->bbWeight
13425                     diff = ((int)bSrc->bbWeight) - ((int)otherEdge->flEdgeWeightMin + (int)edge->flEdgeWeightMax);
13426                     noway_assert((-((int)slop) <= diff) && (diff <= ((int)slop)));
13427 #endif // DEBUG
13428                 }
13429             }
13430         }
13431
13432         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13433         {
13434             BasicBlock::weight_t bDstWeight = bDst->bbWeight;
13435
13436             if (bDstWeight == BB_MAX_WEIGHT)
13437             {
13438                 inconsistentProfileData = true;
13439                 // No point in continuing
13440                 goto EARLY_EXIT;
13441             }
13442             else
13443             {
13444                 // We subtract out the called count so that bDstWeight is
13445                 // the sum of all edges that go into this block from this method.
13446                 //
13447                 if (bDst == fgFirstBB)
13448                 {
13449                     bDstWeight -= fgCalledCount;
13450                 }
13451
13452                 UINT64 minEdgeWeightSum = 0;
13453                 UINT64 maxEdgeWeightSum = 0;
13454
13455                 // Calculate the sums of the minimum and maximum edge weights
13456                 for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13457                 {
13458                     // We are processing the control flow edge (bSrc -> bDst)
13459                     bSrc = edge->flBlock;
13460
13461                     maxEdgeWeightSum += edge->flEdgeWeightMax;
13462                     minEdgeWeightSum += edge->flEdgeWeightMin;
13463                 }
13464
13465                 // maxEdgeWeightSum is the sum of all flEdgeWeightMax values into bDst
13466                 // minEdgeWeightSum is the sum of all flEdgeWeightMin values into bDst
13467
13468                 for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13469                 {
13470                     bool assignOK = true;
13471
13472                     // We are processing the control flow edge (bSrc -> bDst)
13473                     bSrc = edge->flBlock;
13474                     slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
13475
13476                     // otherMaxEdgesWeightSum is the sum of all of the other edges flEdgeWeightMax values
13477                     // This can be used to compute a lower bound for our minimum edge weight
13478                     noway_assert(maxEdgeWeightSum >= edge->flEdgeWeightMax);
13479                     UINT64 otherMaxEdgesWeightSum = maxEdgeWeightSum - edge->flEdgeWeightMax;
13480
13481                     // otherMinEdgesWeightSum is the sum of all of the other edges flEdgeWeightMin values
13482                     // This can be used to compute an upper bound for our maximum edge weight
13483                     noway_assert(minEdgeWeightSum >= edge->flEdgeWeightMin);
13484                     UINT64 otherMinEdgesWeightSum = minEdgeWeightSum - edge->flEdgeWeightMin;
13485
13486                     if (bDstWeight >= otherMaxEdgesWeightSum)
13487                     {
13488                         // minWeightCalc is our minWeight when every other path to bDst takes it's flEdgeWeightMax value
13489                         BasicBlock::weight_t minWeightCalc =
13490                             (BasicBlock::weight_t)(bDstWeight - otherMaxEdgesWeightSum);
13491                         if (minWeightCalc > edge->flEdgeWeightMin)
13492                         {
13493                             assignOK &= edge->setEdgeWeightMinChecked(minWeightCalc, slop, &usedSlop);
13494                         }
13495                     }
13496
13497                     if (bDstWeight >= otherMinEdgesWeightSum)
13498                     {
13499                         // maxWeightCalc is our maxWeight when every other path to bDst takes it's flEdgeWeightMin value
13500                         BasicBlock::weight_t maxWeightCalc =
13501                             (BasicBlock::weight_t)(bDstWeight - otherMinEdgesWeightSum);
13502                         if (maxWeightCalc < edge->flEdgeWeightMax)
13503                         {
13504                             assignOK &= edge->setEdgeWeightMaxChecked(maxWeightCalc, slop, &usedSlop);
13505                         }
13506                     }
13507
13508                     if (!assignOK)
13509                     {
13510                         // Here we have inconsistent profile data
13511                         inconsistentProfileData = true;
13512                         // No point in continuing
13513                         goto EARLY_EXIT;
13514                     }
13515
13516                     // When flEdgeWeightMin equals flEdgeWeightMax we have a "good" edge weight
13517                     if (edge->flEdgeWeightMin == edge->flEdgeWeightMax)
13518                     {
13519                         // Count how many "good" edge weights we have
13520                         // Each time through we should have more "good" weights
13521                         // We exit the while loop when no longer find any new "good" edges
13522                         goodEdgeCountCurrent++;
13523                     }
13524                     else
13525                     {
13526                         // Remember that we have seen at least one "Bad" edge weight
13527                         // so that we will repeat the while loop again
13528                         hasIncompleteEdgeWeights = true;
13529                     }
13530                 }
13531             }
13532         }
13533
13534         if (inconsistentProfileData)
13535         {
13536             hasIncompleteEdgeWeights = true;
13537             break;
13538         }
13539
13540         if (numEdges == goodEdgeCountCurrent)
13541         {
13542             noway_assert(hasIncompleteEdgeWeights == false);
13543             break;
13544         }
13545
13546     } while (hasIncompleteEdgeWeights && (goodEdgeCountCurrent > goodEdgeCountPrevious) && (iterations < 8));
13547
13548 EARLY_EXIT:;
13549
13550 #ifdef DEBUG
13551     if (verbose)
13552     {
13553         if (inconsistentProfileData)
13554         {
13555             printf("fgComputeEdgeWeights() found inconsistent profile data, not using the edge weights\n");
13556         }
13557         else
13558         {
13559             if (hasIncompleteEdgeWeights)
13560             {
13561                 printf("fgComputeEdgeWeights() was able to compute exact edge weights for %3d of the %3d edges, using "
13562                        "%d passes.\n",
13563                        goodEdgeCountCurrent, numEdges, iterations);
13564             }
13565             else
13566             {
13567                 printf("fgComputeEdgeWeights() was able to compute exact edge weights for all of the %3d edges, using "
13568                        "%d passes.\n",
13569                        numEdges, iterations);
13570             }
13571
13572             fgPrintEdgeWeights();
13573         }
13574     }
13575 #endif // DEBUG
13576
13577     fgSlopUsedInEdgeWeights  = usedSlop;
13578     fgRangeUsedInEdgeWeights = false;
13579
13580     // See if any edge weight are expressed in [min..max] form
13581
13582     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
13583     {
13584         if (bDst->bbPreds != nullptr)
13585         {
13586             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
13587             {
13588                 bSrc = edge->flBlock;
13589                 // This is the control flow edge (bSrc -> bDst)
13590
13591                 if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
13592                 {
13593                     fgRangeUsedInEdgeWeights = true;
13594                     break;
13595                 }
13596             }
13597             if (fgRangeUsedInEdgeWeights)
13598             {
13599                 break;
13600             }
13601         }
13602     }
13603
13604     fgHaveValidEdgeWeights = !inconsistentProfileData;
13605     fgEdgeWeightsComputed  = true;
13606 }
13607
13608 // fgOptimizeBranchToEmptyUnconditional:
13609 //    optimize a jump to an empty block which ends in an unconditional branch.
13610 //  Args:
13611 //      block: source block
13612 //      bDest: destination
13613 //  Returns: true if we changed the code
13614 //
13615 bool Compiler::fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBlock* bDest)
13616 {
13617     bool optimizeJump = true;
13618
13619     assert(bDest->isEmpty());
13620     assert(bDest->bbJumpKind == BBJ_ALWAYS);
13621
13622     // We do not optimize jumps between two different try regions.
13623     // However jumping to a block that is not in any try region is OK
13624     //
13625     if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
13626     {
13627         optimizeJump = false;
13628     }
13629
13630     // Don't optimize a jump to a removed block
13631     if (bDest->bbJumpDest->bbFlags & BBF_REMOVED)
13632     {
13633         optimizeJump = false;
13634     }
13635
13636     // Don't optimize a jump to a cloned finally
13637     if (bDest->bbFlags & BBF_CLONED_FINALLY_BEGIN)
13638     {
13639         optimizeJump = false;
13640     }
13641
13642 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13643     // Don't optimize a jump to a finally target. For BB1->BB2->BB3, where
13644     // BB2 is a finally target, if we changed BB1 to jump directly to BB3,
13645     // it would skip the finally target. BB1 might be a BBJ_ALWAYS block part
13646     // of a BBJ_CALLFINALLY/BBJ_ALWAYS pair, so changing the finally target
13647     // would change the unwind behavior.
13648     if (bDest->bbFlags & BBF_FINALLY_TARGET)
13649     {
13650         optimizeJump = false;
13651     }
13652 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13653
13654     // Must optimize jump if bDest has been removed
13655     //
13656     if (bDest->bbFlags & BBF_REMOVED)
13657     {
13658         optimizeJump = true;
13659     }
13660
13661     // If we are optimizing using real profile weights
13662     // then don't optimize a conditional jump to an unconditional jump
13663     // until after we have computed the edge weights
13664     //
13665     if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed)
13666     {
13667         fgNeedsUpdateFlowGraph = true;
13668         optimizeJump           = false;
13669     }
13670
13671     if (optimizeJump)
13672     {
13673 #ifdef DEBUG
13674         if (verbose)
13675         {
13676             printf("\nOptimizing a jump to an unconditional jump (BB%02u -> BB%02u -> BB%02u)\n", block->bbNum,
13677                    bDest->bbNum, bDest->bbJumpDest->bbNum);
13678         }
13679 #endif // DEBUG
13680
13681         //
13682         // When we optimize a branch to branch we need to update the profile weight
13683         // of bDest by subtracting out the block/edge weight of the path that is being optimized.
13684         //
13685         if (fgHaveValidEdgeWeights && bDest->hasProfileWeight())
13686         {
13687             flowList* edge1 = fgGetPredForBlock(bDest, block);
13688             noway_assert(edge1 != nullptr);
13689
13690             BasicBlock::weight_t edgeWeight;
13691
13692             if (edge1->flEdgeWeightMin != edge1->flEdgeWeightMax)
13693             {
13694                 //
13695                 // We only have an estimate for the edge weight
13696                 //
13697                 edgeWeight = (edge1->flEdgeWeightMin + edge1->flEdgeWeightMax) / 2;
13698                 //
13699                 //  Clear the profile weight flag
13700                 //
13701                 bDest->bbFlags &= ~BBF_PROF_WEIGHT;
13702             }
13703             else
13704             {
13705                 //
13706                 // We only have the exact edge weight
13707                 //
13708                 edgeWeight = edge1->flEdgeWeightMin;
13709             }
13710
13711             //
13712             // Update the bDest->bbWeight
13713             //
13714             if (bDest->bbWeight > edgeWeight)
13715             {
13716                 bDest->bbWeight -= edgeWeight;
13717             }
13718             else
13719             {
13720                 bDest->bbWeight = BB_ZERO_WEIGHT;
13721                 bDest->bbFlags |= BBF_RUN_RARELY; // Set the RarelyRun flag
13722             }
13723
13724             flowList* edge2 = fgGetPredForBlock(bDest->bbJumpDest, bDest);
13725
13726             if (edge2 != nullptr)
13727             {
13728                 //
13729                 // Update the edge2 min/max weights
13730                 //
13731                 if (edge2->flEdgeWeightMin > edge1->flEdgeWeightMin)
13732                 {
13733                     edge2->flEdgeWeightMin -= edge1->flEdgeWeightMin;
13734                 }
13735                 else
13736                 {
13737                     edge2->flEdgeWeightMin = BB_ZERO_WEIGHT;
13738                 }
13739
13740                 if (edge2->flEdgeWeightMax > edge1->flEdgeWeightMin)
13741                 {
13742                     edge2->flEdgeWeightMax -= edge1->flEdgeWeightMin;
13743                 }
13744                 else
13745                 {
13746                     edge2->flEdgeWeightMax = BB_ZERO_WEIGHT;
13747                 }
13748             }
13749         }
13750
13751         // Optimize the JUMP to empty unconditional JUMP to go to the new target
13752         block->bbJumpDest = bDest->bbJumpDest;
13753
13754         fgAddRefPred(bDest->bbJumpDest, block, fgRemoveRefPred(bDest, block));
13755
13756         return true;
13757     }
13758     return false;
13759 }
13760
13761 // fgOptimizeEmptyBlock:
13762 //   Does flow optimization of an empty block (can remove it in some cases)
13763 //
13764 //  Args:
13765 //      block: an empty block
13766 //  Returns: true if we changed the code
13767
13768 bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block)
13769 {
13770     assert(block->isEmpty());
13771
13772     BasicBlock* bPrev = block->bbPrev;
13773
13774     switch (block->bbJumpKind)
13775     {
13776         case BBJ_COND:
13777         case BBJ_SWITCH:
13778         case BBJ_THROW:
13779
13780             /* can never happen */
13781             noway_assert(!"Conditional, switch, or throw block with empty body!");
13782             break;
13783
13784         case BBJ_CALLFINALLY:
13785         case BBJ_RETURN:
13786         case BBJ_EHCATCHRET:
13787         case BBJ_EHFINALLYRET:
13788         case BBJ_EHFILTERRET:
13789
13790             /* leave them as is */
13791             /* some compilers generate multiple returns and put all of them at the end -
13792              * to solve that we need the predecessor list */
13793
13794             break;
13795
13796         case BBJ_ALWAYS:
13797
13798             // A GOTO cannot be to the next block since that
13799             // should have been fixed by the  optimization above
13800             // An exception is made for a jump from Hot to Cold
13801             noway_assert(block->bbJumpDest != block->bbNext || ((bPrev != nullptr) && bPrev->isBBCallAlwaysPair()) ||
13802                          fgInDifferentRegions(block, block->bbNext));
13803
13804             /* Cannot remove the first BB */
13805             if (!bPrev)
13806             {
13807                 break;
13808             }
13809
13810             /* Do not remove a block that jumps to itself - used for while (true){} */
13811             if (block->bbJumpDest == block)
13812             {
13813                 break;
13814             }
13815
13816             /* Empty GOTO can be removed iff bPrev is BBJ_NONE */
13817             if (bPrev->bbJumpKind != BBJ_NONE)
13818             {
13819                 break;
13820             }
13821
13822             // can't allow fall through into cold code
13823             if (block->bbNext == fgFirstColdBlock)
13824             {
13825                 break;
13826             }
13827
13828             /* Can fall through since this is similar with removing
13829              * a BBJ_NONE block, only the successor is different */
13830
13831             __fallthrough;
13832
13833         case BBJ_NONE:
13834
13835             /* special case if this is the first BB */
13836             if (!bPrev)
13837             {
13838                 assert(block == fgFirstBB);
13839             }
13840             else
13841             {
13842                 /* If this block follows a BBJ_CALLFINALLY do not remove it
13843                  * (because we don't know who may jump to it) */
13844                 if (bPrev->bbJumpKind == BBJ_CALLFINALLY)
13845                 {
13846                     break;
13847                 }
13848             }
13849
13850 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13851             /* Don't remove finally targets */
13852             if (block->bbFlags & BBF_FINALLY_TARGET)
13853                 break;
13854 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13855
13856 #if FEATURE_EH_FUNCLETS
13857             /* Don't remove an empty block that is in a different EH region
13858              * from its successor block, if the block is the target of a
13859              * catch return. It is required that the return address of a
13860              * catch be in the correct EH region, for re-raise of thread
13861              * abort exceptions to work. Insert a NOP in the empty block
13862              * to ensure we generate code for the block, if we keep it.
13863              */
13864             {
13865                 BasicBlock* succBlock;
13866
13867                 if (block->bbJumpKind == BBJ_ALWAYS)
13868                 {
13869                     succBlock = block->bbJumpDest;
13870                 }
13871                 else
13872                 {
13873                     succBlock = block->bbNext;
13874                 }
13875
13876                 if ((succBlock != nullptr) && !BasicBlock::sameEHRegion(block, succBlock))
13877                 {
13878                     // The empty block and the block that follows it are in different
13879                     // EH regions. Is this a case where they can't be merged?
13880
13881                     bool okToMerge = true; // assume it's ok
13882                     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
13883                     {
13884                         if (pred->flBlock->bbJumpKind == BBJ_EHCATCHRET)
13885                         {
13886                             assert(pred->flBlock->bbJumpDest == block);
13887                             okToMerge = false; // we can't get rid of the empty block
13888                             break;
13889                         }
13890                     }
13891
13892                     if (!okToMerge)
13893                     {
13894                         // Insert a NOP in the empty block to ensure we generate code
13895                         // for the catchret target in the right EH region.
13896                         GenTree* nop = new (this, GT_NO_OP) GenTree(GT_NO_OP, TYP_VOID);
13897
13898                         if (block->IsLIR())
13899                         {
13900                             LIR::AsRange(block).InsertAtEnd(nop);
13901                             LIR::ReadOnlyRange range(nop, nop);
13902                             m_pLowering->LowerRange(block, range);
13903                         }
13904                         else
13905                         {
13906                             GenTree* nopStmt = fgInsertStmtAtEnd(block, nop);
13907                             fgSetStmtSeq(nopStmt);
13908                             gtSetStmtInfo(nopStmt);
13909                         }
13910
13911 #ifdef DEBUG
13912                         if (verbose)
13913                         {
13914                             printf("\nKeeping empty block BB%02u - it is the target of a catch return\n", block->bbNum);
13915                         }
13916 #endif // DEBUG
13917
13918                         break; // go to the next block
13919                     }
13920                 }
13921             }
13922 #endif // FEATURE_EH_FUNCLETS
13923
13924             if (!ehCanDeleteEmptyBlock(block))
13925             {
13926                 // We're not allowed to remove this block due to reasons related to the EH table.
13927                 break;
13928             }
13929
13930             /* special case if this is the last BB */
13931             if (block == fgLastBB)
13932             {
13933                 if (!bPrev)
13934                 {
13935                     break;
13936                 }
13937                 fgLastBB = bPrev;
13938             }
13939
13940             // When using profile weights, fgComputeEdgeWeights expects the first non-internal block to have profile
13941             // weight.
13942             // Make sure we don't break that invariant.
13943             if (fgIsUsingProfileWeights() && block->hasProfileWeight() && (block->bbFlags & BBF_INTERNAL) == 0)
13944             {
13945                 BasicBlock* bNext = block->bbNext;
13946
13947                 // Check if the next block can't maintain the invariant.
13948                 if ((bNext == nullptr) || ((bNext->bbFlags & BBF_INTERNAL) != 0) || !bNext->hasProfileWeight())
13949                 {
13950                     // Check if the current block is the first non-internal block.
13951                     BasicBlock* curBB = bPrev;
13952                     while ((curBB != nullptr) && (curBB->bbFlags & BBF_INTERNAL) != 0)
13953                     {
13954                         curBB = curBB->bbPrev;
13955                     }
13956                     if (curBB == nullptr)
13957                     {
13958                         // This block is the first non-internal block and it has profile weight.
13959                         // Don't delete it.
13960                         break;
13961                     }
13962                 }
13963             }
13964
13965             /* Remove the block */
13966             compCurBB = block;
13967             fgRemoveBlock(block, false);
13968             return true;
13969
13970         default:
13971             noway_assert(!"Unexpected bbJumpKind");
13972             break;
13973     }
13974     return false;
13975 }
13976
13977 // fgOptimizeSwitchBranches:
13978 //   Does flow optimization for a switch - bypasses jumps to empty unconditional branches,
13979 //      and transforms degenerate switch cases like those with 1 or 2 targets
13980 //
13981 //  Args:
13982 //      block: BasicBlock that contains the switch
13983 //  Returns: true if we changed the code
13984 //
13985 bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block)
13986 {
13987     assert(block->bbJumpKind == BBJ_SWITCH);
13988
13989     unsigned     jmpCnt = block->bbJumpSwt->bbsCount;
13990     BasicBlock** jmpTab = block->bbJumpSwt->bbsDstTab;
13991     BasicBlock*  bNewDest; // the new jump target for the current switch case
13992     BasicBlock*  bDest;
13993     bool         returnvalue = false;
13994
13995     do
13996     {
13997     REPEAT_SWITCH:;
13998         bDest    = *jmpTab;
13999         bNewDest = bDest;
14000
14001         // Do we have a JUMP to an empty unconditional JUMP block?
14002         if (bDest->isEmpty() && (bDest->bbJumpKind == BBJ_ALWAYS) &&
14003             (bDest != bDest->bbJumpDest)) // special case for self jumps
14004         {
14005             bool optimizeJump = true;
14006
14007             // We do not optimize jumps between two different try regions.
14008             // However jumping to a block that is not in any try region is OK
14009             //
14010             if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
14011             {
14012                 optimizeJump = false;
14013             }
14014
14015             // If we are optimize using real profile weights
14016             // then don't optimize a switch jump to an unconditional jump
14017             // until after we have computed the edge weights
14018             //
14019             if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed)
14020             {
14021                 fgNeedsUpdateFlowGraph = true;
14022                 optimizeJump           = false;
14023             }
14024
14025             if (optimizeJump)
14026             {
14027                 bNewDest = bDest->bbJumpDest;
14028 #ifdef DEBUG
14029                 if (verbose)
14030                 {
14031                     printf("\nOptimizing a switch jump to an empty block with an unconditional jump (BB%02u -> BB%02u "
14032                            "-> BB%02u)\n",
14033                            block->bbNum, bDest->bbNum, bNewDest->bbNum);
14034                 }
14035 #endif // DEBUG
14036             }
14037         }
14038
14039         if (bNewDest != bDest)
14040         {
14041             //
14042             // When we optimize a branch to branch we need to update the profile weight
14043             // of bDest by subtracting out the block/edge weight of the path that is being optimized.
14044             //
14045             if (fgIsUsingProfileWeights() && bDest->hasProfileWeight())
14046             {
14047                 if (fgHaveValidEdgeWeights)
14048                 {
14049                     flowList*            edge                = fgGetPredForBlock(bDest, block);
14050                     BasicBlock::weight_t branchThroughWeight = edge->flEdgeWeightMin;
14051
14052                     if (bDest->bbWeight > branchThroughWeight)
14053                     {
14054                         bDest->bbWeight -= branchThroughWeight;
14055                     }
14056                     else
14057                     {
14058                         bDest->bbWeight = BB_ZERO_WEIGHT;
14059                         bDest->bbFlags |= BBF_RUN_RARELY;
14060                     }
14061                 }
14062             }
14063
14064             // Update the switch jump table
14065             *jmpTab = bNewDest;
14066
14067             // Maintain, if necessary, the set of unique targets of "block."
14068             UpdateSwitchTableTarget(block, bDest, bNewDest);
14069
14070             fgAddRefPred(bNewDest, block, fgRemoveRefPred(bDest, block));
14071
14072             // we optimized a Switch label - goto REPEAT_SWITCH to follow this new jump
14073             returnvalue = true;
14074
14075             goto REPEAT_SWITCH;
14076         }
14077     } while (++jmpTab, --jmpCnt);
14078
14079     GenTreeStmt* switchStmt = nullptr;
14080     LIR::Range*  blockRange = nullptr;
14081
14082     GenTree* switchTree;
14083     if (block->IsLIR())
14084     {
14085         blockRange = &LIR::AsRange(block);
14086         switchTree = blockRange->LastNode();
14087
14088         assert(switchTree->OperGet() == GT_SWITCH_TABLE);
14089     }
14090     else
14091     {
14092         switchStmt = block->lastStmt();
14093         switchTree = switchStmt->gtStmtExpr;
14094
14095         assert(switchTree->OperGet() == GT_SWITCH);
14096     }
14097
14098     noway_assert(switchTree->gtType == TYP_VOID);
14099
14100     // At this point all of the case jump targets have been updated such
14101     // that none of them go to block that is an empty unconditional block
14102     //
14103     jmpTab = block->bbJumpSwt->bbsDstTab;
14104     jmpCnt = block->bbJumpSwt->bbsCount;
14105     // Now check for two trivial switch jumps.
14106     //
14107     if (block->NumSucc(this) == 1)
14108     {
14109         // Use BBJ_ALWAYS for a switch with only a default clause, or with only one unique successor.
14110         BasicBlock* uniqueSucc = jmpTab[0];
14111
14112 #ifdef DEBUG
14113         if (verbose)
14114         {
14115             printf("\nRemoving a switch jump with a single target (BB%02u)\n", block->bbNum);
14116             printf("BEFORE:\n");
14117         }
14118 #endif // DEBUG
14119
14120         if (block->IsLIR())
14121         {
14122             bool               isClosed;
14123             unsigned           sideEffects;
14124             LIR::ReadOnlyRange switchTreeRange = blockRange->GetTreeRange(switchTree, &isClosed, &sideEffects);
14125
14126             // The switch tree should form a contiguous, side-effect free range by construction. See
14127             // Lowering::LowerSwitch for details.
14128             assert(isClosed);
14129             assert((sideEffects & GTF_ALL_EFFECT) == 0);
14130
14131             blockRange->Delete(this, block, std::move(switchTreeRange));
14132         }
14133         else
14134         {
14135             /* check for SIDE_EFFECTS */
14136             if (switchTree->gtFlags & GTF_SIDE_EFFECT)
14137             {
14138                 /* Extract the side effects from the conditional */
14139                 GenTree* sideEffList = nullptr;
14140
14141                 gtExtractSideEffList(switchTree, &sideEffList);
14142
14143                 if (sideEffList == nullptr)
14144                 {
14145                     goto NO_SWITCH_SIDE_EFFECT;
14146                 }
14147
14148                 noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
14149
14150 #ifdef DEBUG
14151                 if (verbose)
14152                 {
14153                     printf("\nSwitch expression has side effects! Extracting side effects...\n");
14154                     gtDispTree(switchTree);
14155                     printf("\n");
14156                     gtDispTree(sideEffList);
14157                     printf("\n");
14158                 }
14159 #endif // DEBUG
14160
14161                 /* Replace the conditional statement with the list of side effects */
14162                 noway_assert(sideEffList->gtOper != GT_STMT);
14163                 noway_assert(sideEffList->gtOper != GT_SWITCH);
14164
14165                 switchStmt->gtStmtExpr = sideEffList;
14166
14167                 if (fgStmtListThreaded)
14168                 {
14169                     /* Update the lclvar ref counts */
14170                     compCurBB = block;
14171                     fgUpdateRefCntForExtract(switchTree, sideEffList);
14172
14173                     /* Update ordering, costs, FP levels, etc. */
14174                     gtSetStmtInfo(switchStmt);
14175
14176                     /* Re-link the nodes for this statement */
14177                     fgSetStmtSeq(switchStmt);
14178                 }
14179             }
14180             else
14181             {
14182
14183             NO_SWITCH_SIDE_EFFECT:
14184
14185                 /* conditional has NO side effect - remove it */
14186                 fgRemoveStmt(block, switchStmt);
14187             }
14188         }
14189
14190         // Change the switch jump into a BBJ_ALWAYS
14191         block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0];
14192         block->bbJumpKind = BBJ_ALWAYS;
14193         if (jmpCnt > 1)
14194         {
14195             for (unsigned i = 1; i < jmpCnt; ++i)
14196             {
14197                 (void)fgRemoveRefPred(jmpTab[i], block);
14198             }
14199         }
14200
14201         return true;
14202     }
14203     else if (block->bbJumpSwt->bbsCount == 2 && block->bbJumpSwt->bbsDstTab[1] == block->bbNext)
14204     {
14205         /* Use a BBJ_COND(switchVal==0) for a switch with only one
14206            significant clause besides the default clause, if the
14207            default clause is bbNext */
14208         GenTree* switchVal = switchTree->gtOp.gtOp1;
14209         noway_assert(genActualTypeIsIntOrI(switchVal->TypeGet()));
14210
14211         // If we are in LIR, remove the jump table from the block.
14212         if (block->IsLIR())
14213         {
14214             GenTree* jumpTable = switchTree->gtOp.gtOp2;
14215             assert(jumpTable->OperGet() == GT_JMPTABLE);
14216             blockRange->Remove(jumpTable);
14217         }
14218
14219         // Change the GT_SWITCH(switchVal) into GT_JTRUE(GT_EQ(switchVal==0)).
14220         // Also mark the node as GTF_DONT_CSE as further down JIT is not capable of handling it.
14221         // For example CSE could determine that the expression rooted at GT_EQ is a candidate cse and
14222         // replace it with a COMMA node.  In such a case we will end up with GT_JTRUE node pointing to
14223         // a COMMA node which results in noway asserts in fgMorphSmpOp(), optAssertionGen() and rpPredictTreeRegUse().
14224         // For the same reason fgMorphSmpOp() marks GT_JTRUE nodes with RELOP children as GTF_DONT_CSE.
14225         CLANG_FORMAT_COMMENT_ANCHOR;
14226
14227 #ifdef DEBUG
14228         if (verbose)
14229         {
14230             printf("\nConverting a switch (BB%02u) with only one significant clause besides a default target to a "
14231                    "conditional branch\n",
14232                    block->bbNum);
14233         }
14234 #endif // DEBUG
14235
14236         switchTree->ChangeOper(GT_JTRUE);
14237         GenTree* zeroConstNode = gtNewZeroConNode(genActualType(switchVal->TypeGet()));
14238         GenTree* condNode      = gtNewOperNode(GT_EQ, TYP_INT, switchVal, zeroConstNode);
14239         switchTree->gtOp.gtOp1 = condNode;
14240         switchTree->gtOp.gtOp1->gtFlags |= (GTF_RELOP_JMP_USED | GTF_DONT_CSE);
14241
14242         if (block->IsLIR())
14243         {
14244             blockRange->InsertAfter(switchVal, zeroConstNode, condNode);
14245             LIR::ReadOnlyRange range(zeroConstNode, switchTree);
14246             m_pLowering->LowerRange(block, range);
14247         }
14248         else
14249         {
14250             // Re-link the nodes for this statement.
14251             fgSetStmtSeq(switchStmt);
14252         }
14253
14254         block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0];
14255         block->bbJumpKind = BBJ_COND;
14256
14257         return true;
14258     }
14259     return returnvalue;
14260 }
14261
14262 // fgBlockEndFavorsTailDuplication:
14263 //     Heuristic function that returns true if this block ends in a statement that looks favorable
14264 //     for tail-duplicating its successor (such as assigning a constant to a local).
14265 //  Args:
14266 //      block: BasicBlock we are considering duplicating the successor of
14267 //  Returns:
14268 //      true if it seems like a good idea
14269 //
14270 bool Compiler::fgBlockEndFavorsTailDuplication(BasicBlock* block)
14271 {
14272     if (block->isRunRarely())
14273     {
14274         return false;
14275     }
14276
14277     if (!block->lastStmt())
14278     {
14279         return false;
14280     }
14281     else
14282     {
14283         // Tail duplication tends to pay off when the last statement
14284         // is an assignment of a constant, arraylength, or a relop.
14285         // This is because these statements produce information about values
14286         // that would otherwise be lost at the upcoming merge point.
14287
14288         GenTreeStmt* lastStmt = block->lastStmt();
14289         GenTree*     tree     = lastStmt->gtStmtExpr;
14290         if (tree->gtOper != GT_ASG)
14291         {
14292             return false;
14293         }
14294
14295         if (tree->OperIsBlkOp())
14296         {
14297             return false;
14298         }
14299
14300         GenTree* op2 = tree->gtOp.gtOp2;
14301         if (op2->gtOper != GT_ARR_LENGTH && !op2->OperIsConst() && ((op2->OperKind() & GTK_RELOP) == 0))
14302         {
14303             return false;
14304         }
14305     }
14306     return true;
14307 }
14308
14309 // fgBlockIsGoodTailDuplicationCandidate:
14310 //     Heuristic function that examines a block (presumably one that is a merge point) to determine
14311 //     if it should be duplicated.
14312 // args:
14313 //     target - the tail block (candidate for duplication)
14314 // returns:
14315 //     true if this block seems like a good candidate for duplication
14316 //
14317 bool Compiler::fgBlockIsGoodTailDuplicationCandidate(BasicBlock* target)
14318 {
14319     GenTreeStmt* stmt = target->FirstNonPhiDef();
14320
14321     // Here we are looking for blocks with a single statement feeding a conditional branch.
14322     // These blocks are small, and when duplicated onto the tail of blocks that end in
14323     // assignments, there is a high probability of the branch completely going away.
14324
14325     // This is by no means the only kind of tail that it is beneficial to duplicate,
14326     // just the only one we recognize for now.
14327
14328     if (stmt != target->lastStmt())
14329     {
14330         return false;
14331     }
14332
14333     if (target->bbJumpKind != BBJ_COND)
14334     {
14335         return false;
14336     }
14337
14338     GenTree* tree = stmt->gtStmtExpr;
14339
14340     if (tree->gtOper != GT_JTRUE)
14341     {
14342         return false;
14343     }
14344
14345     // must be some kind of relational operator
14346     GenTree* cond = tree->gtOp.gtOp1;
14347     if (!(cond->OperKind() & GTK_RELOP))
14348     {
14349         return false;
14350     }
14351
14352     // op1 must be some combinations of casts of local or constant
14353     GenTree* op1 = cond->gtOp.gtOp1;
14354     while (op1->gtOper == GT_CAST)
14355     {
14356         op1 = op1->gtOp.gtOp1;
14357     }
14358     if (!op1->IsLocal() && !op1->OperIsConst())
14359     {
14360         return false;
14361     }
14362
14363     // op2 must be some combinations of casts of local or constant
14364     GenTree* op2 = cond->gtOp.gtOp2;
14365     while (op2->gtOper == GT_CAST)
14366     {
14367         op2 = op2->gtOp.gtOp1;
14368     }
14369     if (!op2->IsLocal() && !op2->OperIsConst())
14370     {
14371         return false;
14372     }
14373
14374     return true;
14375 }
14376
14377 // fgOptimizeUncondBranchToSimpleCond:
14378 //    For a block which has an unconditional branch, look to see if its target block
14379 //    is a good candidate for tail duplication, and if so do that duplication.
14380 //
14381 // Args:
14382 //    block  - block with uncond branch
14383 //    target - block which is target of first block
14384 //
14385 // returns: true if changes were made
14386
14387 bool Compiler::fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* target)
14388 {
14389     assert(block->bbJumpKind == BBJ_ALWAYS);
14390     assert(block->bbJumpDest == target);
14391
14392     // TODO-Review: OK if they are in the same region?
14393     if (compHndBBtabCount > 0)
14394     {
14395         return false;
14396     }
14397
14398     if (!fgBlockIsGoodTailDuplicationCandidate(target))
14399     {
14400         return false;
14401     }
14402
14403     if (!fgBlockEndFavorsTailDuplication(block))
14404     {
14405         return false;
14406     }
14407
14408     // NOTE: we do not currently hit this assert because this function is only called when
14409     // `fgUpdateFlowGraph` has been called with `doTailDuplication` set to true, and the
14410     // backend always calls `fgUpdateFlowGraph` with `doTailDuplication` set to false.
14411     assert(!block->IsLIR());
14412
14413     GenTreeStmt* stmt = target->FirstNonPhiDef();
14414     assert(stmt == target->lastStmt());
14415
14416     // Duplicate the target block at the end of this block
14417
14418     GenTree* cloned = gtCloneExpr(stmt->gtStmtExpr);
14419     noway_assert(cloned);
14420     GenTree* jmpStmt = gtNewStmt(cloned);
14421
14422     block->bbJumpKind = BBJ_COND;
14423     block->bbJumpDest = target->bbJumpDest;
14424     fgAddRefPred(block->bbJumpDest, block);
14425     fgRemoveRefPred(target, block);
14426
14427     // add an unconditional block after this block to jump to the target block's fallthrough block
14428
14429     BasicBlock* next = fgNewBBafter(BBJ_ALWAYS, block, true);
14430
14431     // The new block 'next' will inherit its weight from 'block'
14432     next->inheritWeight(block);
14433     next->bbJumpDest = target->bbNext;
14434     target->bbNext->bbFlags |= BBF_JMP_TARGET;
14435     fgAddRefPred(next, block);
14436     fgAddRefPred(next->bbJumpDest, next);
14437
14438 #ifdef DEBUG
14439     if (verbose)
14440     {
14441         printf("fgOptimizeUncondBranchToSimpleCond(from BB%02u to cond BB%02u), created new uncond BB%02u\n",
14442                block->bbNum, target->bbNum, next->bbNum);
14443     }
14444 #endif // DEBUG
14445
14446     if (fgStmtListThreaded)
14447     {
14448         gtSetStmtInfo(jmpStmt);
14449     }
14450
14451     fgInsertStmtAtEnd(block, jmpStmt);
14452
14453     return true;
14454 }
14455
14456 // fgOptimizeBranchToNext:
14457 //    Optimize a block which has a branch to the following block
14458 // Args:
14459 //    block - block with a branch
14460 //    bNext - block which is both next and the target of the first block
14461 //    bPrev - block which is prior to the first block
14462 //
14463 // returns: true if changes were made
14464 //
14465 bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev)
14466 {
14467     assert(block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS);
14468     assert(block->bbJumpDest == bNext);
14469     assert(block->bbNext == bNext);
14470     assert(block->bbPrev == bPrev);
14471
14472     if (block->bbJumpKind == BBJ_ALWAYS)
14473     {
14474         // We can't remove it if it is a branch from hot => cold
14475         if (!fgInDifferentRegions(block, bNext))
14476         {
14477             // We can't remove if it is marked as BBF_KEEP_BBJ_ALWAYS
14478             if (!(block->bbFlags & BBF_KEEP_BBJ_ALWAYS))
14479             {
14480                 // We can't remove if the BBJ_ALWAYS is part of a BBJ_CALLFINALLY pair
14481                 if ((bPrev == nullptr) || !bPrev->isBBCallAlwaysPair())
14482                 {
14483                     /* the unconditional jump is to the next BB  */
14484                     block->bbJumpKind = BBJ_NONE;
14485                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
14486 #ifdef DEBUG
14487                     if (verbose)
14488                     {
14489                         printf("\nRemoving unconditional jump to next block (BB%02u -> BB%02u) (converted BB%02u to "
14490                                "fall-through)\n",
14491                                block->bbNum, bNext->bbNum, block->bbNum);
14492                     }
14493 #endif // DEBUG
14494                     return true;
14495                 }
14496             }
14497         }
14498     }
14499     else
14500     {
14501         /* remove the conditional statement at the end of block */
14502         noway_assert(block->bbJumpKind == BBJ_COND);
14503         noway_assert(block->bbTreeList);
14504
14505 #ifdef DEBUG
14506         if (verbose)
14507         {
14508             printf("\nRemoving conditional jump to next block (BB%02u -> BB%02u)\n", block->bbNum, bNext->bbNum);
14509         }
14510 #endif // DEBUG
14511
14512         if (block->IsLIR())
14513         {
14514             LIR::Range& blockRange = LIR::AsRange(block);
14515             GenTree*    jmp        = blockRange.LastNode();
14516             assert(jmp->OperIsConditionalJump());
14517             if (jmp->OperGet() == GT_JTRUE)
14518             {
14519                 jmp->gtOp.gtOp1->gtFlags &= ~GTF_SET_FLAGS;
14520             }
14521
14522             bool               isClosed;
14523             unsigned           sideEffects;
14524             LIR::ReadOnlyRange jmpRange = blockRange.GetTreeRange(jmp, &isClosed, &sideEffects);
14525
14526             // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable
14527             //            diffs compared to the existing backend.
14528             if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0))
14529             {
14530                 // If the jump and its operands form a contiguous, side-effect-free range,
14531                 // remove them.
14532                 blockRange.Delete(this, block, std::move(jmpRange));
14533             }
14534             else
14535             {
14536                 // Otherwise, just remove the jump node itself.
14537                 blockRange.Remove(jmp, true);
14538             }
14539         }
14540         else
14541         {
14542             GenTreeStmt* cond = block->lastStmt();
14543             noway_assert(cond->gtStmtExpr->gtOper == GT_JTRUE);
14544
14545             /* check for SIDE_EFFECTS */
14546             if (cond->gtStmtExpr->gtFlags & GTF_SIDE_EFFECT)
14547             {
14548                 /* Extract the side effects from the conditional */
14549                 GenTree* sideEffList = nullptr;
14550
14551                 gtExtractSideEffList(cond->gtStmtExpr, &sideEffList);
14552
14553                 if (sideEffList == nullptr)
14554                 {
14555                     compCurBB = block;
14556                     fgRemoveStmt(block, cond);
14557                 }
14558                 else
14559                 {
14560                     noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
14561 #ifdef DEBUG
14562                     if (verbose)
14563                     {
14564                         printf("\nConditional has side effects! Extracting side effects...\n");
14565                         gtDispTree(cond);
14566                         printf("\n");
14567                         gtDispTree(sideEffList);
14568                         printf("\n");
14569                     }
14570 #endif // DEBUG
14571
14572                     /* Replace the conditional statement with the list of side effects */
14573                     noway_assert(sideEffList->gtOper != GT_STMT);
14574                     noway_assert(sideEffList->gtOper != GT_JTRUE);
14575
14576                     cond->gtStmtExpr = sideEffList;
14577
14578                     if (fgStmtListThreaded)
14579                     {
14580                         /* Update the lclvar ref counts */
14581                         compCurBB = block;
14582                         fgUpdateRefCntForExtract(cond->gtStmtExpr, sideEffList);
14583
14584                         /* Update ordering, costs, FP levels, etc. */
14585                         gtSetStmtInfo(cond);
14586
14587                         /* Re-link the nodes for this statement */
14588                         fgSetStmtSeq(cond);
14589                     }
14590                 }
14591             }
14592             else
14593             {
14594                 compCurBB = block;
14595                 /* conditional has NO side effect - remove it */
14596                 fgRemoveStmt(block, cond);
14597             }
14598         }
14599
14600         /* Conditional is gone - simply fall into the next block */
14601
14602         block->bbJumpKind = BBJ_NONE;
14603         block->bbFlags &= ~BBF_NEEDS_GCPOLL;
14604
14605         /* Update bbRefs and bbNum - Conditional predecessors to the same
14606          * block are counted twice so we have to remove one of them */
14607
14608         noway_assert(bNext->countOfInEdges() > 1);
14609         fgRemoveRefPred(bNext, block);
14610
14611         return true;
14612     }
14613     return false;
14614 }
14615
14616 /*****************************************************************************
14617  *
14618  *  Function called to optimize an unconditional branch that branches
14619  *  to a conditional branch.
14620  *  Currently we require that the conditional branch jump back to the
14621  *  block that follows the unconditional branch.
14622  *
14623  *  We can improve the code execution and layout by concatenating a copy
14624  *  of the conditional branch block at the end of the conditional branch
14625  *  and reversing the sense of the branch.
14626  *
14627  *  This is only done when the amount of code to be copied is smaller than
14628  *  our calculated threshold in maxDupCostSz.
14629  *
14630  */
14631
14632 bool Compiler::fgOptimizeBranch(BasicBlock* bJump)
14633 {
14634     if (opts.MinOpts())
14635     {
14636         return false;
14637     }
14638
14639     if (bJump->bbJumpKind != BBJ_ALWAYS)
14640     {
14641         return false;
14642     }
14643
14644     if (bJump->bbFlags & BBF_KEEP_BBJ_ALWAYS)
14645     {
14646         return false;
14647     }
14648
14649     // Don't hoist a conditional branch into the scratch block; we'd prefer it stay
14650     // either BBJ_NONE or BBJ_ALWAYS.
14651     if (fgBBisScratch(bJump))
14652     {
14653         return false;
14654     }
14655
14656     BasicBlock* bDest = bJump->bbJumpDest;
14657
14658     if (bDest->bbJumpKind != BBJ_COND)
14659     {
14660         return false;
14661     }
14662
14663     if (bDest->bbJumpDest != bJump->bbNext)
14664     {
14665         return false;
14666     }
14667
14668     // 'bJump' must be in the same try region as the condition, since we're going to insert
14669     // a duplicated condition in 'bJump', and the condition might include exception throwing code.
14670     if (!BasicBlock::sameTryRegion(bJump, bDest))
14671     {
14672         return false;
14673     }
14674
14675     // do not jump into another try region
14676     BasicBlock* bDestNext = bDest->bbNext;
14677     if (bDestNext->hasTryIndex() && !BasicBlock::sameTryRegion(bJump, bDestNext))
14678     {
14679         return false;
14680     }
14681
14682     // This function is only called by fgReorderBlocks, which we do not run in the backend.
14683     // If we wanted to run block reordering in the backend, we would need to be able to
14684     // calculate cost information for LIR on a per-node basis in order for this function
14685     // to work.
14686     assert(!bJump->IsLIR());
14687     assert(!bDest->IsLIR());
14688
14689     GenTreeStmt* stmt;
14690     unsigned     estDupCostSz = 0;
14691     for (stmt = bDest->firstStmt(); stmt; stmt = stmt->gtNextStmt)
14692     {
14693         GenTree* expr = stmt->gtStmtExpr;
14694
14695         /* We call gtPrepareCost to measure the cost of duplicating this tree */
14696         gtPrepareCost(expr);
14697
14698         estDupCostSz += expr->gtCostSz;
14699     }
14700
14701     bool                 allProfileWeightsAreValid = false;
14702     BasicBlock::weight_t weightJump                = bJump->bbWeight;
14703     BasicBlock::weight_t weightDest                = bDest->bbWeight;
14704     BasicBlock::weight_t weightNext                = bJump->bbNext->bbWeight;
14705     bool                 rareJump                  = bJump->isRunRarely();
14706     bool                 rareDest                  = bDest->isRunRarely();
14707     bool                 rareNext                  = bJump->bbNext->isRunRarely();
14708
14709     // If we have profile data then we calculate the number of time
14710     // the loop will iterate into loopIterations
14711     if (fgIsUsingProfileWeights())
14712     {
14713         // Only rely upon the profile weight when all three of these blocks
14714         // have either good profile weights or are rarelyRun
14715         //
14716         if ((bJump->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)) &&
14717             (bDest->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)) &&
14718             (bJump->bbNext->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)))
14719         {
14720             allProfileWeightsAreValid = true;
14721
14722             if ((weightJump * 100) < weightDest)
14723             {
14724                 rareJump = true;
14725             }
14726
14727             if ((weightNext * 100) < weightDest)
14728             {
14729                 rareNext = true;
14730             }
14731
14732             if (((weightDest * 100) < weightJump) && ((weightDest * 100) < weightNext))
14733             {
14734                 rareDest = true;
14735             }
14736         }
14737     }
14738
14739     unsigned maxDupCostSz = 6;
14740
14741     //
14742     // Branches between the hot and rarely run regions
14743     // should be minimized.  So we allow a larger size
14744     //
14745     if (rareDest != rareJump)
14746     {
14747         maxDupCostSz += 6;
14748     }
14749
14750     if (rareDest != rareNext)
14751     {
14752         maxDupCostSz += 6;
14753     }
14754
14755     //
14756     // We we are ngen-ing:
14757     // If the uncondional branch is a rarely run block then
14758     // we are willing to have more code expansion since we
14759     // won't be running code from this page
14760     //
14761     if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
14762     {
14763         if (rareJump)
14764         {
14765             maxDupCostSz *= 2;
14766         }
14767     }
14768
14769     // If the compare has too high cost then we don't want to dup
14770
14771     bool costIsTooHigh = (estDupCostSz > maxDupCostSz);
14772
14773 #ifdef DEBUG
14774     if (verbose)
14775     {
14776         printf("\nDuplication of the conditional block BB%02u (always branch from BB%02u) %s, because the cost of "
14777                "duplication (%i) is %s than %i,"
14778                " validProfileWeights = %s\n",
14779                bDest->bbNum, bJump->bbNum, costIsTooHigh ? "not done" : "performed", estDupCostSz,
14780                costIsTooHigh ? "greater" : "less or equal", maxDupCostSz, allProfileWeightsAreValid ? "true" : "false");
14781     }
14782 #endif // DEBUG
14783
14784     if (costIsTooHigh)
14785     {
14786         return false;
14787     }
14788
14789     /* Looks good - duplicate the conditional block */
14790
14791     GenTree* newStmtList     = nullptr; // new stmt list to be added to bJump
14792     GenTree* newStmtLast     = nullptr;
14793     bool     cloneExprFailed = false;
14794
14795     /* Visit all the statements in bDest */
14796
14797     for (GenTree* curStmt = bDest->bbTreeList; curStmt; curStmt = curStmt->gtNext)
14798     {
14799         /* Clone/substitute the expression */
14800
14801         stmt = gtCloneExpr(curStmt)->AsStmt();
14802
14803         // cloneExpr doesn't handle everything
14804
14805         if (stmt == nullptr)
14806         {
14807             cloneExprFailed = true;
14808             break;
14809         }
14810
14811         /* Append the expression to our list */
14812
14813         if (newStmtList != nullptr)
14814         {
14815             newStmtLast->gtNext = stmt;
14816         }
14817         else
14818         {
14819             newStmtList = stmt;
14820         }
14821
14822         stmt->gtPrev = newStmtLast;
14823         newStmtLast  = stmt;
14824     }
14825
14826     if (cloneExprFailed)
14827     {
14828         return false;
14829     }
14830
14831     noway_assert(newStmtLast != nullptr);
14832     noway_assert(stmt != nullptr);
14833     noway_assert(stmt->gtOper == GT_STMT);
14834
14835     if ((newStmtLast == nullptr) || (stmt == nullptr) || (stmt->gtOper != GT_STMT))
14836     {
14837         return false;
14838     }
14839
14840     /* Get to the condition node from the statement tree */
14841
14842     GenTree* condTree = stmt->gtStmtExpr;
14843     noway_assert(condTree->gtOper == GT_JTRUE);
14844
14845     if (condTree->gtOper != GT_JTRUE)
14846     {
14847         return false;
14848     }
14849
14850     //
14851     // Set condTree to the operand to the GT_JTRUE
14852     //
14853     condTree = condTree->gtOp.gtOp1;
14854
14855     //
14856     // This condTree has to be a RelOp comparison
14857     //
14858     if (condTree->OperIsCompare() == false)
14859     {
14860         return false;
14861     }
14862
14863     // Bump up the ref-counts of any variables in 'stmt'
14864     fgUpdateRefCntForClone(bJump, stmt->gtStmtExpr);
14865
14866     //
14867     // Find the last statement in the bJump block
14868     //
14869     GenTreeStmt* lastStmt = nullptr;
14870     for (stmt = bJump->firstStmt(); stmt; stmt = stmt->gtNextStmt)
14871     {
14872         lastStmt = stmt;
14873     }
14874     stmt = bJump->firstStmt();
14875
14876     /* Join the two linked lists */
14877     newStmtLast->gtNext = nullptr;
14878
14879     if (lastStmt != nullptr)
14880     {
14881         stmt->gtPrev        = newStmtLast;
14882         lastStmt->gtNext    = newStmtList;
14883         newStmtList->gtPrev = lastStmt;
14884     }
14885     else
14886     {
14887         bJump->bbTreeList   = newStmtList;
14888         newStmtList->gtPrev = newStmtLast;
14889     }
14890
14891     //
14892     // Reverse the sense of the compare
14893     //
14894     gtReverseCond(condTree);
14895
14896     // We need to update the following flags of the bJump block if they were set in the bDest block
14897     bJump->bbFlags |=
14898         (bDest->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_VTABREF));
14899
14900     bJump->bbJumpKind = BBJ_COND;
14901     bJump->bbJumpDest = bDest->bbNext;
14902
14903     /* Mark the jump dest block as being a jump target */
14904     bJump->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
14905
14906     /* Update bbRefs and bbPreds */
14907
14908     // bJump now falls through into the next block
14909     //
14910     fgAddRefPred(bJump->bbNext, bJump);
14911
14912     // bJump no longer jumps to bDest
14913     //
14914     fgRemoveRefPred(bDest, bJump);
14915
14916     // bJump now jumps to bDest->bbNext
14917     //
14918     fgAddRefPred(bDest->bbNext, bJump);
14919
14920     if (weightJump > 0)
14921     {
14922         if (allProfileWeightsAreValid)
14923         {
14924             if (weightDest > weightJump)
14925             {
14926                 bDest->bbWeight = (weightDest - weightJump);
14927             }
14928             else if (!bDest->isRunRarely())
14929             {
14930                 bDest->bbWeight = BB_UNITY_WEIGHT;
14931             }
14932         }
14933         else
14934         {
14935             BasicBlock::weight_t newWeightDest    = 0;
14936             BasicBlock::weight_t unloopWeightDest = 0;
14937
14938             if (weightDest > weightJump)
14939             {
14940                 newWeightDest = (weightDest - weightJump);
14941             }
14942             if (weightDest >= (BB_LOOP_WEIGHT * BB_UNITY_WEIGHT) / 2)
14943             {
14944                 newWeightDest = (weightDest * 2) / (BB_LOOP_WEIGHT * BB_UNITY_WEIGHT);
14945             }
14946             if ((newWeightDest > 0) || (unloopWeightDest > 0))
14947             {
14948                 bDest->bbWeight = Max(newWeightDest, unloopWeightDest);
14949             }
14950         }
14951     }
14952
14953 #if DEBUG
14954     if (verbose)
14955     {
14956         // Dump out the newStmtList that we created
14957         printf("\nfgOptimizeBranch added these statements(s) at the end of BB%02u:\n", bJump->bbNum);
14958         for (stmt = newStmtList->AsStmt(); stmt; stmt = stmt->gtNextStmt)
14959         {
14960             gtDispTree(stmt);
14961         }
14962         printf("\nfgOptimizeBranch changed block BB%02u from BBJ_ALWAYS to BBJ_COND.\n", bJump->bbNum);
14963
14964         printf("\nAfter this change in fgOptimizeBranch the BB graph is:");
14965         fgDispBasicBlocks(verboseTrees);
14966         printf("\n");
14967     }
14968 #endif // DEBUG
14969
14970     return true;
14971 }
14972
14973 /*****************************************************************************
14974  *
14975  *  Function called to optimize switch statements
14976  */
14977
14978 bool Compiler::fgOptimizeSwitchJumps()
14979 {
14980     bool result = false; // Our return value
14981
14982 #if 0
14983     // TODO-CQ: Add switch jump optimizations?
14984     if (!fgHasSwitch)
14985         return false;
14986
14987     if (!fgHaveValidEdgeWeights)
14988         return false;
14989
14990     for (BasicBlock* bSrc = fgFirstBB; bSrc != NULL; bSrc = bSrc->bbNext)
14991     {
14992         if (bSrc->bbJumpKind == BBJ_SWITCH)
14993         {
14994             unsigned        jumpCnt; jumpCnt = bSrc->bbJumpSwt->bbsCount;
14995             BasicBlock**    jumpTab; jumpTab = bSrc->bbJumpSwt->bbsDstTab;
14996
14997             do
14998             {
14999                 BasicBlock*   bDst       = *jumpTab;
15000                 flowList*     edgeToDst  = fgGetPredForBlock(bDst, bSrc);
15001                 double        outRatio   = (double) edgeToDst->flEdgeWeightMin  / (double) bSrc->bbWeight;
15002
15003                 if (outRatio >= 0.60)
15004                 {
15005                     // straighten switch here...
15006                 }
15007             }
15008             while (++jumpTab, --jumpCnt);
15009         }
15010     }
15011 #endif
15012
15013     return result;
15014 }
15015
15016 #ifdef _PREFAST_
15017 #pragma warning(push)
15018 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
15019 #endif
15020 /*****************************************************************************
15021  *
15022  *  Function called to reorder the flowgraph of BasicBlocks such that any
15023  *  rarely run blocks are placed at the end of the block list.
15024  *  If we have profile information we also use that information to reverse
15025  *  all conditional jumps that would benefit.
15026  */
15027
15028 void Compiler::fgReorderBlocks()
15029 {
15030     noway_assert(opts.compDbgCode == false);
15031
15032 #if FEATURE_EH_FUNCLETS
15033     assert(fgFuncletsCreated);
15034 #endif // FEATURE_EH_FUNCLETS
15035
15036     // We can't relocate anything if we only have one block
15037     if (fgFirstBB->bbNext == nullptr)
15038     {
15039         return;
15040     }
15041
15042     bool newRarelyRun      = false;
15043     bool movedBlocks       = false;
15044     bool optimizedSwitches = false;
15045
15046     // First let us expand the set of run rarely blocks
15047     newRarelyRun |= fgExpandRarelyRunBlocks();
15048
15049 #if !FEATURE_EH_FUNCLETS
15050     movedBlocks |= fgRelocateEHRegions();
15051 #endif // !FEATURE_EH_FUNCLETS
15052
15053     //
15054     // If we are using profile weights we can change some
15055     // switch jumps into conditional test and jump
15056     //
15057     if (fgIsUsingProfileWeights())
15058     {
15059         //
15060         // Note that this is currently not yet implemented
15061         //
15062         optimizedSwitches = fgOptimizeSwitchJumps();
15063         if (optimizedSwitches)
15064         {
15065             fgUpdateFlowGraph();
15066         }
15067     }
15068
15069 #ifdef DEBUG
15070     if (verbose)
15071     {
15072         printf("*************** In fgReorderBlocks()\n");
15073
15074         printf("\nInitial BasicBlocks");
15075         fgDispBasicBlocks(verboseTrees);
15076         printf("\n");
15077     }
15078 #endif // DEBUG
15079
15080     BasicBlock* bNext;
15081     BasicBlock* bPrev;
15082     BasicBlock* block;
15083     unsigned    XTnum;
15084     EHblkDsc*   HBtab;
15085
15086     // Iterate over every block, remembering our previous block in bPrev
15087     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
15088     {
15089         //
15090         // Consider relocating the rarely run blocks such that they are at the end of the method.
15091         // We also consider reversing conditional branches so that they become a not taken forwards branch.
15092         //
15093
15094         // If block is marked with a BBF_KEEP_BBJ_ALWAYS flag then we don't move the block
15095         if ((block->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)
15096         {
15097             continue;
15098         }
15099
15100         // Finally and handlers blocks are to be kept contiguous.
15101         // TODO-CQ: Allow reordering within the handler region
15102         if (block->hasHndIndex() == true)
15103         {
15104             continue;
15105         }
15106
15107         bool        reorderBlock   = true; // This is set to false if we decide not to reorder 'block'
15108         bool        isRare         = block->isRunRarely();
15109         BasicBlock* bDest          = nullptr;
15110         bool        forwardBranch  = false;
15111         bool        backwardBranch = false;
15112
15113         // Setup bDest
15114         if ((bPrev->bbJumpKind == BBJ_COND) || (bPrev->bbJumpKind == BBJ_ALWAYS))
15115         {
15116             bDest          = bPrev->bbJumpDest;
15117             forwardBranch  = fgIsForwardBranch(bPrev);
15118             backwardBranch = !forwardBranch;
15119         }
15120
15121         // We will look for bPrev as a non rarely run block followed by block as a rarely run block
15122         //
15123         if (bPrev->isRunRarely())
15124         {
15125             reorderBlock = false;
15126         }
15127
15128         // If the weights of the bPrev, block and bDest were all obtained from a profile run
15129         // then we can use them to decide if it is useful to reverse this conditional branch
15130
15131         BasicBlock::weight_t profHotWeight = -1;
15132
15133         if (bPrev->hasProfileWeight() && block->hasProfileWeight() && ((bDest == nullptr) || bDest->hasProfileWeight()))
15134         {
15135             //
15136             // All blocks have profile information
15137             //
15138             if (forwardBranch)
15139             {
15140                 if (bPrev->bbJumpKind == BBJ_ALWAYS)
15141                 {
15142                     // We can pull up the blocks that the unconditional jump branches to
15143                     // if the weight of bDest is greater or equal to the weight of block
15144                     // also the weight of bDest can't be zero.
15145                     //
15146                     if ((bDest->bbWeight < block->bbWeight) || (bDest->bbWeight == 0))
15147                     {
15148                         reorderBlock = false;
15149                     }
15150                     else
15151                     {
15152                         //
15153                         // If this remains true then we will try to pull up bDest to succeed bPrev
15154                         //
15155                         bool moveDestUp = true;
15156
15157                         if (fgHaveValidEdgeWeights)
15158                         {
15159                             //
15160                             // The edge bPrev -> bDest must have a higher minimum weight
15161                             // than every other edge into bDest
15162                             //
15163                             flowList* edgeFromPrev = fgGetPredForBlock(bDest, bPrev);
15164                             noway_assert(edgeFromPrev != nullptr);
15165
15166                             // Examine all of the other edges into bDest
15167                             for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext)
15168                             {
15169                                 if (edge != edgeFromPrev)
15170                                 {
15171                                     if (edge->flEdgeWeightMax >= edgeFromPrev->flEdgeWeightMin)
15172                                     {
15173                                         moveDestUp = false;
15174                                         break;
15175                                     }
15176                                 }
15177                             }
15178                         }
15179                         else
15180                         {
15181                             //
15182                             // The block bPrev must have a higher weight
15183                             // than every other block that goes into bDest
15184                             //
15185
15186                             // Examine all of the other edges into bDest
15187                             for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext)
15188                             {
15189                                 BasicBlock* bTemp = edge->flBlock;
15190
15191                                 if ((bTemp != bPrev) && (bTemp->bbWeight >= bPrev->bbWeight))
15192                                 {
15193                                     moveDestUp = false;
15194                                     break;
15195                                 }
15196                             }
15197                         }
15198
15199                         // Are we still good to move bDest up to bPrev?
15200                         if (moveDestUp)
15201                         {
15202                             //
15203                             // We will consider all blocks that have less weight than profHotWeight to be
15204                             // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest
15205                             //
15206                             profHotWeight = bDest->bbWeight - 1;
15207                         }
15208                         else
15209                         {
15210                             if (block->isRunRarely())
15211                             {
15212                                 // We will move any rarely run blocks blocks
15213                                 profHotWeight = 0;
15214                             }
15215                             else
15216                             {
15217                                 // We will move all blocks that have a weight less or equal to our fall through block
15218                                 profHotWeight = block->bbWeight + 1;
15219                             }
15220                             // But we won't try to connect with bDest
15221                             bDest = nullptr;
15222                         }
15223                     }
15224                 }
15225                 else // (bPrev->bbJumpKind == BBJ_COND)
15226                 {
15227                     noway_assert(bPrev->bbJumpKind == BBJ_COND);
15228                     //
15229                     // We will reverse branch if the taken-jump to bDest ratio (i.e. 'takenRatio')
15230                     // is more than 51%
15231                     //
15232                     // We will setup profHotWeight to be maximum bbWeight that a block
15233                     // could have for us not to want to reverse the conditional branch
15234                     //
15235                     // We will consider all blocks that have less weight than profHotWeight to be
15236                     // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest
15237                     //
15238                     if (fgHaveValidEdgeWeights)
15239                     {
15240                         // We have valid edge weights, however even with valid edge weights
15241                         // we may have a minimum and maximum range for each edges value
15242                         //
15243                         // We will check that the min weight of the bPrev to bDest edge
15244                         //  is more than twice the max weight of the bPrev to block edge.
15245                         //
15246                         //                  bPrev -->   [BB04, weight 31]
15247                         //                                     |         \
15248                         //          edgeToBlock -------------> O          \
15249                         //          [min=8,max=10]             V           \
15250                         //                  block -->   [BB05, weight 10]   \
15251                         //                                                   \
15252                         //          edgeToDest ----------------------------> O
15253                         //          [min=21,max=23]                          |
15254                         //                                                   V
15255                         //                  bDest --------------->   [BB08, weight 21]
15256                         //
15257                         flowList* edgeToDest  = fgGetPredForBlock(bDest, bPrev);
15258                         flowList* edgeToBlock = fgGetPredForBlock(block, bPrev);
15259                         noway_assert(edgeToDest != nullptr);
15260                         noway_assert(edgeToBlock != nullptr);
15261                         //
15262                         // Calculate the taken ratio
15263                         //   A takenRation of 0.10 means taken 10% of the time, not taken 90% of the time
15264                         //   A takenRation of 0.50 means taken 50% of the time, not taken 50% of the time
15265                         //   A takenRation of 0.90 means taken 90% of the time, not taken 10% of the time
15266                         //
15267                         double takenCount =
15268                             ((double)edgeToDest->flEdgeWeightMin + (double)edgeToDest->flEdgeWeightMax) / 2.0;
15269                         double notTakenCount =
15270                             ((double)edgeToBlock->flEdgeWeightMin + (double)edgeToBlock->flEdgeWeightMax) / 2.0;
15271                         double totalCount = takenCount + notTakenCount;
15272                         double takenRatio = takenCount / totalCount;
15273
15274                         // If the takenRatio is greater or equal to 51% then we will reverse the branch
15275                         if (takenRatio < 0.51)
15276                         {
15277                             reorderBlock = false;
15278                         }
15279                         else
15280                         {
15281                             // set profHotWeight
15282                             profHotWeight = (edgeToBlock->flEdgeWeightMin + edgeToBlock->flEdgeWeightMax) / 2 - 1;
15283                         }
15284                     }
15285                     else
15286                     {
15287                         // We don't have valid edge weight so we will be more conservative
15288                         // We could have bPrev, block or bDest as part of a loop and thus have extra weight
15289                         //
15290                         // We will do two checks:
15291                         //   1. Check that the weight of bDest is at least two times more than block
15292                         //   2. Check that the weight of bPrev is at least three times more than block
15293                         //
15294                         //                  bPrev -->   [BB04, weight 31]
15295                         //                                     |         \
15296                         //                                     V          \
15297                         //                  block -->   [BB05, weight 10]  \
15298                         //                                                  \
15299                         //                                                  |
15300                         //                                                  V
15301                         //                  bDest --------------->   [BB08, weight 21]
15302                         //
15303                         //  For this case weightDest is calculated as (21+1)/2  or 11
15304                         //            and weightPrev is calculated as (31+2)/3  also 11
15305                         //
15306                         //  Generally both weightDest and weightPrev should calculate
15307                         //  the same value unless bPrev or bDest are part of a loop
15308                         //
15309                         BasicBlock::weight_t weightDest =
15310                             bDest->isMaxBBWeight() ? bDest->bbWeight : (bDest->bbWeight + 1) / 2;
15311                         BasicBlock::weight_t weightPrev =
15312                             bPrev->isMaxBBWeight() ? bPrev->bbWeight : (bPrev->bbWeight + 2) / 3;
15313
15314                         // select the lower of weightDest and weightPrev
15315                         profHotWeight = (weightDest < weightPrev) ? weightDest : weightPrev;
15316
15317                         // if the weight of block is greater (or equal) to profHotWeight then we don't reverse the cond
15318                         if (block->bbWeight >= profHotWeight)
15319                         {
15320                             reorderBlock = false;
15321                         }
15322                     }
15323                 }
15324             }
15325             else // not a forwardBranch
15326             {
15327                 if (bPrev->bbFallsThrough())
15328                 {
15329                     goto CHECK_FOR_RARE;
15330                 }
15331
15332                 // Here we should pull up the highest weight block remaining
15333                 // and place it here since bPrev does not fall through.
15334
15335                 BasicBlock::weight_t highestWeight           = 0;
15336                 BasicBlock*          candidateBlock          = nullptr;
15337                 BasicBlock*          lastNonFallThroughBlock = bPrev;
15338                 BasicBlock*          bTmp                    = bPrev->bbNext;
15339
15340                 while (bTmp != nullptr)
15341                 {
15342                     // Don't try to split a Call/Always pair
15343                     //
15344                     if (bTmp->isBBCallAlwaysPair())
15345                     {
15346                         // Move bTmp forward
15347                         bTmp = bTmp->bbNext;
15348                     }
15349
15350                     //
15351                     // Check for loop exit condition
15352                     //
15353                     if (bTmp == nullptr)
15354                     {
15355                         break;
15356                     }
15357
15358                     //
15359                     // if its weight is the highest one we've seen and
15360                     //  the EH regions allow for us to place bTmp after bPrev
15361                     //
15362                     if ((bTmp->bbWeight > highestWeight) && fgEhAllowsMoveBlock(bPrev, bTmp))
15363                     {
15364                         // When we have a current candidateBlock that is a conditional (or unconditional) jump
15365                         // to bTmp (which is a higher weighted block) then it is better to keep out current
15366                         // candidateBlock and have it fall into bTmp
15367                         //
15368                         if ((candidateBlock == nullptr) ||
15369                             ((candidateBlock->bbJumpKind != BBJ_COND) && (candidateBlock->bbJumpKind != BBJ_ALWAYS)) ||
15370                             (candidateBlock->bbJumpDest != bTmp))
15371                         {
15372                             // otherwise we have a new candidateBlock
15373                             //
15374                             highestWeight  = bTmp->bbWeight;
15375                             candidateBlock = lastNonFallThroughBlock->bbNext;
15376                         }
15377                     }
15378
15379                     if ((bTmp->bbFallsThrough() == false) || (bTmp->bbWeight == 0))
15380                     {
15381                         lastNonFallThroughBlock = bTmp;
15382                     }
15383
15384                     bTmp = bTmp->bbNext;
15385                 }
15386
15387                 // If we didn't find a suitable block then skip this
15388                 if (highestWeight == 0)
15389                 {
15390                     reorderBlock = false;
15391                 }
15392                 else
15393                 {
15394                     noway_assert(candidateBlock != nullptr);
15395
15396                     // If the candidateBlock is the same a block then skip this
15397                     if (candidateBlock == block)
15398                     {
15399                         reorderBlock = false;
15400                     }
15401                     else
15402                     {
15403                         // Set bDest to the block that we want to come after bPrev
15404                         bDest = candidateBlock;
15405
15406                         // set profHotWeight
15407                         profHotWeight = highestWeight - 1;
15408                     }
15409                 }
15410             }
15411         }
15412         else // we don't have good profile info (or we are falling through)
15413         {
15414
15415         CHECK_FOR_RARE:;
15416
15417             /* We only want to reorder when we have a rarely run   */
15418             /* block right after a normal block,                   */
15419             /* (bPrev is known to be a normal block at this point) */
15420             if (!isRare)
15421             {
15422                 if ((bDest == block->bbNext) && (block->bbJumpKind == BBJ_RETURN) && (bPrev->bbJumpKind == BBJ_ALWAYS))
15423                 {
15424                     // This is a common case with expressions like "return Expr1 && Expr2" -- move the return
15425                     // to establish fall-through.
15426                 }
15427                 else
15428                 {
15429                     reorderBlock = false;
15430                 }
15431             }
15432             else
15433             {
15434                 /* If the jump target bDest is also a rarely run block then we don't want to do the reversal */
15435                 if (bDest && bDest->isRunRarely())
15436                 {
15437                     reorderBlock = false; /* Both block and bDest are rarely run */
15438                 }
15439                 else
15440                 {
15441                     // We will move any rarely run blocks blocks
15442                     profHotWeight = 0;
15443                 }
15444             }
15445         }
15446
15447         if (reorderBlock == false)
15448         {
15449             //
15450             // Check for an unconditional branch to a conditional branch
15451             // which also branches back to our next block
15452             //
15453             if (fgOptimizeBranch(bPrev))
15454             {
15455                 noway_assert(bPrev->bbJumpKind == BBJ_COND);
15456             }
15457             continue;
15458         }
15459
15460         //  Now we need to determine which blocks should be moved
15461         //
15462         //  We consider one of two choices:
15463         //
15464         //  1. Moving the fall-through blocks (or rarely run blocks) down to
15465         //     later in the method and hopefully connecting the jump dest block
15466         //     so that it becomes the fall through block
15467         //
15468         //  And when bDest in not NULL, we also consider:
15469         //
15470         //  2. Moving the bDest block (or blocks) up to bPrev
15471         //     so that it could be used as a fall through block
15472         //
15473         //  We will prefer option #1 if we are able to connect the jump dest
15474         //  block as the fall though block otherwise will we try to use option #2
15475         //
15476
15477         //
15478         //  Consider option #1: relocating blocks starting at 'block'
15479         //    to later in flowgraph
15480         //
15481         // We set bStart to the first block that will be relocated
15482         // and bEnd to the last block that will be relocated
15483
15484         BasicBlock* bStart   = block;
15485         BasicBlock* bEnd     = bStart;
15486         bNext                = bEnd->bbNext;
15487         bool connected_bDest = false;
15488
15489         if ((backwardBranch && !isRare) ||
15490             ((block->bbFlags & BBF_DONT_REMOVE) != 0)) // Don't choose option #1 when block is the start of a try region
15491         {
15492             bStart = nullptr;
15493             bEnd   = nullptr;
15494         }
15495         else
15496         {
15497             while (true)
15498             {
15499                 // Don't try to split a Call/Always pair
15500                 //
15501                 if (bEnd->isBBCallAlwaysPair())
15502                 {
15503                     // Move bEnd and bNext forward
15504                     bEnd  = bNext;
15505                     bNext = bNext->bbNext;
15506                 }
15507
15508                 //
15509                 // Check for loop exit condition
15510                 //
15511                 if (bNext == nullptr)
15512                 {
15513                     break;
15514                 }
15515
15516 #if FEATURE_EH_FUNCLETS
15517                 // Check if we've reached the funclets region, at the end of the function
15518                 if (fgFirstFuncletBB == bEnd->bbNext)
15519                 {
15520                     break;
15521                 }
15522 #endif // FEATURE_EH_FUNCLETS
15523
15524                 if (bNext == bDest)
15525                 {
15526                     connected_bDest = true;
15527                     break;
15528                 }
15529
15530                 // All the blocks must have the same try index
15531                 // and must not have the BBF_DONT_REMOVE flag set
15532
15533                 if (!BasicBlock::sameTryRegion(bStart, bNext) || ((bNext->bbFlags & BBF_DONT_REMOVE) != 0))
15534                 {
15535                     // exit the loop, bEnd is now set to the
15536                     // last block that we want to relocate
15537                     break;
15538                 }
15539
15540                 // If we are relocating rarely run blocks..
15541                 if (isRare)
15542                 {
15543                     // ... then all blocks must be rarely run
15544                     if (!bNext->isRunRarely())
15545                     {
15546                         // exit the loop, bEnd is now set to the
15547                         // last block that we want to relocate
15548                         break;
15549                     }
15550                 }
15551                 else
15552                 {
15553                     // If we are moving blocks that are hot then all
15554                     // of the blocks moved must be less than profHotWeight */
15555                     if (bNext->bbWeight >= profHotWeight)
15556                     {
15557                         // exit the loop, bEnd is now set to the
15558                         // last block that we would relocate
15559                         break;
15560                     }
15561                 }
15562
15563                 // Move bEnd and bNext forward
15564                 bEnd  = bNext;
15565                 bNext = bNext->bbNext;
15566             }
15567
15568             // Set connected_bDest to true if moving blocks [bStart .. bEnd]
15569             //  connects with the the jump dest of bPrev (i.e bDest) and
15570             // thus allows bPrev fall through instead of jump.
15571             if (bNext == bDest)
15572             {
15573                 connected_bDest = true;
15574             }
15575         }
15576
15577         //  Now consider option #2: Moving the jump dest block (or blocks)
15578         //    up to bPrev
15579         //
15580         // The variables bStart2, bEnd2 and bPrev2 are used for option #2
15581         //
15582         // We will setup bStart2 to the first block that will be relocated
15583         // and bEnd2 to the last block that will be relocated
15584         // and bPrev2 to be the lexical pred of bDest
15585         //
15586         // If after this calculation bStart2 is NULL we cannot use option #2,
15587         // otherwise bStart2, bEnd2 and bPrev2 are all non-NULL and we will use option #2
15588
15589         BasicBlock* bStart2 = nullptr;
15590         BasicBlock* bEnd2   = nullptr;
15591         BasicBlock* bPrev2  = nullptr;
15592
15593         // If option #1 didn't connect bDest and bDest isn't NULL
15594         if ((connected_bDest == false) && (bDest != nullptr) &&
15595             //  The jump target cannot be moved if it has the BBF_DONT_REMOVE flag set
15596             ((bDest->bbFlags & BBF_DONT_REMOVE) == 0))
15597         {
15598             // We will consider option #2: relocating blocks starting at 'bDest' to succeed bPrev
15599             //
15600             // setup bPrev2 to be the lexical pred of bDest
15601
15602             bPrev2 = block;
15603             while (bPrev2 != nullptr)
15604             {
15605                 if (bPrev2->bbNext == bDest)
15606                 {
15607                     break;
15608                 }
15609
15610                 bPrev2 = bPrev2->bbNext;
15611             }
15612
15613             if ((bPrev2 != nullptr) && fgEhAllowsMoveBlock(bPrev, bDest))
15614             {
15615                 // We have decided that relocating bDest to be after bPrev is best
15616                 // Set bStart2 to the first block that will be relocated
15617                 // and bEnd2 to the last block that will be relocated
15618                 //
15619                 // Assigning to bStart2 selects option #2
15620                 //
15621                 bStart2 = bDest;
15622                 bEnd2   = bStart2;
15623                 bNext   = bEnd2->bbNext;
15624
15625                 while (true)
15626                 {
15627                     // Don't try to split a Call/Always pair
15628                     //
15629                     if (bEnd2->isBBCallAlwaysPair())
15630                     {
15631                         noway_assert(bNext->bbJumpKind == BBJ_ALWAYS);
15632                         // Move bEnd2 and bNext forward
15633                         bEnd2 = bNext;
15634                         bNext = bNext->bbNext;
15635                     }
15636
15637                     // Check for the Loop exit conditions
15638
15639                     if (bNext == nullptr)
15640                     {
15641                         break;
15642                     }
15643
15644                     if (bEnd2->bbFallsThrough() == false)
15645                     {
15646                         break;
15647                     }
15648
15649                     // If we are relocating rarely run blocks..
15650                     // All the blocks must have the same try index,
15651                     // and must not have the BBF_DONT_REMOVE flag set
15652
15653                     if (!BasicBlock::sameTryRegion(bStart2, bNext) || ((bNext->bbFlags & BBF_DONT_REMOVE) != 0))
15654                     {
15655                         // exit the loop, bEnd2 is now set to the
15656                         // last block that we want to relocate
15657                         break;
15658                     }
15659
15660                     if (isRare)
15661                     {
15662                         /* ... then all blocks must not be rarely run */
15663                         if (bNext->isRunRarely())
15664                         {
15665                             // exit the loop, bEnd2 is now set to the
15666                             // last block that we want to relocate
15667                             break;
15668                         }
15669                     }
15670                     else
15671                     {
15672                         // If we are relocating hot blocks
15673                         // all blocks moved must be greater than profHotWeight
15674                         if (bNext->bbWeight <= profHotWeight)
15675                         {
15676                             // exit the loop, bEnd2 is now set to the
15677                             // last block that we want to relocate
15678                             break;
15679                         }
15680                     }
15681
15682                     // Move bEnd2 and bNext forward
15683                     bEnd2 = bNext;
15684                     bNext = bNext->bbNext;
15685                 }
15686             }
15687         }
15688
15689         // If we are using option #1 then ...
15690         if (bStart2 == nullptr)
15691         {
15692             // Don't use option #1 for a backwards branch
15693             if (bStart == nullptr)
15694             {
15695                 continue;
15696             }
15697
15698             // .... Don't move a set of blocks that are already at the end of the main method
15699             if (bEnd == fgLastBBInMainFunction())
15700             {
15701                 continue;
15702             }
15703         }
15704
15705 #ifdef DEBUG
15706         if (verbose)
15707         {
15708             if (bDest != nullptr)
15709             {
15710                 if (bPrev->bbJumpKind == BBJ_COND)
15711                 {
15712                     printf("Decided to reverse conditional branch at block BB%02u branch to BB%02u ", bPrev->bbNum,
15713                            bDest->bbNum);
15714                 }
15715                 else if (bPrev->bbJumpKind == BBJ_ALWAYS)
15716                 {
15717                     printf("Decided to straighten unconditional branch at block BB%02u branch to BB%02u ", bPrev->bbNum,
15718                            bDest->bbNum);
15719                 }
15720                 else
15721                 {
15722                     printf("Decided to place hot code after BB%02u, placed BB%02u after this block ", bPrev->bbNum,
15723                            bDest->bbNum);
15724                 }
15725
15726                 if (profHotWeight > 0)
15727                 {
15728                     printf("because of IBC profile data\n");
15729                 }
15730                 else
15731                 {
15732                     if (bPrev->bbFallsThrough())
15733                     {
15734                         printf("since it falls into a rarely run block\n");
15735                     }
15736                     else
15737                     {
15738                         printf("since it is succeeded by a rarely run block\n");
15739                     }
15740                 }
15741             }
15742             else
15743             {
15744                 printf("Decided to relocate block(s) after block BB%02u since they are %s block(s)\n", bPrev->bbNum,
15745                        block->isRunRarely() ? "rarely run" : "uncommonly run");
15746             }
15747         }
15748 #endif // DEBUG
15749
15750         // We will set insertAfterBlk to the block the precedes our insertion range
15751         // We will set bStartPrev to be the block that precedes the set of blocks that we are moving
15752         BasicBlock* insertAfterBlk;
15753         BasicBlock* bStartPrev;
15754
15755         if (bStart2 != nullptr)
15756         {
15757             // Option #2: relocating blocks starting at 'bDest' to follow bPrev
15758
15759             // Update bStart and bEnd so that we can use these two for all later operations
15760             bStart = bStart2;
15761             bEnd   = bEnd2;
15762
15763             // Set bStartPrev to be the block that comes before bStart
15764             bStartPrev = bPrev2;
15765
15766             // We will move [bStart..bEnd] to immediately after bPrev
15767             insertAfterBlk = bPrev;
15768         }
15769         else
15770         {
15771             // option #1: Moving the fall-through blocks (or rarely run blocks) down to later in the method
15772
15773             // Set bStartPrev to be the block that come before bStart
15774             bStartPrev = bPrev;
15775
15776             // We will move [bStart..bEnd] but we will pick the insert location later
15777             insertAfterBlk = nullptr;
15778         }
15779
15780         // We are going to move [bStart..bEnd] so they can't be NULL
15781         noway_assert(bStart != nullptr);
15782         noway_assert(bEnd != nullptr);
15783
15784         // bEnd can't be a BBJ_CALLFINALLY unless it is a RETLESS call
15785         noway_assert((bEnd->bbJumpKind != BBJ_CALLFINALLY) || (bEnd->bbFlags & BBF_RETLESS_CALL));
15786
15787         // bStartPrev must be set to the block that precedes bStart
15788         noway_assert(bStartPrev->bbNext == bStart);
15789
15790         // Since we will be unlinking [bStart..bEnd],
15791         // we need to compute and remember if bStart is in each of
15792         // the try and handler regions
15793         //
15794         bool* fStartIsInTry = nullptr;
15795         bool* fStartIsInHnd = nullptr;
15796
15797         if (compHndBBtabCount > 0)
15798         {
15799             fStartIsInTry = new (this, CMK_Unknown) bool[compHndBBtabCount];
15800             fStartIsInHnd = new (this, CMK_Unknown) bool[compHndBBtabCount];
15801
15802             for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
15803             {
15804                 fStartIsInTry[XTnum] = HBtab->InTryRegionBBRange(bStart);
15805                 fStartIsInHnd[XTnum] = HBtab->InHndRegionBBRange(bStart);
15806             }
15807         }
15808
15809         /* Temporarily unlink [bStart..bEnd] from the flow graph */
15810         fgUnlinkRange(bStart, bEnd);
15811
15812         if (insertAfterBlk == nullptr)
15813         {
15814             // Find new location for the unlinked block(s)
15815             // Set insertAfterBlk to the block which will precede the insertion point
15816
15817             if (!bStart->hasTryIndex() && isRare)
15818             {
15819                 // We'll just insert the blocks at the end of the method. If the method
15820                 // has funclets, we will insert at the end of the main method but before
15821                 // any of the funclets. Note that we create funclets before we call
15822                 // fgReorderBlocks().
15823
15824                 insertAfterBlk = fgLastBBInMainFunction();
15825                 noway_assert(insertAfterBlk != bPrev);
15826             }
15827             else
15828             {
15829                 BasicBlock* startBlk;
15830                 BasicBlock* lastBlk;
15831                 EHblkDsc*   ehDsc = ehInitTryBlockRange(bStart, &startBlk, &lastBlk);
15832
15833                 BasicBlock* endBlk;
15834
15835                 /* Setup startBlk and endBlk as the range to search */
15836
15837                 if (ehDsc != nullptr)
15838                 {
15839                     endBlk = lastBlk->bbNext;
15840
15841                     /*
15842                        Multiple (nested) try regions might start from the same BB.
15843                        For example,
15844
15845                        try3   try2   try1
15846                        |---   |---   |---   BB01
15847                        |      |      |      BB02
15848                        |      |      |---   BB03
15849                        |      |             BB04
15850                        |      |------------ BB05
15851                        |                    BB06
15852                        |------------------- BB07
15853
15854                        Now if we want to insert in try2 region, we will start with startBlk=BB01.
15855                        The following loop will allow us to start from startBlk==BB04.
15856                     */
15857                     while (!BasicBlock::sameTryRegion(startBlk, bStart) && (startBlk != endBlk))
15858                     {
15859                         startBlk = startBlk->bbNext;
15860                     }
15861
15862                     // startBlk cannot equal endBlk as it must come before endBlk
15863                     if (startBlk == endBlk)
15864                     {
15865                         goto CANNOT_MOVE;
15866                     }
15867
15868                     // we also can't start searching the try region at bStart
15869                     if (startBlk == bStart)
15870                     {
15871                         // if bEnd is the last block in the method or
15872                         // or if bEnd->bbNext is in a different try region
15873                         // then we cannot move the blocks
15874                         //
15875                         if ((bEnd->bbNext == nullptr) || !BasicBlock::sameTryRegion(startBlk, bEnd->bbNext))
15876                         {
15877                             goto CANNOT_MOVE;
15878                         }
15879
15880                         startBlk = bEnd->bbNext;
15881
15882                         // Check that the new startBlk still comes before endBlk
15883
15884                         // startBlk cannot equal endBlk as it must come before endBlk
15885                         if (startBlk == endBlk)
15886                         {
15887                             goto CANNOT_MOVE;
15888                         }
15889
15890                         BasicBlock* tmpBlk = startBlk;
15891                         while ((tmpBlk != endBlk) && (tmpBlk != nullptr))
15892                         {
15893                             tmpBlk = tmpBlk->bbNext;
15894                         }
15895
15896                         // when tmpBlk is NULL that means startBlk is after endBlk
15897                         // so there is no way to move bStart..bEnd within the try region
15898                         if (tmpBlk == nullptr)
15899                         {
15900                             goto CANNOT_MOVE;
15901                         }
15902                     }
15903                 }
15904                 else
15905                 {
15906                     noway_assert(isRare == false);
15907
15908                     /* We'll search through the entire main method */
15909                     startBlk = fgFirstBB;
15910                     endBlk   = fgEndBBAfterMainFunction();
15911                 }
15912
15913                 // Calculate nearBlk and jumpBlk and then call fgFindInsertPoint()
15914                 // to find our insertion block
15915                 //
15916                 {
15917                     // If the set of blocks that we are moving ends with a BBJ_ALWAYS to
15918                     // another [rarely run] block that comes after bPrev (forward branch)
15919                     // then we can set up nearBlk to eliminate this jump sometimes
15920                     //
15921                     BasicBlock* nearBlk = nullptr;
15922                     BasicBlock* jumpBlk = nullptr;
15923
15924                     if ((bEnd->bbJumpKind == BBJ_ALWAYS) && (!isRare || bEnd->bbJumpDest->isRunRarely()) &&
15925                         fgIsForwardBranch(bEnd, bPrev))
15926                     {
15927                         // Set nearBlk to be the block in [startBlk..endBlk]
15928                         // such that nearBlk->bbNext == bEnd->JumpDest
15929                         // if no such block exists then set nearBlk to NULL
15930                         nearBlk = startBlk;
15931                         jumpBlk = bEnd;
15932                         do
15933                         {
15934                             // We do not want to set nearBlk to bPrev
15935                             // since then we will not move [bStart..bEnd]
15936                             //
15937                             if (nearBlk != bPrev)
15938                             {
15939                                 // Check if nearBlk satisfies our requirement
15940                                 if (nearBlk->bbNext == bEnd->bbJumpDest)
15941                                 {
15942                                     break;
15943                                 }
15944                             }
15945
15946                             // Did we reach the endBlk?
15947                             if (nearBlk == endBlk)
15948                             {
15949                                 nearBlk = nullptr;
15950                                 break;
15951                             }
15952
15953                             // advance nearBlk to the next block
15954                             nearBlk = nearBlk->bbNext;
15955
15956                         } while (nearBlk != nullptr);
15957                     }
15958
15959                     // if nearBlk is NULL then we set nearBlk to be the
15960                     // first block that we want to insert after.
15961                     if (nearBlk == nullptr)
15962                     {
15963                         if (bDest != nullptr)
15964                         {
15965                             // we want to insert after bDest
15966                             nearBlk = bDest;
15967                         }
15968                         else
15969                         {
15970                             // we want to insert after bPrev
15971                             nearBlk = bPrev;
15972                         }
15973                     }
15974
15975                     /* Set insertAfterBlk to the block which we will insert after. */
15976
15977                     insertAfterBlk =
15978                         fgFindInsertPoint(bStart->bbTryIndex,
15979                                           true, // Insert in the try region.
15980                                           startBlk, endBlk, nearBlk, jumpBlk, bStart->bbWeight == BB_ZERO_WEIGHT);
15981                 }
15982
15983                 /* See if insertAfterBlk is the same as where we started, */
15984                 /*  or if we could not find any insertion point     */
15985
15986                 if ((insertAfterBlk == bPrev) || (insertAfterBlk == nullptr))
15987                 {
15988                 CANNOT_MOVE:;
15989                     /* We couldn't move the blocks, so put everything back */
15990                     /* relink [bStart .. bEnd] into the flow graph */
15991
15992                     bPrev->setNext(bStart);
15993                     if (bEnd->bbNext)
15994                     {
15995                         bEnd->bbNext->bbPrev = bEnd;
15996                     }
15997 #ifdef DEBUG
15998                     if (verbose)
15999                     {
16000                         if (bStart != bEnd)
16001                         {
16002                             printf("Could not relocate blocks (BB%02u .. BB%02u)\n", bStart->bbNum, bEnd->bbNum);
16003                         }
16004                         else
16005                         {
16006                             printf("Could not relocate block BB%02u\n", bStart->bbNum);
16007                         }
16008                     }
16009 #endif // DEBUG
16010                     continue;
16011                 }
16012             }
16013         }
16014
16015         noway_assert(insertAfterBlk != nullptr);
16016         noway_assert(bStartPrev != nullptr);
16017         noway_assert(bStartPrev != insertAfterBlk);
16018
16019 #ifdef DEBUG
16020         movedBlocks = true;
16021
16022         if (verbose)
16023         {
16024             const char* msg;
16025             if (bStart2 != nullptr)
16026             {
16027                 msg = "hot";
16028             }
16029             else
16030             {
16031                 if (isRare)
16032                 {
16033                     msg = "rarely run";
16034                 }
16035                 else
16036                 {
16037                     msg = "uncommon";
16038                 }
16039             }
16040
16041             printf("Relocated %s ", msg);
16042             if (bStart != bEnd)
16043             {
16044                 printf("blocks (BB%02u .. BB%02u)", bStart->bbNum, bEnd->bbNum);
16045             }
16046             else
16047             {
16048                 printf("block BB%02u", bStart->bbNum);
16049             }
16050
16051             if (bPrev->bbJumpKind == BBJ_COND)
16052             {
16053                 printf(" by reversing conditional jump at BB%02u\n", bPrev->bbNum);
16054             }
16055             else
16056             {
16057                 printf("\n", bPrev->bbNum);
16058             }
16059         }
16060 #endif // DEBUG
16061
16062         if (bPrev->bbJumpKind == BBJ_COND)
16063         {
16064             /* Reverse the bPrev jump condition */
16065             GenTree* condTest = bPrev->lastStmt();
16066
16067             condTest = condTest->gtStmt.gtStmtExpr;
16068             noway_assert(condTest->gtOper == GT_JTRUE);
16069
16070             condTest->gtOp.gtOp1 = gtReverseCond(condTest->gtOp.gtOp1);
16071
16072             if (bStart2 == nullptr)
16073             {
16074                 /* Set the new jump dest for bPrev to the rarely run or uncommon block(s) */
16075                 bPrev->bbJumpDest = bStart;
16076                 bStart->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
16077             }
16078             else
16079             {
16080                 noway_assert(insertAfterBlk == bPrev);
16081                 noway_assert(insertAfterBlk->bbNext == block);
16082
16083                 /* Set the new jump dest for bPrev to the rarely run or uncommon block(s) */
16084                 bPrev->bbJumpDest = block;
16085                 block->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
16086             }
16087         }
16088
16089         // If we are moving blocks that are at the end of a try or handler
16090         // we will need to shorten ebdTryLast or ebdHndLast
16091         //
16092         ehUpdateLastBlocks(bEnd, bStartPrev);
16093
16094         // If we are moving blocks into the end of a try region or handler region
16095         // we will need to extend ebdTryLast or ebdHndLast so the blocks that we
16096         // are moving are part of this try or handler region.
16097         //
16098         for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
16099         {
16100             // Are we moving blocks to the end of a try region?
16101             if (HBtab->ebdTryLast == insertAfterBlk)
16102             {
16103                 if (fStartIsInTry[XTnum])
16104                 {
16105                     // bStart..bEnd is in the try, so extend the try region
16106                     fgSetTryEnd(HBtab, bEnd);
16107                 }
16108             }
16109
16110             // Are we moving blocks to the end of a handler region?
16111             if (HBtab->ebdHndLast == insertAfterBlk)
16112             {
16113                 if (fStartIsInHnd[XTnum])
16114                 {
16115                     // bStart..bEnd is in the handler, so extend the handler region
16116                     fgSetHndEnd(HBtab, bEnd);
16117                 }
16118             }
16119         }
16120
16121         /* We have decided to insert the block(s) after 'insertAfterBlk' */
16122         fgMoveBlocksAfter(bStart, bEnd, insertAfterBlk);
16123
16124         if (bDest)
16125         {
16126             /* We may need to insert an unconditional branch after bPrev to bDest */
16127             fgConnectFallThrough(bPrev, bDest);
16128         }
16129         else
16130         {
16131             /* If bPrev falls through, we must insert a jump to block */
16132             fgConnectFallThrough(bPrev, block);
16133         }
16134
16135         BasicBlock* bSkip = bEnd->bbNext;
16136
16137         /* If bEnd falls through, we must insert a jump to bNext */
16138         fgConnectFallThrough(bEnd, bNext);
16139
16140         if (bStart2 == nullptr)
16141         {
16142             /* If insertAfterBlk falls through, we are forced to     */
16143             /* add a jump around the block(s) we just inserted */
16144             fgConnectFallThrough(insertAfterBlk, bSkip);
16145         }
16146         else
16147         {
16148             /* We may need to insert an unconditional branch after bPrev2 to bStart */
16149             fgConnectFallThrough(bPrev2, bStart);
16150         }
16151
16152 #if DEBUG
16153         if (verbose)
16154         {
16155             printf("\nAfter this change in fgReorderBlocks the BB graph is:");
16156             fgDispBasicBlocks(verboseTrees);
16157             printf("\n");
16158         }
16159         fgVerifyHandlerTab();
16160
16161         // Make sure that the predecessor lists are accurate
16162         if (expensiveDebugCheckLevel >= 2)
16163         {
16164             fgDebugCheckBBlist();
16165         }
16166 #endif // DEBUG
16167
16168         // Set our iteration point 'block' to be the new bPrev->bbNext
16169         //  It will be used as the next bPrev
16170         block = bPrev->bbNext;
16171
16172     } // end of for loop(bPrev,block)
16173
16174     bool changed = movedBlocks || newRarelyRun || optimizedSwitches;
16175
16176     if (changed)
16177     {
16178         fgNeedsUpdateFlowGraph = true;
16179 #if DEBUG
16180         // Make sure that the predecessor lists are accurate
16181         if (expensiveDebugCheckLevel >= 2)
16182         {
16183             fgDebugCheckBBlist();
16184         }
16185 #endif // DEBUG
16186     }
16187 }
16188 #ifdef _PREFAST_
16189 #pragma warning(pop)
16190 #endif
16191
16192 /*-------------------------------------------------------------------------
16193  *
16194  * Walk the basic blocks list to determine the first block to place in the
16195  * cold section.  This would be the first of a series of rarely executed blocks
16196  * such that no succeeding blocks are in a try region or an exception handler
16197  * or are rarely executed.
16198  */
16199
16200 void Compiler::fgDetermineFirstColdBlock()
16201 {
16202 #ifdef DEBUG
16203     if (verbose)
16204     {
16205         printf("\n*************** In fgDetermineFirstColdBlock()\n");
16206     }
16207 #endif // DEBUG
16208
16209     // Since we may need to create a new transistion block
16210     // we assert that it is OK to create new blocks.
16211     //
16212     assert(fgSafeBasicBlockCreation);
16213
16214     fgFirstColdBlock = nullptr;
16215
16216     if (!opts.compProcedureSplitting)
16217     {
16218         JITDUMP("No procedure splitting will be done for this method\n");
16219         return;
16220     }
16221
16222 #ifdef DEBUG
16223     if ((compHndBBtabCount > 0) && !opts.compProcedureSplittingEH)
16224     {
16225         JITDUMP("No procedure splitting will be done for this method with EH (by request)\n");
16226         return;
16227     }
16228 #endif // DEBUG
16229
16230 #if FEATURE_EH_FUNCLETS
16231     // TODO-CQ: handle hot/cold splitting in functions with EH (including synchronized methods
16232     // that create EH in methods without explicit EH clauses).
16233
16234     if (compHndBBtabCount > 0)
16235     {
16236         JITDUMP("No procedure splitting will be done for this method with EH (implementation limitation)\n");
16237         return;
16238     }
16239 #endif // FEATURE_EH_FUNCLETS
16240
16241     BasicBlock* firstColdBlock       = nullptr;
16242     BasicBlock* prevToFirstColdBlock = nullptr;
16243     BasicBlock* block;
16244     BasicBlock* lblk;
16245
16246     for (lblk = nullptr, block = fgFirstBB; block != nullptr; lblk = block, block = block->bbNext)
16247     {
16248         bool blockMustBeInHotSection = false;
16249
16250 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
16251         if (bbIsHandlerBeg(block))
16252         {
16253             blockMustBeInHotSection = true;
16254         }
16255 #endif // HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
16256
16257         // Do we have a candidate for the first cold block?
16258         if (firstColdBlock != nullptr)
16259         {
16260             // We have a candidate for first cold block
16261
16262             // Is this a hot block?
16263             if (blockMustBeInHotSection || (block->isRunRarely() == false))
16264             {
16265                 // We have to restart the search for the first cold block
16266                 firstColdBlock       = nullptr;
16267                 prevToFirstColdBlock = nullptr;
16268             }
16269         }
16270         else // (firstColdBlock == NULL)
16271         {
16272             // We don't have a candidate for first cold block
16273
16274             // Is this a cold block?
16275             if (!blockMustBeInHotSection && (block->isRunRarely() == true))
16276             {
16277                 //
16278                 // If the last block that was hot was a BBJ_COND
16279                 // then we will have to add an unconditional jump
16280                 // so the code size for block needs be large
16281                 // enough to make it worth our while
16282                 //
16283                 if ((lblk == nullptr) || (lblk->bbJumpKind != BBJ_COND) || (fgGetCodeEstimate(block) >= 8))
16284                 {
16285                     // This block is now a candidate for first cold block
16286                     // Also remember the predecessor to this block
16287                     firstColdBlock       = block;
16288                     prevToFirstColdBlock = lblk;
16289                 }
16290             }
16291         }
16292     }
16293
16294     if (firstColdBlock == fgFirstBB)
16295     {
16296         // If the first block is Cold then we can't move any blocks
16297         // into the cold section
16298
16299         firstColdBlock = nullptr;
16300     }
16301
16302     if (firstColdBlock != nullptr)
16303     {
16304         noway_assert(prevToFirstColdBlock != nullptr);
16305
16306         if (prevToFirstColdBlock == nullptr)
16307         {
16308             return; // To keep Prefast happy
16309         }
16310
16311         // If we only have one cold block
16312         // then it may not be worth it to move it
16313         // into the Cold section as a jump to the
16314         // Cold section is 5 bytes in size.
16315         //
16316         if (firstColdBlock->bbNext == nullptr)
16317         {
16318             // If the size of the cold block is 7 or less
16319             // then we will keep it in the Hot section.
16320             //
16321             if (fgGetCodeEstimate(firstColdBlock) < 8)
16322             {
16323                 firstColdBlock = nullptr;
16324                 goto EXIT;
16325             }
16326         }
16327
16328         // When the last Hot block fall through into the Cold section
16329         // we may need to add a jump
16330         //
16331         if (prevToFirstColdBlock->bbFallsThrough())
16332         {
16333             switch (prevToFirstColdBlock->bbJumpKind)
16334             {
16335                 default:
16336                     noway_assert(!"Unhandled jumpkind in fgDetermineFirstColdBlock()");
16337
16338                 case BBJ_CALLFINALLY:
16339                     // A BBJ_CALLFINALLY that falls through is always followed
16340                     // by an empty BBJ_ALWAYS.
16341                     //
16342                     assert(prevToFirstColdBlock->isBBCallAlwaysPair());
16343                     firstColdBlock =
16344                         firstColdBlock->bbNext; // Note that this assignment could make firstColdBlock == nullptr
16345                     break;
16346
16347                 case BBJ_COND:
16348                     //
16349                     // This is a slightly more complicated case, because we will
16350                     // probably need to insert a block to jump to the cold section.
16351                     //
16352                     if (firstColdBlock->isEmpty() && (firstColdBlock->bbJumpKind == BBJ_ALWAYS))
16353                     {
16354                         // We can just use this block as the transitionBlock
16355                         firstColdBlock = firstColdBlock->bbNext;
16356                         // Note that this assignment could make firstColdBlock == NULL
16357                     }
16358                     else
16359                     {
16360                         BasicBlock* transitionBlock = fgNewBBafter(BBJ_ALWAYS, prevToFirstColdBlock, true);
16361                         transitionBlock->bbJumpDest = firstColdBlock;
16362                         transitionBlock->inheritWeight(firstColdBlock);
16363
16364                         noway_assert(fgComputePredsDone);
16365
16366                         // Update the predecessor list for firstColdBlock
16367                         fgReplacePred(firstColdBlock, prevToFirstColdBlock, transitionBlock);
16368
16369                         // Add prevToFirstColdBlock as a predecessor for transitionBlock
16370                         fgAddRefPred(transitionBlock, prevToFirstColdBlock);
16371                     }
16372                     break;
16373
16374                 case BBJ_NONE:
16375                     // If the block preceding the first cold block is BBJ_NONE,
16376                     // convert it to BBJ_ALWAYS to force an explicit jump.
16377
16378                     prevToFirstColdBlock->bbJumpDest = firstColdBlock;
16379                     prevToFirstColdBlock->bbJumpKind = BBJ_ALWAYS;
16380                     break;
16381             }
16382         }
16383     }
16384
16385     if (firstColdBlock != nullptr)
16386     {
16387         firstColdBlock->bbFlags |= BBF_JMP_TARGET;
16388
16389         for (block = firstColdBlock; block; block = block->bbNext)
16390         {
16391             block->bbFlags |= BBF_COLD;
16392         }
16393     }
16394
16395 EXIT:;
16396
16397 #ifdef DEBUG
16398     if (verbose)
16399     {
16400         if (firstColdBlock)
16401         {
16402             printf("fgFirstColdBlock is BB%02u.\n", firstColdBlock->bbNum);
16403         }
16404         else
16405         {
16406             printf("fgFirstColdBlock is NULL.\n");
16407         }
16408
16409         fgDispBasicBlocks();
16410     }
16411
16412     fgVerifyHandlerTab();
16413 #endif // DEBUG
16414
16415     fgFirstColdBlock = firstColdBlock;
16416 }
16417
16418 #ifdef _PREFAST_
16419 #pragma warning(push)
16420 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
16421 #endif
16422 /*****************************************************************************
16423  *
16424  *  Function called to "comb" the basic block list.
16425  *  Removes any empty blocks, unreachable blocks and redundant jumps.
16426  *  Most of those appear after dead store removal and folding of conditionals.
16427  *
16428  *  Returns: true if the flowgraph has been modified
16429  *
16430  *  It also compacts basic blocks
16431  *   (consecutive basic blocks that should in fact be one).
16432  *
16433  *  NOTE:
16434  *    Debuggable code and Min Optimization JIT also introduces basic blocks
16435  *    but we do not optimize those!
16436  */
16437
16438 bool Compiler::fgUpdateFlowGraph(bool doTailDuplication)
16439 {
16440 #ifdef DEBUG
16441     if (verbose)
16442     {
16443         printf("\n*************** In fgUpdateFlowGraph()");
16444     }
16445 #endif // DEBUG
16446
16447     /* This should never be called for debuggable code */
16448
16449     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
16450
16451 #ifdef DEBUG
16452     if (verbose)
16453     {
16454         printf("\nBefore updating the flow graph:\n");
16455         fgDispBasicBlocks(verboseTrees);
16456         printf("\n");
16457     }
16458 #endif // DEBUG
16459
16460     /* Walk all the basic blocks - look for unconditional jumps, empty blocks, blocks to compact, etc...
16461      *
16462      * OBSERVATION:
16463      *      Once a block is removed the predecessors are not accurate (assuming they were at the beginning)
16464      *      For now we will only use the information in bbRefs because it is easier to be updated
16465      */
16466
16467     bool modified = false;
16468     bool change;
16469     do
16470     {
16471         change = false;
16472
16473         BasicBlock* block;           // the current block
16474         BasicBlock* bPrev = nullptr; // the previous non-worthless block
16475         BasicBlock* bNext;           // the successor of the current block
16476         BasicBlock* bDest;           // the jump target of the current block
16477
16478         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
16479         {
16480             /*  Some blocks may be already marked removed by other optimizations
16481              *  (e.g worthless loop removal), without being explicitly removed
16482              *  from the list.
16483              */
16484
16485             if (block->bbFlags & BBF_REMOVED)
16486             {
16487                 if (bPrev)
16488                 {
16489                     bPrev->setNext(block->bbNext);
16490                 }
16491                 else
16492                 {
16493                     /* WEIRD first basic block is removed - should have an assert here */
16494                     noway_assert(!"First basic block marked as BBF_REMOVED???");
16495
16496                     fgFirstBB = block->bbNext;
16497                 }
16498                 continue;
16499             }
16500
16501         /*  We jump to the REPEAT label if we performed a change involving the current block
16502          *  This is in case there are other optimizations that can show up
16503          *  (e.g. - compact 3 blocks in a row)
16504          *  If nothing happens, we then finish the iteration and move to the next block
16505          */
16506
16507         REPEAT:;
16508
16509             bNext = block->bbNext;
16510             bDest = nullptr;
16511
16512             if (block->bbJumpKind == BBJ_ALWAYS)
16513             {
16514                 bDest = block->bbJumpDest;
16515                 if (doTailDuplication && fgOptimizeUncondBranchToSimpleCond(block, bDest))
16516                 {
16517                     change   = true;
16518                     modified = true;
16519                     bDest    = block->bbJumpDest;
16520                     bNext    = block->bbNext;
16521                 }
16522             }
16523
16524             // Remove JUMPS to the following block
16525             // and optimize any JUMPS to JUMPS
16526
16527             if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
16528             {
16529                 bDest = block->bbJumpDest;
16530                 if (bDest == bNext)
16531                 {
16532                     if (fgOptimizeBranchToNext(block, bNext, bPrev))
16533                     {
16534                         change   = true;
16535                         modified = true;
16536                         bDest    = nullptr;
16537                     }
16538                 }
16539             }
16540
16541             if (bDest != nullptr)
16542             {
16543                 // Do we have a JUMP to an empty unconditional JUMP block?
16544                 if (bDest->isEmpty() && (bDest->bbJumpKind == BBJ_ALWAYS) &&
16545                     (bDest != bDest->bbJumpDest)) // special case for self jumps
16546                 {
16547                     if (fgOptimizeBranchToEmptyUnconditional(block, bDest))
16548                     {
16549                         change   = true;
16550                         modified = true;
16551                         goto REPEAT;
16552                     }
16553                 }
16554
16555                 // Check for a conditional branch that just skips over an empty BBJ_ALWAYS block
16556
16557                 if ((block->bbJumpKind == BBJ_COND) &&   // block is a BBJ_COND block
16558                     (bNext != nullptr) &&                // block is not the last block
16559                     (bNext->bbRefs == 1) &&              // No other block jumps to bNext
16560                     (bNext->bbNext == bDest) &&          // The block after bNext is the BBJ_COND jump dest
16561                     (bNext->bbJumpKind == BBJ_ALWAYS) && // The next block is a BBJ_ALWAYS block
16562                     bNext->isEmpty() &&                  // and it is an an empty block
16563                     (bNext != bNext->bbJumpDest) &&      // special case for self jumps
16564                     (bDest != fgFirstColdBlock))
16565                 {
16566                     bool optimizeJump = true;
16567
16568                     // We do not optimize jumps between two different try regions.
16569                     // However jumping to a block that is not in any try region is OK
16570                     //
16571                     if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
16572                     {
16573                         optimizeJump = false;
16574                     }
16575
16576                     // Also consider bNext's try region
16577                     //
16578                     if (bNext->hasTryIndex() && !BasicBlock::sameTryRegion(block, bNext))
16579                     {
16580                         optimizeJump = false;
16581                     }
16582
16583                     // If we are optimizing using real profile weights
16584                     // then don't optimize a conditional jump to an unconditional jump
16585                     // until after we have computed the edge weights
16586                     //
16587                     if (fgIsUsingProfileWeights())
16588                     {
16589                         // if block and bdest are in different hot/cold regions we can't do this this optimization
16590                         // because we can't allow fall-through into the cold region.
16591                         if (!fgEdgeWeightsComputed || fgInDifferentRegions(block, bDest))
16592                         {
16593                             fgNeedsUpdateFlowGraph = true;
16594                             optimizeJump           = false;
16595                         }
16596                     }
16597
16598                     if (optimizeJump)
16599                     {
16600 #ifdef DEBUG
16601                         if (verbose)
16602                         {
16603                             printf("\nReversing a conditional jump around an unconditional jump (BB%02u -> BB%02u -> "
16604                                    "BB%02u)\n",
16605                                    block->bbNum, bDest->bbNum, bNext->bbJumpDest->bbNum);
16606                         }
16607 #endif // DEBUG
16608                         /* Reverse the jump condition */
16609
16610                         GenTree* test = block->lastNode();
16611                         noway_assert(test->OperIsConditionalJump());
16612
16613                         if (test->OperGet() == GT_JTRUE)
16614                         {
16615                             GenTree* cond = gtReverseCond(test->gtOp.gtOp1);
16616                             assert(cond == test->gtOp.gtOp1); // Ensure `gtReverseCond` did not create a new node.
16617                             test->gtOp.gtOp1 = cond;
16618                         }
16619                         else
16620                         {
16621                             gtReverseCond(test);
16622                         }
16623
16624                         // Optimize the Conditional JUMP to go to the new target
16625                         block->bbJumpDest = bNext->bbJumpDest;
16626
16627                         fgAddRefPred(bNext->bbJumpDest, block, fgRemoveRefPred(bNext->bbJumpDest, bNext));
16628
16629                         /*
16630                           Unlink bNext from the BasicBlock list; note that we can
16631                           do this even though other blocks could jump to it - the
16632                           reason is that elsewhere in this function we always
16633                           redirect jumps to jumps to jump to the final label,
16634                           so even if another block jumps to bNext it won't matter
16635                           once we're done since any such jump will be redirected
16636                           to the final target by the time we're done here.
16637                         */
16638
16639                         fgRemoveRefPred(bNext, block);
16640                         fgUnlinkBlock(bNext);
16641
16642                         /* Mark the block as removed */
16643                         bNext->bbFlags |= BBF_REMOVED;
16644
16645                         // If this is the first Cold basic block update fgFirstColdBlock
16646                         if (bNext == fgFirstColdBlock)
16647                         {
16648                             fgFirstColdBlock = bNext->bbNext;
16649                         }
16650
16651                         //
16652                         // If we removed the end of a try region or handler region
16653                         // we will need to update ebdTryLast or ebdHndLast.
16654                         //
16655
16656                         EHblkDsc* HBtab;
16657                         EHblkDsc* HBtabEnd;
16658
16659                         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd;
16660                              HBtab++)
16661                         {
16662                             if ((HBtab->ebdTryLast == bNext) || (HBtab->ebdHndLast == bNext))
16663                             {
16664                                 fgSkipRmvdBlocks(HBtab);
16665                             }
16666                         }
16667
16668                         // we optimized this JUMP - goto REPEAT to catch similar cases
16669                         change   = true;
16670                         modified = true;
16671
16672 #ifdef DEBUG
16673                         if (verbose)
16674                         {
16675                             printf("\nAfter reversing the jump:\n");
16676                             fgDispBasicBlocks(verboseTrees);
16677                         }
16678 #endif // DEBUG
16679
16680                         /*
16681                            For a rare special case we cannot jump to REPEAT
16682                            as jumping to REPEAT will cause us to delete 'block'
16683                            because it currently appears to be unreachable.  As
16684                            it is a self loop that only has a single bbRef (itself)
16685                            However since the unlinked bNext has additional bbRefs
16686                            (that we will later connect to 'block'), it is not really
16687                            unreachable.
16688                         */
16689                         if ((bNext->bbRefs > 0) && (bNext->bbJumpDest == block) && (block->bbRefs == 1))
16690                         {
16691                             continue;
16692                         }
16693
16694                         goto REPEAT;
16695                     }
16696                 }
16697             }
16698
16699             //
16700             // Update the switch jump table such that it follows jumps to jumps:
16701             //
16702             if (block->bbJumpKind == BBJ_SWITCH)
16703             {
16704                 if (fgOptimizeSwitchBranches(block))
16705                 {
16706                     change   = true;
16707                     modified = true;
16708                     goto REPEAT;
16709                 }
16710             }
16711
16712             noway_assert(!(block->bbFlags & BBF_REMOVED));
16713
16714             /* COMPACT blocks if possible */
16715
16716             if (fgCanCompactBlocks(block, bNext))
16717             {
16718                 fgCompactBlocks(block, bNext);
16719
16720                 /* we compacted two blocks - goto REPEAT to catch similar cases */
16721                 change   = true;
16722                 modified = true;
16723                 goto REPEAT;
16724             }
16725
16726             /* Remove unreachable or empty blocks - do not consider blocks marked BBF_DONT_REMOVE or genReturnBB block
16727              * These include first and last block of a TRY, exception handlers and RANGE_CHECK_FAIL THROW blocks */
16728
16729             if ((block->bbFlags & BBF_DONT_REMOVE) == BBF_DONT_REMOVE || block == genReturnBB)
16730             {
16731                 bPrev = block;
16732                 continue;
16733             }
16734
16735 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16736             // Don't remove the BBJ_ALWAYS block of a BBJ_CALLFINALLY/BBJ_ALWAYS pair.
16737             if (block->countOfInEdges() == 0 && bPrev->bbJumpKind == BBJ_CALLFINALLY)
16738             {
16739                 assert(bPrev->isBBCallAlwaysPair());
16740                 noway_assert(!(bPrev->bbFlags & BBF_RETLESS_CALL));
16741                 noway_assert(block->bbJumpKind == BBJ_ALWAYS);
16742                 bPrev = block;
16743                 continue;
16744             }
16745 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16746
16747             noway_assert(!block->bbCatchTyp);
16748             noway_assert(!(block->bbFlags & BBF_TRY_BEG));
16749
16750             /* Remove unreachable blocks
16751              *
16752              * We'll look for blocks that have countOfInEdges() = 0 (blocks may become
16753              * unreachable due to a BBJ_ALWAYS introduced by conditional folding for example)
16754              */
16755
16756             if (block->countOfInEdges() == 0)
16757             {
16758                 /* no references -> unreachable - remove it */
16759                 /* For now do not update the bbNum, do it at the end */
16760
16761                 fgRemoveBlock(block, true);
16762
16763                 change   = true;
16764                 modified = true;
16765
16766                 /* we removed the current block - the rest of the optimizations won't have a target
16767                  * continue with the next one */
16768
16769                 continue;
16770             }
16771             else if (block->countOfInEdges() == 1)
16772             {
16773                 switch (block->bbJumpKind)
16774                 {
16775                     case BBJ_COND:
16776                     case BBJ_ALWAYS:
16777                         if (block->bbJumpDest == block)
16778                         {
16779                             fgRemoveBlock(block, true);
16780
16781                             change   = true;
16782                             modified = true;
16783
16784                             /* we removed the current block - the rest of the optimizations
16785                              * won't have a target so continue with the next block */
16786
16787                             continue;
16788                         }
16789                         break;
16790
16791                     default:
16792                         break;
16793                 }
16794             }
16795
16796             noway_assert(!(block->bbFlags & BBF_REMOVED));
16797
16798             /* Remove EMPTY blocks */
16799
16800             if (block->isEmpty())
16801             {
16802                 assert(bPrev == block->bbPrev);
16803                 if (fgOptimizeEmptyBlock(block))
16804                 {
16805                     change   = true;
16806                     modified = true;
16807                 }
16808
16809                 /* Have we removed the block? */
16810
16811                 if (block->bbFlags & BBF_REMOVED)
16812                 {
16813                     /* block was removed - no change to bPrev */
16814                     continue;
16815                 }
16816             }
16817
16818             /* Set the predecessor of the last reachable block
16819              * If we removed the current block, the predecessor remains unchanged
16820              * otherwise, since the current block is ok, it becomes the predecessor */
16821
16822             noway_assert(!(block->bbFlags & BBF_REMOVED));
16823
16824             bPrev = block;
16825         }
16826     } while (change);
16827
16828     fgNeedsUpdateFlowGraph = false;
16829
16830 #ifdef DEBUG
16831     if (verbose && modified)
16832     {
16833         printf("\nAfter updating the flow graph:\n");
16834         fgDispBasicBlocks(verboseTrees);
16835         fgDispHandlerTab();
16836     }
16837
16838     if (compRationalIRForm)
16839     {
16840         for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
16841         {
16842             LIR::AsRange(block).CheckLIR(this);
16843         }
16844     }
16845
16846     fgVerifyHandlerTab();
16847     // Make sure that the predecessor lists are accurate
16848     fgDebugCheckBBlist();
16849     fgDebugCheckUpdate();
16850 #endif // DEBUG
16851
16852     return modified;
16853 }
16854 #ifdef _PREFAST_
16855 #pragma warning(pop)
16856 #endif
16857
16858 /*****************************************************************************
16859  *  Check that the flow graph is really updated
16860  */
16861
16862 #ifdef DEBUG
16863
16864 void Compiler::fgDebugCheckUpdate()
16865 {
16866     if (!compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))
16867     {
16868         return;
16869     }
16870
16871     /* We check for these conditions:
16872      * no unreachable blocks  -> no blocks have countOfInEdges() = 0
16873      * no empty blocks        -> no blocks have bbTreeList = 0
16874      * no un-imported blocks  -> no blocks have BBF_IMPORTED not set (this is
16875      *                           kind of redundand with the above, but to make sure)
16876      * no un-compacted blocks -> BBJ_NONE followed by block with no jumps to it (countOfInEdges() = 1)
16877      */
16878
16879     BasicBlock* prev;
16880     BasicBlock* block;
16881     for (prev = nullptr, block = fgFirstBB; block != nullptr; prev = block, block = block->bbNext)
16882     {
16883         /* no unreachable blocks */
16884
16885         if ((block->countOfInEdges() == 0) && !(block->bbFlags & BBF_DONT_REMOVE)
16886 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16887             // With funclets, we never get rid of the BBJ_ALWAYS part of a BBJ_CALLFINALLY/BBJ_ALWAYS pair,
16888             // even if we can prove that the finally block never returns.
16889             && (prev == NULL || block->bbJumpKind != BBJ_ALWAYS || !prev->isBBCallAlwaysPair())
16890 #endif // FEATURE_EH_FUNCLETS
16891                 )
16892         {
16893             noway_assert(!"Unreachable block not removed!");
16894         }
16895
16896         /* no empty blocks */
16897
16898         if (block->isEmpty() && !(block->bbFlags & BBF_DONT_REMOVE))
16899         {
16900             switch (block->bbJumpKind)
16901             {
16902                 case BBJ_CALLFINALLY:
16903                 case BBJ_EHFINALLYRET:
16904                 case BBJ_EHFILTERRET:
16905                 case BBJ_RETURN:
16906                 /* for BBJ_ALWAYS is probably just a GOTO, but will have to be treated */
16907                 case BBJ_ALWAYS:
16908                 case BBJ_EHCATCHRET:
16909                     /* These jump kinds are allowed to have empty tree lists */
16910                     break;
16911
16912                 default:
16913                     /* it may be the case that the block had more than one reference to it
16914                      * so we couldn't remove it */
16915
16916                     if (block->countOfInEdges() == 0)
16917                     {
16918                         noway_assert(!"Empty block not removed!");
16919                     }
16920                     break;
16921             }
16922         }
16923
16924         /* no un-imported blocks */
16925
16926         if (!(block->bbFlags & BBF_IMPORTED))
16927         {
16928             /* internal blocks do not count */
16929
16930             if (!(block->bbFlags & BBF_INTERNAL))
16931             {
16932                 noway_assert(!"Non IMPORTED block not removed!");
16933             }
16934         }
16935
16936         bool prevIsCallAlwaysPair = ((prev != nullptr) && prev->isBBCallAlwaysPair());
16937
16938         // Check for an unnecessary jumps to the next block
16939         bool doAssertOnJumpToNextBlock = false; // unless we have a BBJ_COND or BBJ_ALWAYS we can not assert
16940
16941         if (block->bbJumpKind == BBJ_COND)
16942         {
16943             // A conditional branch should never jump to the next block
16944             // as it can be folded into a BBJ_NONE;
16945             doAssertOnJumpToNextBlock = true;
16946         }
16947         else if (block->bbJumpKind == BBJ_ALWAYS)
16948         {
16949             // Generally we will want to assert if a BBJ_ALWAYS branches to the next block
16950             doAssertOnJumpToNextBlock = true;
16951
16952             // If the BBF_KEEP_BBJ_ALWAYS flag is set we allow it to jump to the next block
16953             if (block->bbFlags & BBF_KEEP_BBJ_ALWAYS)
16954             {
16955                 doAssertOnJumpToNextBlock = false;
16956             }
16957
16958             // A call/always pair is also allowed to jump to the next block
16959             if (prevIsCallAlwaysPair)
16960             {
16961                 doAssertOnJumpToNextBlock = false;
16962             }
16963
16964             // We are allowed to have a branch from a hot 'block' to a cold 'bbNext'
16965             //
16966             if ((block->bbNext != nullptr) && fgInDifferentRegions(block, block->bbNext))
16967             {
16968                 doAssertOnJumpToNextBlock = false;
16969             }
16970         }
16971
16972         if (doAssertOnJumpToNextBlock)
16973         {
16974             if (block->bbJumpDest == block->bbNext)
16975             {
16976                 noway_assert(!"Unnecessary jump to the next block!");
16977             }
16978         }
16979
16980         /* Make sure BBF_KEEP_BBJ_ALWAYS is set correctly */
16981
16982         if ((block->bbJumpKind == BBJ_ALWAYS) && prevIsCallAlwaysPair)
16983         {
16984             noway_assert(block->bbFlags & BBF_KEEP_BBJ_ALWAYS);
16985         }
16986
16987         /* For a BBJ_CALLFINALLY block we make sure that we are followed by */
16988         /* an BBJ_ALWAYS block with BBF_INTERNAL set */
16989         /* or that it's a BBF_RETLESS_CALL */
16990         if (block->bbJumpKind == BBJ_CALLFINALLY)
16991         {
16992             assert((block->bbFlags & BBF_RETLESS_CALL) || block->isBBCallAlwaysPair());
16993         }
16994
16995         /* no un-compacted blocks */
16996
16997         if (fgCanCompactBlocks(block, block->bbNext))
16998         {
16999             noway_assert(!"Found un-compacted blocks!");
17000         }
17001     }
17002 }
17003
17004 #endif // DEBUG
17005
17006 /*****************************************************************************
17007  * We've inserted a new block before 'block' that should be part of the same EH region as 'block'.
17008  * Update the EH table to make this so. Also, set the new block to have the right EH region data
17009  * (copy the bbTryIndex, bbHndIndex, and bbCatchTyp from 'block' to the new predecessor, and clear
17010  * 'bbCatchTyp' from 'block').
17011  */
17012 void Compiler::fgExtendEHRegionBefore(BasicBlock* block)
17013 {
17014     assert(block->bbPrev != nullptr);
17015
17016     BasicBlock* bPrev = block->bbPrev;
17017
17018     bPrev->copyEHRegion(block);
17019
17020     // The first block (and only the first block) of a handler has bbCatchTyp set
17021     bPrev->bbCatchTyp = block->bbCatchTyp;
17022     block->bbCatchTyp = BBCT_NONE;
17023
17024     EHblkDsc* HBtab;
17025     EHblkDsc* HBtabEnd;
17026
17027     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
17028     {
17029         /* Multiple pointers in EHblkDsc can point to same block. We can not early out after the first match. */
17030         if (HBtab->ebdTryBeg == block)
17031         {
17032 #ifdef DEBUG
17033             if (verbose)
17034             {
17035                 printf("EH#%u: New first block of try: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
17036             }
17037 #endif // DEBUG
17038             HBtab->ebdTryBeg = bPrev;
17039             bPrev->bbFlags |= BBF_TRY_BEG | BBF_DONT_REMOVE | BBF_HAS_LABEL;
17040
17041             // clear the TryBeg flag unless it begins another try region
17042             if (!bbIsTryBeg(block))
17043             {
17044                 block->bbFlags &= ~BBF_TRY_BEG;
17045             }
17046         }
17047
17048         if (HBtab->ebdHndBeg == block)
17049         {
17050 #ifdef DEBUG
17051             if (verbose)
17052             {
17053                 printf("EH#%u: New first block of handler: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
17054             }
17055 #endif // DEBUG
17056
17057             // The first block of a handler has an artificial extra refcount. Transfer that to the new block.
17058             assert(block->bbRefs > 0);
17059             block->bbRefs--;
17060
17061             HBtab->ebdHndBeg = bPrev;
17062             bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL;
17063
17064 #if FEATURE_EH_FUNCLETS
17065             if (fgFuncletsCreated)
17066             {
17067                 assert((block->bbFlags & BBF_FUNCLET_BEG) != 0);
17068                 bPrev->bbFlags |= BBF_FUNCLET_BEG;
17069                 block->bbFlags &= ~BBF_FUNCLET_BEG;
17070             }
17071 #endif // FEATURE_EH_FUNCLETS
17072
17073             bPrev->bbRefs++;
17074
17075             // If this is a handler for a filter, the last block of the filter will end with
17076             // a BBJ_EJFILTERRET block that has a bbJumpDest that jumps to the first block of
17077             // it's handler.  So we need to update it to keep things in sync.
17078             //
17079             if (HBtab->HasFilter())
17080             {
17081                 BasicBlock* bFilterLast = HBtab->BBFilterLast();
17082                 assert(bFilterLast != nullptr);
17083                 assert(bFilterLast->bbJumpKind == BBJ_EHFILTERRET);
17084                 assert(bFilterLast->bbJumpDest == block);
17085 #ifdef DEBUG
17086                 if (verbose)
17087                 {
17088                     printf("EH#%u: Updating bbJumpDest for filter ret block: BB%02u => BB%02u\n", ehGetIndex(HBtab),
17089                            bFilterLast->bbNum, bPrev->bbNum);
17090                 }
17091 #endif // DEBUG
17092                 // Change the bbJumpDest for bFilterLast from the old first 'block' to the new first 'bPrev'
17093                 bFilterLast->bbJumpDest = bPrev;
17094             }
17095         }
17096
17097         if (HBtab->HasFilter() && (HBtab->ebdFilter == block))
17098         {
17099 #ifdef DEBUG
17100             if (verbose)
17101             {
17102                 printf("EH#%u: New first block of filter: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
17103             }
17104 #endif // DEBUG
17105
17106             // The first block of a filter has an artificial extra refcount. Transfer that to the new block.
17107             assert(block->bbRefs > 0);
17108             block->bbRefs--;
17109
17110             HBtab->ebdFilter = bPrev;
17111             bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL;
17112
17113 #if FEATURE_EH_FUNCLETS
17114             if (fgFuncletsCreated)
17115             {
17116                 assert((block->bbFlags & BBF_FUNCLET_BEG) != 0);
17117                 bPrev->bbFlags |= BBF_FUNCLET_BEG;
17118                 block->bbFlags &= ~BBF_FUNCLET_BEG;
17119             }
17120 #endif // FEATURE_EH_FUNCLETS
17121
17122             bPrev->bbRefs++;
17123         }
17124     }
17125 }
17126
17127 /*****************************************************************************
17128  * We've inserted a new block after 'block' that should be part of the same EH region as 'block'.
17129  * Update the EH table to make this so. Also, set the new block to have the right EH region data.
17130  */
17131
17132 void Compiler::fgExtendEHRegionAfter(BasicBlock* block)
17133 {
17134     BasicBlock* newBlk = block->bbNext;
17135     assert(newBlk != nullptr);
17136
17137     newBlk->copyEHRegion(block);
17138     newBlk->bbCatchTyp =
17139         BBCT_NONE; // Only the first block of a catch has this set, and 'newBlk' can't be the first block of a catch.
17140
17141     // TODO-Throughput: if the block is not in an EH region, then we don't need to walk the EH table looking for 'last'
17142     // block pointers to update.
17143     ehUpdateLastBlocks(block, newBlk);
17144 }
17145
17146 /*****************************************************************************
17147  *
17148  * Insert a BasicBlock before the given block.
17149  */
17150
17151 BasicBlock* Compiler::fgNewBBbefore(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion)
17152 {
17153     // Create a new BasicBlock and chain it in
17154
17155     BasicBlock* newBlk = bbNewBasicBlock(jumpKind);
17156     newBlk->bbFlags |= BBF_INTERNAL;
17157
17158     fgInsertBBbefore(block, newBlk);
17159
17160     newBlk->bbRefs = 0;
17161
17162     if (newBlk->bbFallsThrough() && block->isRunRarely())
17163     {
17164         newBlk->bbSetRunRarely();
17165     }
17166
17167     if (extendRegion)
17168     {
17169         fgExtendEHRegionBefore(block);
17170     }
17171     else
17172     {
17173         // When extendRegion is false the caller is responsible for setting these two values
17174         newBlk->setTryIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
17175         newBlk->setHndIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
17176     }
17177
17178     // We assume that if the block we are inserting before is in the cold region, then this new
17179     // block will also be in the cold region.
17180     newBlk->bbFlags |= (block->bbFlags & BBF_COLD);
17181
17182     return newBlk;
17183 }
17184
17185 /*****************************************************************************
17186  *
17187  * Insert a BasicBlock after the given block.
17188  */
17189
17190 BasicBlock* Compiler::fgNewBBafter(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion)
17191 {
17192     // Create a new BasicBlock and chain it in
17193
17194     BasicBlock* newBlk = bbNewBasicBlock(jumpKind);
17195     newBlk->bbFlags |= BBF_INTERNAL;
17196
17197     fgInsertBBafter(block, newBlk);
17198
17199     newBlk->bbRefs = 0;
17200
17201     if (block->bbFallsThrough() && block->isRunRarely())
17202     {
17203         newBlk->bbSetRunRarely();
17204     }
17205
17206     if (extendRegion)
17207     {
17208         fgExtendEHRegionAfter(block);
17209     }
17210     else
17211     {
17212         // When extendRegion is false the caller is responsible for setting these two values
17213         newBlk->setTryIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
17214         newBlk->setHndIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
17215     }
17216
17217     // If the new block is in the cold region (because the block we are inserting after
17218     // is in the cold region), mark it as such.
17219     newBlk->bbFlags |= (block->bbFlags & BBF_COLD);
17220
17221     return newBlk;
17222 }
17223
17224 /*****************************************************************************
17225  *  Inserts basic block before existing basic block.
17226  *
17227  *  If insertBeforeBlk is in the funclet region, then newBlk will be in the funclet region.
17228  *  (If insertBeforeBlk is the first block of the funclet region, then 'newBlk' will be the
17229  *  new first block of the funclet region.)
17230  */
17231 void Compiler::fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk)
17232 {
17233     if (insertBeforeBlk->bbPrev)
17234     {
17235         fgInsertBBafter(insertBeforeBlk->bbPrev, newBlk);
17236     }
17237     else
17238     {
17239         newBlk->setNext(fgFirstBB);
17240
17241         fgFirstBB      = newBlk;
17242         newBlk->bbPrev = nullptr;
17243     }
17244
17245 #if FEATURE_EH_FUNCLETS
17246
17247     /* Update fgFirstFuncletBB if insertBeforeBlk is the first block of the funclet region. */
17248
17249     if (fgFirstFuncletBB == insertBeforeBlk)
17250     {
17251         fgFirstFuncletBB = newBlk;
17252     }
17253
17254 #endif // FEATURE_EH_FUNCLETS
17255 }
17256
17257 /*****************************************************************************
17258  *  Inserts basic block after existing basic block.
17259  *
17260  *  If insertBeforeBlk is in the funclet region, then newBlk will be in the funclet region.
17261  *  (It can't be used to insert a block as the first block of the funclet region).
17262  */
17263 void Compiler::fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk)
17264 {
17265     newBlk->bbNext = insertAfterBlk->bbNext;
17266
17267     if (insertAfterBlk->bbNext)
17268     {
17269         insertAfterBlk->bbNext->bbPrev = newBlk;
17270     }
17271
17272     insertAfterBlk->bbNext = newBlk;
17273     newBlk->bbPrev         = insertAfterBlk;
17274
17275     if (fgLastBB == insertAfterBlk)
17276     {
17277         fgLastBB = newBlk;
17278         assert(fgLastBB->bbNext == nullptr);
17279     }
17280 }
17281
17282 // We have two edges (bAlt => bCur) and (bCur => bNext).
17283 //
17284 // Returns true if the weight of (bAlt => bCur)
17285 //  is greater than the weight of (bCur => bNext).
17286 // We compare the edge weights if we have valid edge weights
17287 //  otherwise we compare blocks weights.
17288 //
17289 bool Compiler::fgIsBetterFallThrough(BasicBlock* bCur, BasicBlock* bAlt)
17290 {
17291     // bCur can't be NULL and must be a fall through bbJumpKind
17292     noway_assert(bCur != nullptr);
17293     noway_assert(bCur->bbFallsThrough());
17294     noway_assert(bAlt != nullptr);
17295
17296     // We only handle the cases when bAlt is a BBJ_ALWAYS or a BBJ_COND
17297     if ((bAlt->bbJumpKind != BBJ_ALWAYS) && (bAlt->bbJumpKind != BBJ_COND))
17298     {
17299         return false;
17300     }
17301
17302     // if bAlt doesn't jump to bCur it can't be a better fall through than bCur
17303     if (bAlt->bbJumpDest != bCur)
17304     {
17305         return false;
17306     }
17307
17308     // Currently bNext is the fall through for bCur
17309     BasicBlock* bNext = bCur->bbNext;
17310     noway_assert(bNext != nullptr);
17311
17312     // We will set result to true if bAlt is a better fall through than bCur
17313     bool result;
17314     if (fgHaveValidEdgeWeights)
17315     {
17316         // We will compare the edge weight for our two choices
17317         flowList* edgeFromAlt = fgGetPredForBlock(bCur, bAlt);
17318         flowList* edgeFromCur = fgGetPredForBlock(bNext, bCur);
17319         noway_assert(edgeFromCur != nullptr);
17320         noway_assert(edgeFromAlt != nullptr);
17321
17322         result = (edgeFromAlt->flEdgeWeightMin > edgeFromCur->flEdgeWeightMax);
17323     }
17324     else
17325     {
17326         if (bAlt->bbJumpKind == BBJ_ALWAYS)
17327         {
17328             // Our result is true if bAlt's weight is more than bCur's weight
17329             result = (bAlt->bbWeight > bCur->bbWeight);
17330         }
17331         else
17332         {
17333             noway_assert(bAlt->bbJumpKind == BBJ_COND);
17334             // Our result is true if bAlt's weight is more than twice bCur's weight
17335             result = (bAlt->bbWeight > (2 * bCur->bbWeight));
17336         }
17337     }
17338     return result;
17339 }
17340
17341 //------------------------------------------------------------------------
17342 // fgCheckEHCanInsertAfterBlock: Determine if a block can be inserted after
17343 // 'blk' and legally be put in the EH region specified by 'regionIndex'. This
17344 // can be true if the most nested region the block is in is already 'regionIndex',
17345 // as we'll just extend the most nested region (and any region ending at the same block).
17346 // It can also be true if it is the end of (a set of) EH regions, such that
17347 // inserting the block and properly extending some EH regions (if necessary)
17348 // puts the block in the correct region. We only consider the case of extending
17349 // an EH region after 'blk' (that is, to include 'blk' and the newly insert block);
17350 // we don't consider inserting a block as the the first block of an EH region following 'blk'.
17351 //
17352 // Consider this example:
17353 //
17354 //      try3   try2   try1
17355 //      |---   |      |      BB01
17356 //      |      |---   |      BB02
17357 //      |      |      |---   BB03
17358 //      |      |      |      BB04
17359 //      |      |---   |---   BB05
17360 //      |                    BB06
17361 //      |-----------------   BB07
17362 //
17363 // Passing BB05 and try1/try2/try3 as the region to insert into (as well as putInTryRegion==true)
17364 // will all return 'true'. Here are the cases:
17365 // 1. Insert into try1: the most nested EH region BB05 is in is already try1, so we can insert after
17366 //    it and extend try1 (and try2).
17367 // 2. Insert into try2: we can extend try2, but leave try1 alone.
17368 // 3. Insert into try3: we can leave try1 and try2 alone, and put the new block just in try3. Note that
17369 //    in this case, after we "loop outwards" in the EH nesting, we get to a place where we're in the middle
17370 //    of the try3 region, not at the end of it.
17371 // In all cases, it is possible to put a block after BB05 and put it in any of these three 'try' regions legally.
17372 //
17373 // Filters are ignored; if 'blk' is in a filter, the answer will be false.
17374 //
17375 // Arguments:
17376 //    blk - the BasicBlock we are checking to see if we can insert after.
17377 //    regionIndex - the EH region we want to insert a block into. regionIndex is
17378 //          in the range [0..compHndBBtabCount]; 0 means "main method".
17379 //    putInTryRegion - 'true' if the new block should be inserted in the 'try' region of 'regionIndex'.
17380 //          For regionIndex 0 (the "main method"), this should be 'true'.
17381 //
17382 // Return Value:
17383 //    'true' if a block can be inserted after 'blk' and put in EH region 'regionIndex', else 'false'.
17384 //
17385 bool Compiler::fgCheckEHCanInsertAfterBlock(BasicBlock* blk, unsigned regionIndex, bool putInTryRegion)
17386 {
17387     assert(blk != nullptr);
17388     assert(regionIndex <= compHndBBtabCount);
17389
17390     if (regionIndex == 0)
17391     {
17392         assert(putInTryRegion);
17393     }
17394
17395     bool     inTryRegion;
17396     unsigned nestedRegionIndex = ehGetMostNestedRegionIndex(blk, &inTryRegion);
17397
17398     bool insertOK = true;
17399     for (;;)
17400     {
17401         if (nestedRegionIndex == regionIndex)
17402         {
17403             // This block is in the region we want to be in. We can insert here if it's the right type of region.
17404             // (If we want to be in the 'try' region, but the block is in the handler region, then inserting a
17405             // new block after 'blk' can't put it in the 'try' region, and vice-versa, since we only consider
17406             // extending regions after, not prepending to regions.)
17407             // This check will be 'true' if we are trying to put something in the main function (as putInTryRegion
17408             // must be 'true' if regionIndex is zero, and inTryRegion will also be 'true' if nestedRegionIndex is zero).
17409             insertOK = (putInTryRegion == inTryRegion);
17410             break;
17411         }
17412         else if (nestedRegionIndex == 0)
17413         {
17414             // The block is in the main function, but we want to put something in a nested region. We can't do that.
17415             insertOK = false;
17416             break;
17417         }
17418
17419         assert(nestedRegionIndex > 0);
17420         EHblkDsc* ehDsc = ehGetDsc(nestedRegionIndex - 1); // ehGetDsc uses [0..compHndBBtabCount) form.
17421
17422         if (inTryRegion)
17423         {
17424             if (blk != ehDsc->ebdTryLast)
17425             {
17426                 // Not the last block? Then it must be somewhere else within the try region, so we can't insert here.
17427                 insertOK = false;
17428                 break; // exit the 'for' loop
17429             }
17430         }
17431         else
17432         {
17433             // We ignore filters.
17434             if (blk != ehDsc->ebdHndLast)
17435             {
17436                 // Not the last block? Then it must be somewhere else within the handler region, so we can't insert
17437                 // here.
17438                 insertOK = false;
17439                 break; // exit the 'for' loop
17440             }
17441         }
17442
17443         // Things look good for this region; check the enclosing regions, if any.
17444
17445         nestedRegionIndex =
17446             ehGetEnclosingRegionIndex(nestedRegionIndex - 1,
17447                                       &inTryRegion); // ehGetEnclosingRegionIndex uses [0..compHndBBtabCount) form.
17448
17449         // Convert to [0..compHndBBtabCount] form.
17450         nestedRegionIndex = (nestedRegionIndex == EHblkDsc::NO_ENCLOSING_INDEX) ? 0 : nestedRegionIndex + 1;
17451     } // end of for(;;)
17452
17453     return insertOK;
17454 }
17455
17456 //------------------------------------------------------------------------
17457 // Finds the block closest to endBlk in the range [startBlk..endBlk) after which a block can be
17458 // inserted easily. Note that endBlk cannot be returned; its predecessor is the last block that can
17459 // be returned. The new block will be put in an EH region described by the arguments regionIndex,
17460 // putInTryRegion, startBlk, and endBlk (explained below), so it must be legal to place to put the
17461 // new block after the insertion location block, give it the specified EH region index, and not break
17462 // EH nesting rules. This function is careful to choose a block in the correct EH region. However,
17463 // it assumes that the new block can ALWAYS be placed at the end (just before endBlk). That means
17464 // that the caller must ensure that is true.
17465 //
17466 // Below are the possible cases for the arguments to this method:
17467 //      1. putInTryRegion == true and regionIndex > 0:
17468 //         Search in the try region indicated by regionIndex.
17469 //      2. putInTryRegion == false and regionIndex > 0:
17470 //         a. If startBlk is the first block of a filter and endBlk is the block after the end of the
17471 //            filter (that is, the startBlk and endBlk match a filter bounds exactly), then choose a
17472 //            location within this filter region. (Note that, due to IL rules, filters do not have any
17473 //            EH nested within them.) Otherwise, filters are skipped.
17474 //         b. Else, search in the handler region indicated by regionIndex.
17475 //      3. regionIndex = 0:
17476 //         Search in the entire main method, excluding all EH regions. In this case, putInTryRegion must be true.
17477 //
17478 // This method makes sure to find an insertion point which would not cause the inserted block to
17479 // be put inside any inner try/filter/handler regions.
17480 //
17481 // The actual insertion occurs after the returned block. Note that the returned insertion point might
17482 // be the last block of a more nested EH region, because the new block will be inserted after the insertion
17483 // point, and will not extend the more nested EH region. For example:
17484 //
17485 //      try3   try2   try1
17486 //      |---   |      |      BB01
17487 //      |      |---   |      BB02
17488 //      |      |      |---   BB03
17489 //      |      |      |      BB04
17490 //      |      |---   |---   BB05
17491 //      |                    BB06
17492 //      |-----------------   BB07
17493 //
17494 // for regionIndex==try3, putInTryRegion==true, we might return BB05, even though BB05 will have a try index
17495 // for try1 (the most nested 'try' region the block is in). That's because when we insert after BB05, the new
17496 // block will be in the correct, desired EH region, since try1 and try2 regions will not be extended to include
17497 // the inserted block. Furthermore, for regionIndex==try2, putInTryRegion==true, we can also return BB05. In this
17498 // case, when the new block is inserted, the try1 region remains the same, but we need extend region 'try2' to
17499 // include the inserted block. (We also need to check all parent regions as well, just in case any parent regions
17500 // also end on the same block, in which case we would also need to extend the parent regions. This is standard
17501 // procedure when inserting a block at the end of an EH region.)
17502 //
17503 // If nearBlk is non-nullptr then we return the closest block after nearBlk that will work best.
17504 //
17505 // We try to find a block in the appropriate region that is not a fallthrough block, so we can insert after it
17506 // without the need to insert a jump around the inserted block.
17507 //
17508 // Note that regionIndex is numbered the same as BasicBlock::bbTryIndex and BasicBlock::bbHndIndex, that is, "0" is
17509 // "main method" and otherwise is +1 from normal, so we can call, e.g., ehGetDsc(tryIndex - 1).
17510 //
17511 // Arguments:
17512 //    regionIndex - the region index where the new block will be inserted. Zero means entire method;
17513 //          non-zero means either a "try" or a "handler" region, depending on what putInTryRegion says.
17514 //    putInTryRegion - 'true' to put the block in the 'try' region corresponding to 'regionIndex', 'false'
17515 //          to put the block in the handler region. Should be 'true' if regionIndex==0.
17516 //    startBlk - start block of range to search.
17517 //    endBlk - end block of range to search (don't include this block in the range). Can be nullptr to indicate
17518 //          the end of the function.
17519 //    nearBlk - If non-nullptr, try to find an insertion location closely after this block. If nullptr, we insert
17520 //          at the best location found towards the end of the acceptable block range.
17521 //    jumpBlk - When nearBlk is set, this can be set to the block which jumps to bNext->bbNext (TODO: need to review
17522 //    this?)
17523 //    runRarely - true if the block being inserted is expected to be rarely run. This helps determine
17524 //          the best place to put the new block, by putting in a place that has the same 'rarely run' characteristic.
17525 //
17526 // Return Value:
17527 //    A block with the desired characteristics, so the new block will be inserted after this one.
17528 //    If there is no suitable location, return nullptr. This should basically never happen.
17529 //
17530 BasicBlock* Compiler::fgFindInsertPoint(unsigned    regionIndex,
17531                                         bool        putInTryRegion,
17532                                         BasicBlock* startBlk,
17533                                         BasicBlock* endBlk,
17534                                         BasicBlock* nearBlk,
17535                                         BasicBlock* jumpBlk,
17536                                         bool        runRarely)
17537 {
17538     noway_assert(startBlk != nullptr);
17539     noway_assert(startBlk != endBlk);
17540     noway_assert((regionIndex == 0 && putInTryRegion) || // Search in the main method
17541                  (putInTryRegion && regionIndex > 0 &&
17542                   startBlk->bbTryIndex == regionIndex) || // Search in the specified try     region
17543                  (!putInTryRegion && regionIndex > 0 &&
17544                   startBlk->bbHndIndex == regionIndex)); // Search in the specified handler region
17545
17546 #ifdef DEBUG
17547     // Assert that startBlk precedes endBlk in the block list.
17548     // We don't want to use bbNum to assert this condition, as we cannot depend on the block numbers being
17549     // sequential at all times.
17550     for (BasicBlock* b = startBlk; b != endBlk; b = b->bbNext)
17551     {
17552         assert(b != nullptr); // We reached the end of the block list, but never found endBlk.
17553     }
17554 #endif // DEBUG
17555
17556     JITDUMP("fgFindInsertPoint(regionIndex=%u, putInTryRegion=%s, startBlk=BB%02u, endBlk=BB%02u, nearBlk=BB%02u, "
17557             "jumpBlk=BB%02u, runRarely=%s)\n",
17558             regionIndex, dspBool(putInTryRegion), startBlk->bbNum, (endBlk == nullptr) ? 0 : endBlk->bbNum,
17559             (nearBlk == nullptr) ? 0 : nearBlk->bbNum, (jumpBlk == nullptr) ? 0 : jumpBlk->bbNum, dspBool(runRarely));
17560
17561     bool insertingIntoFilter = false;
17562     if (!putInTryRegion)
17563     {
17564         EHblkDsc* const dsc = ehGetDsc(regionIndex - 1);
17565         insertingIntoFilter = dsc->HasFilter() && (startBlk == dsc->ebdFilter) && (endBlk == dsc->ebdHndBeg);
17566     }
17567
17568     bool        reachedNear = false; // Have we reached 'nearBlk' in our search? If not, we'll keep searching.
17569     bool        inFilter    = false; // Are we in a filter region that we need to skip?
17570     BasicBlock* bestBlk =
17571         nullptr; // Set to the best insertion point we've found so far that meets all the EH requirements.
17572     BasicBlock* goodBlk =
17573         nullptr; // Set to an acceptable insertion point that we'll use if we don't find a 'best' option.
17574     BasicBlock* blk;
17575
17576     if (nearBlk != nullptr)
17577     {
17578         // Does the nearBlk precede the startBlk?
17579         for (blk = nearBlk; blk != nullptr; blk = blk->bbNext)
17580         {
17581             if (blk == startBlk)
17582             {
17583                 reachedNear = true;
17584                 break;
17585             }
17586             else if (blk == endBlk)
17587             {
17588                 break;
17589             }
17590         }
17591     }
17592
17593     for (blk = startBlk; blk != endBlk; blk = blk->bbNext)
17594     {
17595         // The only way (blk == nullptr) could be true is if the caller passed an endBlk that preceded startBlk in the
17596         // block list, or if endBlk isn't in the block list at all. In DEBUG, we'll instead hit the similar
17597         // well-formedness assert earlier in this function.
17598         noway_assert(blk != nullptr);
17599
17600         if (blk == nearBlk)
17601         {
17602             reachedNear = true;
17603         }
17604
17605         if (blk->bbCatchTyp == BBCT_FILTER)
17606         {
17607             // Record the fact that we entered a filter region, so we don't insert into filters...
17608             // Unless the caller actually wanted the block inserted in this exact filter region.
17609             if (!insertingIntoFilter || (blk != startBlk))
17610             {
17611                 inFilter = true;
17612             }
17613         }
17614         else if (blk->bbCatchTyp == BBCT_FILTER_HANDLER)
17615         {
17616             // Record the fact that we exited a filter region.
17617             inFilter = false;
17618         }
17619
17620         // Don't insert a block inside this filter region.
17621         if (inFilter)
17622         {
17623             continue;
17624         }
17625
17626         // Note that the new block will be inserted AFTER "blk". We check to make sure that doing so
17627         // would put the block in the correct EH region. We make an assumption here that you can
17628         // ALWAYS insert the new block before "endBlk" (that is, at the end of the search range)
17629         // and be in the correct EH region. This is must be guaranteed by the caller (as it is by
17630         // fgNewBBinRegion(), which passes the search range as an exact EH region block range).
17631         // Because of this assumption, we only check the EH information for blocks before the last block.
17632         if (blk->bbNext != endBlk)
17633         {
17634             // We are in the middle of the search range. We can't insert the new block in
17635             // an inner try or handler region. We can, however, set the insertion
17636             // point to the last block of an EH try/handler region, if the enclosing
17637             // region is the region we wish to insert in. (Since multiple regions can
17638             // end at the same block, we need to search outwards, checking that the
17639             // block is the last block of every EH region out to the region we want
17640             // to insert in.) This is especially useful for putting a call-to-finally
17641             // block on AMD64 immediately after its corresponding 'try' block, so in the
17642             // common case, we'll just fall through to it. For example:
17643             //
17644             //      BB01
17645             //      BB02 -- first block of try
17646             //      BB03
17647             //      BB04 -- last block of try
17648             //      BB05 -- first block of finally
17649             //      BB06
17650             //      BB07 -- last block of handler
17651             //      BB08
17652             //
17653             // Assume there is only one try/finally, so BB01 and BB08 are in the "main function".
17654             // For AMD64 call-to-finally, we'll want to insert the BBJ_CALLFINALLY in
17655             // the main function, immediately after BB04. This allows us to do that.
17656
17657             if (!fgCheckEHCanInsertAfterBlock(blk, regionIndex, putInTryRegion))
17658             {
17659                 // Can't insert here.
17660                 continue;
17661             }
17662         }
17663
17664         // Look for an insert location:
17665         // 1. We want blocks that don't end with a fall through,
17666         // 2. Also, when blk equals nearBlk we may want to insert here.
17667         if (!blk->bbFallsThrough() || (blk == nearBlk))
17668         {
17669             bool updateBestBlk = true; // We will probably update the bestBlk
17670
17671             // If blk falls through then we must decide whether to use the nearBlk
17672             // hint
17673             if (blk->bbFallsThrough())
17674             {
17675                 noway_assert(blk == nearBlk);
17676                 if (jumpBlk != nullptr)
17677                 {
17678                     updateBestBlk = fgIsBetterFallThrough(blk, jumpBlk);
17679                 }
17680                 else
17681                 {
17682                     updateBestBlk = false;
17683                 }
17684             }
17685
17686             // If we already have a best block, see if the 'runRarely' flags influences
17687             // our choice. If we want a runRarely insertion point, and the existing best
17688             // block is run rarely but the current block isn't run rarely, then don't
17689             // update the best block.
17690             // TODO-CQ: We should also handle the reverse case, where runRarely is false (we
17691             // want a non-rarely-run block), but bestBlock->isRunRarely() is true. In that
17692             // case, we should update the block, also. Probably what we want is:
17693             //    (bestBlk->isRunRarely() != runRarely) && (blk->isRunRarely() == runRarely)
17694             if (updateBestBlk && (bestBlk != nullptr) && runRarely && bestBlk->isRunRarely() && !blk->isRunRarely())
17695             {
17696                 updateBestBlk = false;
17697             }
17698
17699             if (updateBestBlk)
17700             {
17701                 // We found a 'best' insertion location, so save it away.
17702                 bestBlk = blk;
17703
17704                 // If we've reached nearBlk, we've satisfied all the criteria,
17705                 // so we're done.
17706                 if (reachedNear)
17707                 {
17708                     goto DONE;
17709                 }
17710
17711                 // If we haven't reached nearBlk, keep looking for a 'best' location, just
17712                 // in case we'll find one at or after nearBlk. If no nearBlk was specified,
17713                 // we prefer inserting towards the end of the given range, so keep looking
17714                 // for more acceptable insertion locations.
17715             }
17716         }
17717
17718         // No need to update goodBlk after we have set bestBlk, but we could still find a better
17719         // bestBlk, so keep looking.
17720         if (bestBlk != nullptr)
17721         {
17722             continue;
17723         }
17724
17725         // Set the current block as a "good enough" insertion point, if it meets certain criteria.
17726         // We'll return this block if we don't find a "best" block in the search range. The block
17727         // can't be a BBJ_CALLFINALLY of a BBJ_CALLFINALLY/BBJ_ALWAYS pair (since we don't want
17728         // to insert anything between these two blocks). Otherwise, we can use it. However,
17729         // if we'd previously chosen a BBJ_COND block, then we'd prefer the "good" block to be
17730         // something else. We keep updating it until we've reached the 'nearBlk', to push it as
17731         // close to endBlk as possible.
17732         if (!blk->isBBCallAlwaysPair())
17733         {
17734             if (goodBlk == nullptr)
17735             {
17736                 goodBlk = blk;
17737             }
17738             else if ((goodBlk->bbJumpKind == BBJ_COND) || (blk->bbJumpKind != BBJ_COND))
17739             {
17740                 if ((blk == nearBlk) || !reachedNear)
17741                 {
17742                     goodBlk = blk;
17743                 }
17744             }
17745         }
17746     }
17747
17748     // If we didn't find a non-fall_through block, then insert at the last good block.
17749
17750     if (bestBlk == nullptr)
17751     {
17752         bestBlk = goodBlk;
17753     }
17754
17755 DONE:
17756
17757 #if defined(JIT32_GCENCODER)
17758     // If we are inserting into a filter and the best block is the end of the filter region, we need to
17759     // insert after its predecessor instead: the JIT32 GC encoding used by the x86 CLR ABI  states that the
17760     // terminal block of a filter region is its exit block. If the filter region consists of a single block,
17761     // a new block cannot be inserted without either splitting the single block before inserting a new block
17762     // or inserting the new block before the single block and updating the filter description such that the
17763     // inserted block is marked as the entry block for the filter. Becuase this sort of split can be complex
17764     // (especially given that it must ensure that the liveness of the exception object is properly tracked),
17765     // we avoid this situation by never generating single-block filters on x86 (see impPushCatchArgOnStack).
17766     if (insertingIntoFilter && (bestBlk == endBlk->bbPrev))
17767     {
17768         assert(bestBlk != startBlk);
17769         bestBlk = bestBlk->bbPrev;
17770     }
17771 #endif // defined(JIT32_GCENCODER)
17772
17773     return bestBlk;
17774 }
17775
17776 //------------------------------------------------------------------------
17777 // Creates a new BasicBlock and inserts it in a specific EH region, given by 'tryIndex', 'hndIndex', and 'putInFilter'.
17778 //
17779 // If 'putInFilter' it true, then the block is inserted in the filter region given by 'hndIndex'. In this case, tryIndex
17780 // must be a less nested EH region (that is, tryIndex > hndIndex).
17781 //
17782 // Otherwise, the block is inserted in either the try region or the handler region, depending on which one is the inner
17783 // region. In other words, if the try region indicated by tryIndex is nested in the handler region indicated by
17784 // hndIndex,
17785 // then the new BB will be created in the try region. Vice versa.
17786 //
17787 // Note that tryIndex and hndIndex are numbered the same as BasicBlock::bbTryIndex and BasicBlock::bbHndIndex, that is,
17788 // "0" is "main method" and otherwise is +1 from normal, so we can call, e.g., ehGetDsc(tryIndex - 1).
17789 //
17790 // To be more specific, this function will create a new BB in one of the following 5 regions (if putInFilter is false):
17791 // 1. When tryIndex = 0 and hndIndex = 0:
17792 //    The new BB will be created in the method region.
17793 // 2. When tryIndex != 0 and hndIndex = 0:
17794 //    The new BB will be created in the try region indicated by tryIndex.
17795 // 3. When tryIndex == 0 and hndIndex != 0:
17796 //    The new BB will be created in the handler region indicated by hndIndex.
17797 // 4. When tryIndex != 0 and hndIndex != 0 and tryIndex < hndIndex:
17798 //    In this case, the try region is nested inside the handler region. Therefore, the new BB will be created
17799 //    in the try region indicated by tryIndex.
17800 // 5. When tryIndex != 0 and hndIndex != 0 and tryIndex > hndIndex:
17801 //    In this case, the handler region is nested inside the try region. Therefore, the new BB will be created
17802 //    in the handler region indicated by hndIndex.
17803 //
17804 // Note that if tryIndex != 0 and hndIndex != 0 then tryIndex must not be equal to hndIndex (this makes sense because
17805 // if they are equal, you are asking to put the new block in both the try and handler, which is impossible).
17806 //
17807 // The BasicBlock will not be inserted inside an EH region that is more nested than the requested tryIndex/hndIndex
17808 // region (so the function is careful to skip more nested EH regions when searching for a place to put the new block).
17809 //
17810 // This function cannot be used to insert a block as the first block of any region. It always inserts a block after
17811 // an existing block in the given region.
17812 //
17813 // If nearBlk is nullptr, or the block is run rarely, then the new block is assumed to be run rarely.
17814 //
17815 // Arguments:
17816 //    jumpKind - the jump kind of the new block to create.
17817 //    tryIndex - the try region to insert the new block in, described above. This must be a number in the range
17818 //               [0..compHndBBtabCount].
17819 //    hndIndex - the handler region to insert the new block in, described above. This must be a number in the range
17820 //               [0..compHndBBtabCount].
17821 //    nearBlk  - insert the new block closely after this block, if possible. If nullptr, put the new block anywhere
17822 //               in the requested region.
17823 //    putInFilter - put the new block in the filter region given by hndIndex, as described above.
17824 //    runRarely - 'true' if the new block is run rarely.
17825 //    insertAtEnd - 'true' if the block should be inserted at the end of the region. Note: this is currently only
17826 //                  implemented when inserting into the main function (not into any EH region).
17827 //
17828 // Return Value:
17829 //    The new block.
17830
17831 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind,
17832                                       unsigned    tryIndex,
17833                                       unsigned    hndIndex,
17834                                       BasicBlock* nearBlk,
17835                                       bool        putInFilter /* = false */,
17836                                       bool        runRarely /* = false */,
17837                                       bool        insertAtEnd /* = false */)
17838 {
17839     assert(tryIndex <= compHndBBtabCount);
17840     assert(hndIndex <= compHndBBtabCount);
17841
17842     /* afterBlk is the block which will precede the newBB */
17843     BasicBlock* afterBlk;
17844
17845     // start and end limit for inserting the block
17846     BasicBlock* startBlk = nullptr;
17847     BasicBlock* endBlk   = nullptr;
17848
17849     bool     putInTryRegion = true;
17850     unsigned regionIndex    = 0;
17851
17852     // First, figure out which region (the "try" region or the "handler" region) to put the newBB in.
17853     if ((tryIndex == 0) && (hndIndex == 0))
17854     {
17855         assert(!putInFilter);
17856
17857         endBlk = fgEndBBAfterMainFunction(); // don't put new BB in funclet region
17858
17859         if (insertAtEnd || (nearBlk == nullptr))
17860         {
17861             /* We'll just insert the block at the end of the method, before the funclets */
17862
17863             afterBlk = fgLastBBInMainFunction();
17864             goto _FoundAfterBlk;
17865         }
17866         else
17867         {
17868             // We'll search through the entire method
17869             startBlk = fgFirstBB;
17870         }
17871
17872         noway_assert(regionIndex == 0);
17873     }
17874     else
17875     {
17876         noway_assert(tryIndex > 0 || hndIndex > 0);
17877         PREFIX_ASSUME(tryIndex <= compHndBBtabCount);
17878         PREFIX_ASSUME(hndIndex <= compHndBBtabCount);
17879
17880         // Decide which region to put in, the "try" region or the "handler" region.
17881         if (tryIndex == 0)
17882         {
17883             noway_assert(hndIndex > 0);
17884             putInTryRegion = false;
17885         }
17886         else if (hndIndex == 0)
17887         {
17888             noway_assert(tryIndex > 0);
17889             noway_assert(putInTryRegion);
17890             assert(!putInFilter);
17891         }
17892         else
17893         {
17894             noway_assert(tryIndex > 0 && hndIndex > 0 && tryIndex != hndIndex);
17895             putInTryRegion = (tryIndex < hndIndex);
17896         }
17897
17898         if (putInTryRegion)
17899         {
17900             // Try region is the inner region.
17901             // In other words, try region must be nested inside the handler region.
17902             noway_assert(hndIndex == 0 || bbInHandlerRegions(hndIndex - 1, ehGetDsc(tryIndex - 1)->ebdTryBeg));
17903             assert(!putInFilter);
17904         }
17905         else
17906         {
17907             // Handler region is the inner region.
17908             // In other words, handler region must be nested inside the try region.
17909             noway_assert(tryIndex == 0 || bbInTryRegions(tryIndex - 1, ehGetDsc(hndIndex - 1)->ebdHndBeg));
17910         }
17911
17912         // Figure out the start and end block range to search for an insertion location. Pick the beginning and
17913         // ending blocks of the target EH region (the 'endBlk' is one past the last block of the EH region, to make
17914         // loop iteration easier). Note that, after funclets have been created (for FEATURE_EH_FUNCLETS),
17915         // this linear block range will not include blocks of handlers for try/handler clauses nested within
17916         // this EH region, as those blocks have been extracted as funclets. That is ok, though, because we don't
17917         // want to insert a block in any nested EH region.
17918
17919         if (putInTryRegion)
17920         {
17921             // We will put the newBB in the try region.
17922             EHblkDsc* ehDsc = ehGetDsc(tryIndex - 1);
17923             startBlk        = ehDsc->ebdTryBeg;
17924             endBlk          = ehDsc->ebdTryLast->bbNext;
17925             regionIndex     = tryIndex;
17926         }
17927         else if (putInFilter)
17928         {
17929             // We will put the newBB in the filter region.
17930             EHblkDsc* ehDsc = ehGetDsc(hndIndex - 1);
17931             startBlk        = ehDsc->ebdFilter;
17932             endBlk          = ehDsc->ebdHndBeg;
17933             regionIndex     = hndIndex;
17934         }
17935         else
17936         {
17937             // We will put the newBB in the handler region.
17938             EHblkDsc* ehDsc = ehGetDsc(hndIndex - 1);
17939             startBlk        = ehDsc->ebdHndBeg;
17940             endBlk          = ehDsc->ebdHndLast->bbNext;
17941             regionIndex     = hndIndex;
17942         }
17943
17944         noway_assert(regionIndex > 0);
17945     }
17946
17947     // Now find the insertion point.
17948     afterBlk = fgFindInsertPoint(regionIndex, putInTryRegion, startBlk, endBlk, nearBlk, nullptr, runRarely);
17949
17950 _FoundAfterBlk:;
17951
17952     /* We have decided to insert the block after 'afterBlk'. */
17953     noway_assert(afterBlk != nullptr);
17954
17955     JITDUMP("fgNewBBinRegion(jumpKind=%u, tryIndex=%u, hndIndex=%u, putInFilter=%s, runRarely=%s, insertAtEnd=%s): "
17956             "inserting after BB%02u\n",
17957             jumpKind, tryIndex, hndIndex, dspBool(putInFilter), dspBool(runRarely), dspBool(insertAtEnd),
17958             afterBlk->bbNum);
17959
17960     return fgNewBBinRegionWorker(jumpKind, afterBlk, regionIndex, putInTryRegion);
17961 }
17962
17963 //------------------------------------------------------------------------
17964 // Creates a new BasicBlock and inserts it in the same EH region as 'srcBlk'.
17965 //
17966 // See the implementation of fgNewBBinRegion() used by this one for more notes.
17967 //
17968 // Arguments:
17969 //    jumpKind - the jump kind of the new block to create.
17970 //    srcBlk   - insert the new block in the same EH region as this block, and closely after it if possible.
17971 //
17972 // Return Value:
17973 //    The new block.
17974
17975 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind,
17976                                       BasicBlock* srcBlk,
17977                                       bool        runRarely /* = false */,
17978                                       bool        insertAtEnd /* = false */)
17979 {
17980     assert(srcBlk != nullptr);
17981
17982     const unsigned tryIndex    = srcBlk->bbTryIndex;
17983     const unsigned hndIndex    = srcBlk->bbHndIndex;
17984     bool           putInFilter = false;
17985
17986     // Check to see if we need to put the new block in a filter. We do if srcBlk is in a filter.
17987     // This can only be true if there is a handler index, and the handler region is more nested than the
17988     // try region (if any). This is because no EH regions can be nested within a filter.
17989     if (BasicBlock::ehIndexMaybeMoreNested(hndIndex, tryIndex))
17990     {
17991         assert(hndIndex != 0); // If hndIndex is more nested, we must be in some handler!
17992         putInFilter = ehGetDsc(hndIndex - 1)->InFilterRegionBBRange(srcBlk);
17993     }
17994
17995     return fgNewBBinRegion(jumpKind, tryIndex, hndIndex, srcBlk, putInFilter, runRarely, insertAtEnd);
17996 }
17997
17998 //------------------------------------------------------------------------
17999 // Creates a new BasicBlock and inserts it at the end of the function.
18000 //
18001 // See the implementation of fgNewBBinRegion() used by this one for more notes.
18002 //
18003 // Arguments:
18004 //    jumpKind - the jump kind of the new block to create.
18005 //
18006 // Return Value:
18007 //    The new block.
18008
18009 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind)
18010 {
18011     return fgNewBBinRegion(jumpKind, 0, 0, nullptr, /* putInFilter */ false, /* runRarely */ false,
18012                            /* insertAtEnd */ true);
18013 }
18014
18015 //------------------------------------------------------------------------
18016 // Creates a new BasicBlock, and inserts it after 'afterBlk'.
18017 //
18018 // The block cannot be inserted into a more nested try/handler region than that specified by 'regionIndex'.
18019 // (It is given exactly 'regionIndex'.) Thus, the parameters must be passed to ensure proper EH nesting
18020 // rules are followed.
18021 //
18022 // Arguments:
18023 //    jumpKind - the jump kind of the new block to create.
18024 //    afterBlk - insert the new block after this one.
18025 //    regionIndex - the block will be put in this EH region.
18026 //    putInTryRegion - If true, put the new block in the 'try' region corresponding to 'regionIndex', and
18027 //          set its handler index to the most nested handler region enclosing that 'try' region.
18028 //          Otherwise, put the block in the handler region specified by 'regionIndex', and set its 'try'
18029 //          index to the most nested 'try' region enclosing that handler region.
18030 //
18031 // Return Value:
18032 //    The new block.
18033
18034 BasicBlock* Compiler::fgNewBBinRegionWorker(BBjumpKinds jumpKind,
18035                                             BasicBlock* afterBlk,
18036                                             unsigned    regionIndex,
18037                                             bool        putInTryRegion)
18038 {
18039     /* Insert the new block */
18040     BasicBlock* afterBlkNext = afterBlk->bbNext;
18041     (void)afterBlkNext; // prevent "unused variable" error from GCC
18042     BasicBlock* newBlk = fgNewBBafter(jumpKind, afterBlk, false);
18043
18044     if (putInTryRegion)
18045     {
18046         noway_assert(regionIndex <= MAX_XCPTN_INDEX);
18047         newBlk->bbTryIndex = (unsigned short)regionIndex;
18048         newBlk->bbHndIndex = bbFindInnermostHandlerRegionContainingTryRegion(regionIndex);
18049     }
18050     else
18051     {
18052         newBlk->bbTryIndex = bbFindInnermostTryRegionContainingHandlerRegion(regionIndex);
18053         noway_assert(regionIndex <= MAX_XCPTN_INDEX);
18054         newBlk->bbHndIndex = (unsigned short)regionIndex;
18055     }
18056
18057     // We're going to compare for equal try regions (to handle the case of 'mutually protect'
18058     // regions). We need to save off the current try region, otherwise we might change it
18059     // before it gets compared later, thereby making future comparisons fail.
18060
18061     BasicBlock* newTryBeg;
18062     BasicBlock* newTryLast;
18063     (void)ehInitTryBlockRange(newBlk, &newTryBeg, &newTryLast);
18064
18065     unsigned  XTnum;
18066     EHblkDsc* HBtab;
18067
18068     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
18069     {
18070         // Is afterBlk at the end of a try region?
18071         if (HBtab->ebdTryLast == afterBlk)
18072         {
18073             noway_assert(afterBlkNext == newBlk->bbNext);
18074
18075             bool extendTryRegion = false;
18076             if (newBlk->hasTryIndex())
18077             {
18078                 // We're adding a block after the last block of some try region. Do
18079                 // we extend the try region to include the block, or not?
18080                 // If the try region is exactly the same as the try region
18081                 // associated with the new block (based on the block's try index,
18082                 // which represents the innermost try the block is a part of), then
18083                 // we extend it.
18084                 // If the try region is a "parent" try region -- an enclosing try region
18085                 // that has the same last block as the new block's try region -- then
18086                 // we also extend. For example:
18087                 //      try { // 1
18088                 //          ...
18089                 //          try { // 2
18090                 //          ...
18091                 //      } /* 2 */ } /* 1 */
18092                 // This example is meant to indicate that both try regions 1 and 2 end at
18093                 // the same block, and we're extending 2. Thus, we must also extend 1. If we
18094                 // only extended 2, we would break proper nesting. (Dev11 bug 137967)
18095
18096                 extendTryRegion = HBtab->ebdIsSameTry(newTryBeg, newTryLast) || bbInTryRegions(XTnum, newBlk);
18097             }
18098
18099             // Does newBlk extend this try region?
18100             if (extendTryRegion)
18101             {
18102                 // Yes, newBlk extends this try region
18103
18104                 // newBlk is the now the new try last block
18105                 fgSetTryEnd(HBtab, newBlk);
18106             }
18107         }
18108
18109         // Is afterBlk at the end of a handler region?
18110         if (HBtab->ebdHndLast == afterBlk)
18111         {
18112             noway_assert(afterBlkNext == newBlk->bbNext);
18113
18114             // Does newBlk extend this handler region?
18115             bool extendHndRegion = false;
18116             if (newBlk->hasHndIndex())
18117             {
18118                 // We're adding a block after the last block of some handler region. Do
18119                 // we extend the handler region to include the block, or not?
18120                 // If the handler region is exactly the same as the handler region
18121                 // associated with the new block (based on the block's handler index,
18122                 // which represents the innermost handler the block is a part of), then
18123                 // we extend it.
18124                 // If the handler region is a "parent" handler region -- an enclosing
18125                 // handler region that has the same last block as the new block's handler
18126                 // region -- then we also extend. For example:
18127                 //      catch { // 1
18128                 //          ...
18129                 //          catch { // 2
18130                 //          ...
18131                 //      } /* 2 */ } /* 1 */
18132                 // This example is meant to indicate that both handler regions 1 and 2 end at
18133                 // the same block, and we're extending 2. Thus, we must also extend 1. If we
18134                 // only extended 2, we would break proper nesting. (Dev11 bug 372051)
18135
18136                 extendHndRegion = bbInHandlerRegions(XTnum, newBlk);
18137             }
18138
18139             if (extendHndRegion)
18140             {
18141                 // Yes, newBlk extends this handler region
18142
18143                 // newBlk is now the last block of the handler.
18144                 fgSetHndEnd(HBtab, newBlk);
18145             }
18146         }
18147     }
18148
18149     /* If afterBlk falls through, we insert a jump around newBlk */
18150     fgConnectFallThrough(afterBlk, newBlk->bbNext);
18151
18152 #ifdef DEBUG
18153     fgVerifyHandlerTab();
18154 #endif
18155
18156     return newBlk;
18157 }
18158
18159 /*****************************************************************************
18160  */
18161
18162 /* static */
18163 unsigned Compiler::acdHelper(SpecialCodeKind codeKind)
18164 {
18165     switch (codeKind)
18166     {
18167         case SCK_RNGCHK_FAIL:
18168             return CORINFO_HELP_RNGCHKFAIL;
18169         case SCK_ARG_EXCPN:
18170             return CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
18171         case SCK_ARG_RNG_EXCPN:
18172             return CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
18173         case SCK_DIV_BY_ZERO:
18174             return CORINFO_HELP_THROWDIVZERO;
18175         case SCK_ARITH_EXCPN:
18176             return CORINFO_HELP_OVERFLOW;
18177         default:
18178             assert(!"Bad codeKind");
18179             return 0;
18180     }
18181 }
18182
18183 /*****************************************************************************
18184  *
18185  *  Find/create an added code entry associated with the given block and with
18186  *  the given kind.
18187  */
18188
18189 BasicBlock* Compiler::fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, SpecialCodeKind kind, unsigned stkDepth)
18190 {
18191     // Record that the code will call a THROW_HELPER
18192     // so on Windows Amd64 we can allocate the 4 outgoing
18193     // arg slots on the stack frame if there are no other calls.
18194     compUsesThrowHelper = true;
18195
18196     if (!fgUseThrowHelperBlocks())
18197     {
18198         return nullptr;
18199     }
18200
18201     const static BBjumpKinds jumpKinds[] = {
18202         BBJ_NONE,   // SCK_NONE
18203         BBJ_THROW,  // SCK_RNGCHK_FAIL
18204         BBJ_ALWAYS, // SCK_PAUSE_EXEC
18205         BBJ_THROW,  // SCK_DIV_BY_ZERO
18206         BBJ_THROW,  // SCK_ARITH_EXCP, SCK_OVERFLOW
18207         BBJ_THROW,  // SCK_ARG_EXCPN
18208         BBJ_THROW,  // SCK_ARG_RNG_EXCPN
18209     };
18210
18211     noway_assert(sizeof(jumpKinds) == SCK_COUNT); // sanity check
18212
18213     /* First look for an existing entry that matches what we're looking for */
18214
18215     AddCodeDsc* add = fgFindExcptnTarget(kind, refData);
18216
18217     if (add) // found it
18218     {
18219 #if !FEATURE_FIXED_OUT_ARGS
18220         // If different range checks happen at different stack levels,
18221         // they can't all jump to the same "call @rngChkFailed" AND have
18222         // frameless methods, as the rngChkFailed may need to unwind the
18223         // stack, and we have to be able to report the stack level.
18224         //
18225         // The following check forces most methods that reference an
18226         // array element in a parameter list to have an EBP frame,
18227         // this restriction could be removed with more careful code
18228         // generation for BBJ_THROW (i.e. range check failed).
18229         //
18230         // For Linux/x86, we possibly need to insert stack alignment adjustment
18231         // before the first stack argument pushed for every call. But we
18232         // don't know what the stack alignment adjustment will be when
18233         // we morph a tree that calls fgAddCodeRef(), so the stack depth
18234         // number will be incorrect. For now, simply force all functions with
18235         // these helpers to have EBP frames. It might be possible to make
18236         // this less conservative. E.g., for top-level (not nested) calls
18237         // without stack args, the stack pointer hasn't changed and stack
18238         // depth will be known to be zero. Or, figure out a way to update
18239         // or generate all required helpers after all stack alignment
18240         // has been added, and the stack level at each call to fgAddCodeRef()
18241         // is known, or can be recalculated.
18242         CLANG_FORMAT_COMMENT_ANCHOR;
18243
18244 #if defined(UNIX_X86_ABI)
18245         codeGen->setFrameRequired(true);
18246         codeGen->setFramePointerRequiredGCInfo(true);
18247 #else  // !defined(UNIX_X86_ABI)
18248         if (add->acdStkLvl != stkDepth)
18249         {
18250             codeGen->setFrameRequired(true);
18251             codeGen->setFramePointerRequiredGCInfo(true);
18252         }
18253 #endif // !defined(UNIX_X86_ABI)
18254 #endif // !FEATURE_FIXED_OUT_ARGS
18255
18256         return add->acdDstBlk;
18257     }
18258
18259     /* We have to allocate a new entry and prepend it to the list */
18260
18261     add          = new (this, CMK_Unknown) AddCodeDsc;
18262     add->acdData = refData;
18263     add->acdKind = kind;
18264     add->acdNext = fgAddCodeList;
18265 #if !FEATURE_FIXED_OUT_ARGS
18266     add->acdStkLvl     = stkDepth;
18267     add->acdStkLvlInit = false;
18268 #endif // !FEATURE_FIXED_OUT_ARGS
18269
18270     fgAddCodeList = add;
18271
18272     /* Create the target basic block */
18273
18274     BasicBlock* newBlk;
18275
18276     newBlk = add->acdDstBlk = fgNewBBinRegion(jumpKinds[kind], srcBlk, /* runRarely */ true, /* insertAtEnd */ true);
18277
18278     add->acdDstBlk->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
18279
18280 #ifdef DEBUG
18281     if (verbose)
18282     {
18283         const char* msgWhere = "";
18284         if (!srcBlk->hasTryIndex() && !srcBlk->hasHndIndex())
18285         {
18286             msgWhere = "non-EH region";
18287         }
18288         else if (!srcBlk->hasTryIndex())
18289         {
18290             msgWhere = "handler";
18291         }
18292         else if (!srcBlk->hasHndIndex())
18293         {
18294             msgWhere = "try";
18295         }
18296         else if (srcBlk->getTryIndex() < srcBlk->getHndIndex())
18297         {
18298             msgWhere = "try";
18299         }
18300         else
18301         {
18302             msgWhere = "handler";
18303         }
18304
18305         const char* msg;
18306         switch (kind)
18307         {
18308             case SCK_RNGCHK_FAIL:
18309                 msg = " for RNGCHK_FAIL";
18310                 break;
18311             case SCK_PAUSE_EXEC:
18312                 msg = " for PAUSE_EXEC";
18313                 break;
18314             case SCK_DIV_BY_ZERO:
18315                 msg = " for DIV_BY_ZERO";
18316                 break;
18317             case SCK_OVERFLOW:
18318                 msg = " for OVERFLOW";
18319                 break;
18320             case SCK_ARG_EXCPN:
18321                 msg = " for ARG_EXCPN";
18322                 break;
18323             case SCK_ARG_RNG_EXCPN:
18324                 msg = " for ARG_RNG_EXCPN";
18325                 break;
18326             default:
18327                 msg = " for ??";
18328                 break;
18329         }
18330
18331         printf("\nfgAddCodeRef - Add BB in %s%s, new block %s, stkDepth is %d\n", msgWhere, msg,
18332                add->acdDstBlk->dspToString(), stkDepth);
18333     }
18334 #endif // DEBUG
18335
18336 #ifdef DEBUG
18337     newBlk->bbTgtStkDepth = stkDepth;
18338 #endif // DEBUG
18339
18340     /* Mark the block as added by the compiler and not removable by future flow
18341        graph optimizations. Note that no bbJumpDest points to these blocks. */
18342
18343     newBlk->bbFlags |= BBF_IMPORTED;
18344     newBlk->bbFlags |= BBF_DONT_REMOVE;
18345
18346     /* Remember that we're adding a new basic block */
18347
18348     fgAddCodeModf      = true;
18349     fgRngChkThrowAdded = true;
18350
18351     /* Now figure out what code to insert */
18352
18353     GenTreeCall* tree;
18354     int          helper = CORINFO_HELP_UNDEF;
18355
18356     switch (kind)
18357     {
18358         case SCK_RNGCHK_FAIL:
18359             helper = CORINFO_HELP_RNGCHKFAIL;
18360             break;
18361
18362         case SCK_DIV_BY_ZERO:
18363             helper = CORINFO_HELP_THROWDIVZERO;
18364             break;
18365
18366         case SCK_ARITH_EXCPN:
18367             helper = CORINFO_HELP_OVERFLOW;
18368             noway_assert(SCK_OVERFLOW == SCK_ARITH_EXCPN);
18369             break;
18370
18371         case SCK_ARG_EXCPN:
18372             helper = CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
18373             break;
18374
18375         case SCK_ARG_RNG_EXCPN:
18376             helper = CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
18377             break;
18378
18379         // case SCK_PAUSE_EXEC:
18380         //     noway_assert(!"add code to pause exec");
18381
18382         default:
18383             noway_assert(!"unexpected code addition kind");
18384             return nullptr;
18385     }
18386
18387     noway_assert(helper != CORINFO_HELP_UNDEF);
18388
18389     // Add the appropriate helper call.
18390     tree = gtNewHelperCallNode(helper, TYP_VOID);
18391
18392     // There are no args here but fgMorphArgs has side effects
18393     // such as setting the outgoing arg area (which is necessary
18394     // on AMD if there are any calls).
18395     tree = fgMorphArgs(tree);
18396
18397     // Store the tree in the new basic block.
18398     assert(!srcBlk->isEmpty());
18399     if (!srcBlk->IsLIR())
18400     {
18401         fgInsertStmtAtEnd(newBlk, fgNewStmtFromTree(tree));
18402     }
18403     else
18404     {
18405         LIR::AsRange(newBlk).InsertAtEnd(LIR::SeqTree(this, tree));
18406     }
18407
18408     return add->acdDstBlk;
18409 }
18410
18411 /*****************************************************************************
18412  * Finds the block to jump to, to throw a given kind of exception
18413  * We maintain a cache of one AddCodeDsc for each kind, to make searching fast.
18414  * Note : Each block uses the same (maybe shared) block as the jump target for
18415  * a given type of exception
18416  */
18417
18418 Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData)
18419 {
18420     assert(fgUseThrowHelperBlocks());
18421     if (!(fgExcptnTargetCache[kind] && // Try the cached value first
18422           fgExcptnTargetCache[kind]->acdData == refData))
18423     {
18424         // Too bad, have to search for the jump target for the exception
18425
18426         AddCodeDsc* add = nullptr;
18427
18428         for (add = fgAddCodeList; add != nullptr; add = add->acdNext)
18429         {
18430             if (add->acdData == refData && add->acdKind == kind)
18431             {
18432                 break;
18433             }
18434         }
18435
18436         fgExcptnTargetCache[kind] = add; // Cache it
18437     }
18438
18439     return fgExcptnTargetCache[kind];
18440 }
18441
18442 /*****************************************************************************
18443  *
18444  *  The given basic block contains an array range check; return the label this
18445  *  range check is to jump to upon failure.
18446  */
18447
18448 BasicBlock* Compiler::fgRngChkTarget(BasicBlock* block, unsigned stkDepth, SpecialCodeKind kind)
18449 {
18450 #ifdef DEBUG
18451     if (verbose)
18452     {
18453         printf("*** Computing fgRngChkTarget for block BB%02u to stkDepth %d\n", block->bbNum, stkDepth);
18454         if (!block->IsLIR())
18455         {
18456             gtDispTree(compCurStmt);
18457         }
18458     }
18459 #endif // DEBUG
18460
18461     /* We attach the target label to the containing try block (if any) */
18462     noway_assert(!compIsForInlining());
18463     return fgAddCodeRef(block, bbThrowIndex(block), kind, stkDepth);
18464 }
18465
18466 // Sequences the tree.
18467 // prevTree is what gtPrev of the first node in execution order gets set to.
18468 // Returns the first node (execution order) in the sequenced tree.
18469 GenTree* Compiler::fgSetTreeSeq(GenTree* tree, GenTree* prevTree, bool isLIR)
18470 {
18471     GenTree list;
18472
18473     if (prevTree == nullptr)
18474     {
18475         prevTree = &list;
18476     }
18477     fgTreeSeqLst = prevTree;
18478     fgTreeSeqNum = 0;
18479     fgTreeSeqBeg = nullptr;
18480     fgSetTreeSeqHelper(tree, isLIR);
18481
18482     GenTree* result = prevTree->gtNext;
18483     if (prevTree == &list)
18484     {
18485         list.gtNext->gtPrev = nullptr;
18486     }
18487
18488     return result;
18489 }
18490
18491 /*****************************************************************************
18492  *
18493  *  Assigns sequence numbers to the given tree and its sub-operands, and
18494  *  threads all the nodes together via the 'gtNext' and 'gtPrev' fields.
18495  *  Uses 'global' - fgTreeSeqLst
18496  */
18497
18498 void Compiler::fgSetTreeSeqHelper(GenTree* tree, bool isLIR)
18499 {
18500     genTreeOps oper;
18501     unsigned   kind;
18502
18503     noway_assert(tree);
18504     assert(!IsUninitialized(tree));
18505     noway_assert(tree->gtOper != GT_STMT);
18506
18507     /* Figure out what kind of a node we have */
18508
18509     oper = tree->OperGet();
18510     kind = tree->OperKind();
18511
18512     /* Is this a leaf/constant node? */
18513
18514     if (kind & (GTK_CONST | GTK_LEAF))
18515     {
18516         fgSetTreeSeqFinish(tree, isLIR);
18517         return;
18518     }
18519
18520     // Special handling for dynamic block ops.
18521     if (tree->OperIsDynBlkOp())
18522     {
18523         GenTreeDynBlk* dynBlk;
18524         GenTree*       src;
18525         GenTree*       asg = tree;
18526         if (tree->OperGet() == GT_ASG)
18527         {
18528             dynBlk = tree->gtGetOp1()->AsDynBlk();
18529             src    = tree->gtGetOp2();
18530         }
18531         else
18532         {
18533             dynBlk = tree->AsDynBlk();
18534             src    = dynBlk->Data();
18535             asg    = nullptr;
18536         }
18537         GenTree* sizeNode = dynBlk->gtDynamicSize;
18538         GenTree* dstAddr  = dynBlk->Addr();
18539         if (dynBlk->gtEvalSizeFirst)
18540         {
18541             fgSetTreeSeqHelper(sizeNode, isLIR);
18542         }
18543         if (tree->gtFlags & GTF_REVERSE_OPS)
18544         {
18545             fgSetTreeSeqHelper(src, isLIR);
18546             fgSetTreeSeqHelper(dstAddr, isLIR);
18547         }
18548         else
18549         {
18550             fgSetTreeSeqHelper(dstAddr, isLIR);
18551             fgSetTreeSeqHelper(src, isLIR);
18552         }
18553         if (!dynBlk->gtEvalSizeFirst)
18554         {
18555             fgSetTreeSeqHelper(sizeNode, isLIR);
18556         }
18557         fgSetTreeSeqFinish(dynBlk, isLIR);
18558         if (asg != nullptr)
18559         {
18560             fgSetTreeSeqFinish(asg, isLIR);
18561         }
18562         return;
18563     }
18564
18565     /* Is it a 'simple' unary/binary operator? */
18566
18567     if (kind & GTK_SMPOP)
18568     {
18569         GenTree* op1 = tree->gtOp.gtOp1;
18570         GenTree* op2 = tree->gtGetOp2IfPresent();
18571
18572         // Special handling for GT_LIST
18573         if (tree->OperGet() == GT_LIST)
18574         {
18575             // First, handle the list items, which will be linked in forward order.
18576             // As we go, we will link the GT_LIST nodes in reverse order - we will number
18577             // them and update fgTreeSeqList in a subsequent traversal.
18578             GenTree* nextList = tree;
18579             GenTree* list     = nullptr;
18580             while (nextList != nullptr && nextList->OperGet() == GT_LIST)
18581             {
18582                 list              = nextList;
18583                 GenTree* listItem = list->gtOp.gtOp1;
18584                 fgSetTreeSeqHelper(listItem, isLIR);
18585                 nextList = list->gtOp.gtOp2;
18586                 if (nextList != nullptr)
18587                 {
18588                     nextList->gtNext = list;
18589                 }
18590                 list->gtPrev = nextList;
18591             }
18592             // Next, handle the GT_LIST nodes.
18593             // Note that fgSetTreeSeqFinish() sets the gtNext to null, so we need to capture the nextList
18594             // before we call that method.
18595             nextList = list;
18596             do
18597             {
18598                 assert(list != nullptr);
18599                 list     = nextList;
18600                 nextList = list->gtNext;
18601                 fgSetTreeSeqFinish(list, isLIR);
18602             } while (list != tree);
18603             return;
18604         }
18605
18606         /* Special handling for AddrMode */
18607         if (tree->OperIsAddrMode())
18608         {
18609             bool reverse = ((tree->gtFlags & GTF_REVERSE_OPS) != 0);
18610             if (reverse)
18611             {
18612                 assert(op1 != nullptr && op2 != nullptr);
18613                 fgSetTreeSeqHelper(op2, isLIR);
18614             }
18615             if (op1 != nullptr)
18616             {
18617                 fgSetTreeSeqHelper(op1, isLIR);
18618             }
18619             if (!reverse && op2 != nullptr)
18620             {
18621                 fgSetTreeSeqHelper(op2, isLIR);
18622             }
18623
18624             fgSetTreeSeqFinish(tree, isLIR);
18625             return;
18626         }
18627
18628         /* Check for a nilary operator */
18629
18630         if (op1 == nullptr)
18631         {
18632             noway_assert(op2 == nullptr);
18633             fgSetTreeSeqFinish(tree, isLIR);
18634             return;
18635         }
18636
18637         /* Is this a unary operator?
18638          * Although UNARY GT_IND has a special structure */
18639
18640         if (oper == GT_IND)
18641         {
18642             /* Visit the indirection first - op2 may point to the
18643              * jump Label for array-index-out-of-range */
18644
18645             fgSetTreeSeqHelper(op1, isLIR);
18646             fgSetTreeSeqFinish(tree, isLIR);
18647             return;
18648         }
18649
18650         /* Now this is REALLY a unary operator */
18651
18652         if (!op2)
18653         {
18654             /* Visit the (only) operand and we're done */
18655
18656             fgSetTreeSeqHelper(op1, isLIR);
18657             fgSetTreeSeqFinish(tree, isLIR);
18658             return;
18659         }
18660
18661         /*
18662            For "real" ?: operators, we make sure the order is
18663            as follows:
18664
18665                condition
18666                1st operand
18667                GT_COLON
18668                2nd operand
18669                GT_QMARK
18670         */
18671
18672         if (oper == GT_QMARK)
18673         {
18674             noway_assert((tree->gtFlags & GTF_REVERSE_OPS) == 0);
18675
18676             fgSetTreeSeqHelper(op1, isLIR);
18677             // Here, for the colon, the sequence does not actually represent "order of evaluation":
18678             // one or the other of the branches is executed, not both.  Still, to make debugging checks
18679             // work, we want the sequence to match the order in which we'll generate code, which means
18680             // "else" clause then "then" clause.
18681             fgSetTreeSeqHelper(op2->AsColon()->ElseNode(), isLIR);
18682             fgSetTreeSeqHelper(op2, isLIR);
18683             fgSetTreeSeqHelper(op2->AsColon()->ThenNode(), isLIR);
18684
18685             fgSetTreeSeqFinish(tree, isLIR);
18686             return;
18687         }
18688
18689         if (oper == GT_COLON)
18690         {
18691             fgSetTreeSeqFinish(tree, isLIR);
18692             return;
18693         }
18694
18695         /* This is a binary operator */
18696
18697         if (tree->gtFlags & GTF_REVERSE_OPS)
18698         {
18699             fgSetTreeSeqHelper(op2, isLIR);
18700             fgSetTreeSeqHelper(op1, isLIR);
18701         }
18702         else
18703         {
18704             fgSetTreeSeqHelper(op1, isLIR);
18705             fgSetTreeSeqHelper(op2, isLIR);
18706         }
18707
18708         fgSetTreeSeqFinish(tree, isLIR);
18709         return;
18710     }
18711
18712     /* See what kind of a special operator we have here */
18713
18714     switch (oper)
18715     {
18716         case GT_FIELD:
18717             noway_assert(tree->gtField.gtFldObj == nullptr);
18718             break;
18719
18720         case GT_CALL:
18721
18722             /* We'll evaluate the 'this' argument value first */
18723             if (tree->gtCall.gtCallObjp)
18724             {
18725                 fgSetTreeSeqHelper(tree->gtCall.gtCallObjp, isLIR);
18726             }
18727
18728             /* We'll evaluate the arguments next, left to right
18729              * NOTE: setListOrder needs cleanup - eliminate the #ifdef afterwards */
18730
18731             if (tree->gtCall.gtCallArgs)
18732             {
18733                 fgSetTreeSeqHelper(tree->gtCall.gtCallArgs, isLIR);
18734             }
18735
18736             /* Evaluate the temp register arguments list
18737              * This is a "hidden" list and its only purpose is to
18738              * extend the life of temps until we make the call */
18739
18740             if (tree->gtCall.gtCallLateArgs)
18741             {
18742                 fgSetTreeSeqHelper(tree->gtCall.gtCallLateArgs, isLIR);
18743             }
18744
18745             if ((tree->gtCall.gtCallType == CT_INDIRECT) && (tree->gtCall.gtCallCookie != nullptr))
18746             {
18747                 fgSetTreeSeqHelper(tree->gtCall.gtCallCookie, isLIR);
18748             }
18749
18750             if (tree->gtCall.gtCallType == CT_INDIRECT)
18751             {
18752                 fgSetTreeSeqHelper(tree->gtCall.gtCallAddr, isLIR);
18753             }
18754
18755             if (tree->gtCall.gtControlExpr)
18756             {
18757                 fgSetTreeSeqHelper(tree->gtCall.gtControlExpr, isLIR);
18758             }
18759
18760             break;
18761
18762         case GT_ARR_ELEM:
18763
18764             fgSetTreeSeqHelper(tree->gtArrElem.gtArrObj, isLIR);
18765
18766             unsigned dim;
18767             for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
18768             {
18769                 fgSetTreeSeqHelper(tree->gtArrElem.gtArrInds[dim], isLIR);
18770             }
18771
18772             break;
18773
18774         case GT_ARR_OFFSET:
18775             fgSetTreeSeqHelper(tree->gtArrOffs.gtOffset, isLIR);
18776             fgSetTreeSeqHelper(tree->gtArrOffs.gtIndex, isLIR);
18777             fgSetTreeSeqHelper(tree->gtArrOffs.gtArrObj, isLIR);
18778             break;
18779
18780         case GT_CMPXCHG:
18781             // Evaluate the trees left to right
18782             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpLocation, isLIR);
18783             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpValue, isLIR);
18784             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpComparand, isLIR);
18785             break;
18786
18787         case GT_ARR_BOUNDS_CHECK:
18788 #ifdef FEATURE_SIMD
18789         case GT_SIMD_CHK:
18790 #endif // FEATURE_SIMD
18791 #ifdef FEATURE_HW_INTRINSICS
18792         case GT_HW_INTRINSIC_CHK:
18793 #endif // FEATURE_HW_INTRINSICS
18794             // Evaluate the trees left to right
18795             fgSetTreeSeqHelper(tree->gtBoundsChk.gtIndex, isLIR);
18796             fgSetTreeSeqHelper(tree->gtBoundsChk.gtArrLen, isLIR);
18797             break;
18798
18799         case GT_STORE_DYN_BLK:
18800         case GT_DYN_BLK:
18801             noway_assert(!"DYN_BLK nodes should be sequenced as a special case");
18802             break;
18803
18804         case GT_INDEX_ADDR:
18805             // Evaluate the index first, then the array address
18806             assert((tree->gtFlags & GTF_REVERSE_OPS) != 0);
18807             fgSetTreeSeqHelper(tree->AsIndexAddr()->Index(), isLIR);
18808             fgSetTreeSeqHelper(tree->AsIndexAddr()->Arr(), isLIR);
18809             break;
18810
18811         default:
18812 #ifdef DEBUG
18813             gtDispTree(tree);
18814             noway_assert(!"unexpected operator");
18815 #endif // DEBUG
18816             break;
18817     }
18818
18819     fgSetTreeSeqFinish(tree, isLIR);
18820 }
18821
18822 void Compiler::fgSetTreeSeqFinish(GenTree* tree, bool isLIR)
18823 {
18824     // If we are sequencing for LIR:
18825     // - Clear the reverse ops flag
18826     // - If we are processing a node that does not appear in LIR, do not add it to the list.
18827     if (isLIR)
18828     {
18829         tree->gtFlags &= ~GTF_REVERSE_OPS;
18830
18831         if ((tree->OperGet() == GT_LIST) || (tree->OperGet() == GT_ARGPLACE) ||
18832             (tree->OperGet() == GT_FIELD_LIST && !tree->AsFieldList()->IsFieldListHead()))
18833         {
18834             return;
18835         }
18836     }
18837
18838     /* Append to the node list */
18839     ++fgTreeSeqNum;
18840
18841 #ifdef DEBUG
18842     tree->gtSeqNum = fgTreeSeqNum;
18843
18844     if (verbose & 0)
18845     {
18846         printf("SetTreeOrder: ");
18847         printTreeID(fgTreeSeqLst);
18848         printf(" followed by ");
18849         printTreeID(tree);
18850         printf("\n");
18851     }
18852 #endif // DEBUG
18853
18854     fgTreeSeqLst->gtNext = tree;
18855     tree->gtNext         = nullptr;
18856     tree->gtPrev         = fgTreeSeqLst;
18857     fgTreeSeqLst         = tree;
18858
18859     /* Remember the very first node */
18860
18861     if (!fgTreeSeqBeg)
18862     {
18863         fgTreeSeqBeg = tree;
18864         assert(tree->gtSeqNum == 1);
18865     }
18866 }
18867
18868 /*****************************************************************************
18869  *
18870  *  Figure out the order in which operators should be evaluated, along with
18871  *  other information (such as the register sets trashed by each subtree).
18872  *  Also finds blocks that need GC polls and inserts them as needed.
18873  */
18874
18875 void Compiler::fgSetBlockOrder()
18876 {
18877 #ifdef DEBUG
18878     if (verbose)
18879     {
18880         printf("*************** In fgSetBlockOrder()\n");
18881     }
18882 #endif // DEBUG
18883
18884 #ifdef DEBUG
18885     BasicBlock::s_nMaxTrees = 0;
18886 #endif
18887
18888     /* Walk the basic blocks to assign sequence numbers */
18889
18890     /* If we don't compute the doms, then we never mark blocks as loops. */
18891     if (fgDomsComputed)
18892     {
18893         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18894         {
18895             /* If this block is a loop header, mark it appropriately */
18896
18897             if (block->isLoopHead())
18898             {
18899                 fgMarkLoopHead(block);
18900             }
18901         }
18902     }
18903     // only enable fully interruptible code for if we're hijacking.
18904     else if (GCPOLL_NONE == opts.compGCPollType)
18905     {
18906         /* If we don't have the dominators, use an abbreviated test for fully interruptible.  If there are
18907          * any back edges, check the source and destination blocks to see if they're GC Safe.  If not, then
18908          * go fully interruptible. */
18909
18910         /* XXX Mon 1/21/2008
18911          * Wouldn't it be nice to have a block iterator that can do this loop?
18912          */
18913         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18914         {
18915 // true if the edge is forward, or if it is a back edge and either the source and dest are GC safe.
18916 #define EDGE_IS_GC_SAFE(src, dst)                                                                                      \
18917     (((src)->bbNum < (dst)->bbNum) || (((src)->bbFlags | (dst)->bbFlags) & BBF_GC_SAFE_POINT))
18918
18919             bool partiallyInterruptible = true;
18920             switch (block->bbJumpKind)
18921             {
18922                 case BBJ_COND:
18923                 case BBJ_ALWAYS:
18924                     partiallyInterruptible = EDGE_IS_GC_SAFE(block, block->bbJumpDest);
18925                     break;
18926
18927                 case BBJ_SWITCH:
18928
18929                     unsigned jumpCnt;
18930                     jumpCnt = block->bbJumpSwt->bbsCount;
18931                     BasicBlock** jumpPtr;
18932                     jumpPtr = block->bbJumpSwt->bbsDstTab;
18933
18934                     do
18935                     {
18936                         partiallyInterruptible &= EDGE_IS_GC_SAFE(block, *jumpPtr);
18937                     } while (++jumpPtr, --jumpCnt);
18938
18939                     break;
18940
18941                 default:
18942                     break;
18943             }
18944
18945             if (!partiallyInterruptible)
18946             {
18947                 // DDB 204533:
18948                 // The GC encoding for fully interruptible methods does not
18949                 // support more than 1023 pushed arguments, so we can't set
18950                 // genInterruptible here when we have 1024 or more pushed args
18951                 //
18952                 if (compCanEncodePtrArgCntMax())
18953                 {
18954                     genInterruptible = true;
18955                 }
18956                 break;
18957             }
18958 #undef EDGE_IS_GC_SAFE
18959         }
18960     }
18961
18962     if (!fgGCPollsCreated)
18963     {
18964         fgCreateGCPolls();
18965     }
18966
18967     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18968     {
18969
18970 #if FEATURE_FASTTAILCALL
18971 #ifndef JIT32_GCENCODER
18972         if (block->endsWithTailCallOrJmp(this, true) && optReachWithoutCall(fgFirstBB, block))
18973         {
18974             // We have a tail call that is reachable without making any other
18975             // 'normal' call that would have counted as a GC Poll.  If we were
18976             // using polls, all return blocks meeting this criteria would have
18977             // already added polls and then marked as being GC safe
18978             // (BBF_GC_SAFE_POINT). Thus we can only reach here when *NOT*
18979             // using GC polls, but instead relying on the JIT to generate
18980             // fully-interruptible code.
18981             noway_assert(GCPOLL_NONE == opts.compGCPollType);
18982
18983             // This tail call might combine with other tail calls to form a
18984             // loop.  Thus we need to either add a poll, or make the method
18985             // fully interruptible.  I chose the later because that's what
18986             // JIT64 does.
18987             genInterruptible = true;
18988         }
18989 #endif // !JIT32_GCENCODER
18990 #endif // FEATURE_FASTTAILCALL
18991
18992         fgSetBlockOrder(block);
18993     }
18994
18995     /* Remember that now the tree list is threaded */
18996
18997     fgStmtListThreaded = true;
18998
18999 #ifdef DEBUG
19000     if (verbose)
19001     {
19002         printf("The biggest BB has %4u tree nodes\n", BasicBlock::s_nMaxTrees);
19003     }
19004     fgDebugCheckLinks();
19005 #endif // DEBUG
19006 }
19007
19008 /*****************************************************************************/
19009
19010 void Compiler::fgSetStmtSeq(GenTree* tree)
19011 {
19012     GenTree list; // helper node that we use to start the StmtList
19013                   // It's located in front of the first node in the list
19014
19015     noway_assert(tree->gtOper == GT_STMT);
19016
19017     /* Assign numbers and next/prev links for this tree */
19018
19019     fgTreeSeqNum = 0;
19020     fgTreeSeqLst = &list;
19021     fgTreeSeqBeg = nullptr;
19022
19023     fgSetTreeSeqHelper(tree->gtStmt.gtStmtExpr, false);
19024
19025     /* Record the address of the first node */
19026
19027     tree->gtStmt.gtStmtList = fgTreeSeqBeg;
19028
19029 #ifdef DEBUG
19030
19031     if (list.gtNext->gtPrev != &list)
19032     {
19033         printf("&list ");
19034         printTreeID(&list);
19035         printf(" != list.next->prev ");
19036         printTreeID(list.gtNext->gtPrev);
19037         printf("\n");
19038         goto BAD_LIST;
19039     }
19040
19041     GenTree* temp;
19042     GenTree* last;
19043     for (temp = list.gtNext, last = &list; temp; last = temp, temp = temp->gtNext)
19044     {
19045         if (temp->gtPrev != last)
19046         {
19047             printTreeID(temp);
19048             printf("->gtPrev = ");
19049             printTreeID(temp->gtPrev);
19050             printf(", but last = ");
19051             printTreeID(last);
19052             printf("\n");
19053
19054         BAD_LIST:;
19055
19056             printf("\n");
19057             gtDispTree(tree->gtStmt.gtStmtExpr);
19058             printf("\n");
19059
19060             for (GenTree* bad = &list; bad; bad = bad->gtNext)
19061             {
19062                 printf("  entry at ");
19063                 printTreeID(bad);
19064                 printf(" (prev=");
19065                 printTreeID(bad->gtPrev);
19066                 printf(",next=)");
19067                 printTreeID(bad->gtNext);
19068                 printf("\n");
19069             }
19070
19071             printf("\n");
19072             noway_assert(!"Badly linked tree");
19073             break;
19074         }
19075     }
19076 #endif // DEBUG
19077
19078     /* Fix the first node's 'prev' link */
19079
19080     noway_assert(list.gtNext->gtPrev == &list);
19081     list.gtNext->gtPrev = nullptr;
19082
19083 #ifdef DEBUG
19084     /* Keep track of the highest # of tree nodes */
19085
19086     if (BasicBlock::s_nMaxTrees < fgTreeSeqNum)
19087     {
19088         BasicBlock::s_nMaxTrees = fgTreeSeqNum;
19089     }
19090 #endif // DEBUG
19091 }
19092
19093 /*****************************************************************************/
19094
19095 void Compiler::fgSetBlockOrder(BasicBlock* block)
19096 {
19097     GenTree* tree;
19098
19099     tree = block->bbTreeList;
19100     if (!tree)
19101     {
19102         return;
19103     }
19104
19105     for (;;)
19106     {
19107         fgSetStmtSeq(tree);
19108
19109         /* Are there any more trees in this basic block? */
19110
19111         if (tree->gtNext == nullptr)
19112         {
19113             /* last statement in the tree list */
19114             noway_assert(block->lastStmt() == tree);
19115             break;
19116         }
19117
19118 #ifdef DEBUG
19119         if (block->bbTreeList == tree)
19120         {
19121             /* first statement in the list */
19122             noway_assert(tree->gtPrev->gtNext == nullptr);
19123         }
19124         else
19125         {
19126             noway_assert(tree->gtPrev->gtNext == tree);
19127         }
19128
19129         noway_assert(tree->gtNext->gtPrev == tree);
19130 #endif // DEBUG
19131
19132         tree = tree->gtNext;
19133     }
19134 }
19135
19136 //------------------------------------------------------------------------
19137 // fgGetFirstNode: Get the first node in the tree, in execution order
19138 //
19139 // Arguments:
19140 //    tree - The top node of the tree of interest
19141 //
19142 // Return Value:
19143 //    The first node in execution order, that belongs to tree.
19144 //
19145 // Assumptions:
19146 //     'tree' must either be a leaf, or all of its constituent nodes must be contiguous
19147 //     in execution order.
19148 //     TODO-Cleanup: Add a debug-only method that verifies this.
19149
19150 /* static */
19151 GenTree* Compiler::fgGetFirstNode(GenTree* tree)
19152 {
19153     GenTree* child = tree;
19154     while (child->NumChildren() > 0)
19155     {
19156         if (child->OperIsBinary() && child->IsReverseOp())
19157         {
19158             child = child->GetChild(1);
19159         }
19160         else
19161         {
19162             child = child->GetChild(0);
19163         }
19164     }
19165     return child;
19166 }
19167
19168 // Examine the bbTreeList and return the estimated code size for this block
19169 unsigned Compiler::fgGetCodeEstimate(BasicBlock* block)
19170 {
19171     unsigned costSz = 0; // estimate of blocks code size cost
19172
19173     switch (block->bbJumpKind)
19174     {
19175         case BBJ_NONE:
19176             costSz = 0;
19177             break;
19178         case BBJ_ALWAYS:
19179         case BBJ_EHCATCHRET:
19180         case BBJ_LEAVE:
19181         case BBJ_COND:
19182             costSz = 2;
19183             break;
19184         case BBJ_CALLFINALLY:
19185             costSz = 5;
19186             break;
19187         case BBJ_SWITCH:
19188             costSz = 10;
19189             break;
19190         case BBJ_THROW:
19191             costSz = 1; // We place a int3 after the code for a throw block
19192             break;
19193         case BBJ_EHFINALLYRET:
19194         case BBJ_EHFILTERRET:
19195             costSz = 1;
19196             break;
19197         case BBJ_RETURN: // return from method
19198             costSz = 3;
19199             break;
19200         default:
19201             noway_assert(!"Bad bbJumpKind");
19202             break;
19203     }
19204
19205     GenTree* tree = block->FirstNonPhiDef();
19206     if (tree)
19207     {
19208         do
19209         {
19210             noway_assert(tree->gtOper == GT_STMT);
19211
19212             if (tree->gtCostSz < MAX_COST)
19213             {
19214                 costSz += tree->gtCostSz;
19215             }
19216             else
19217             {
19218                 // We could walk the tree to find out the real gtCostSz,
19219                 // but just using MAX_COST for this trees code size works OK
19220                 costSz += tree->gtCostSz;
19221             }
19222
19223             tree = tree->gtNext;
19224         } while (tree);
19225     }
19226
19227     return costSz;
19228 }
19229
19230 #if DUMP_FLOWGRAPHS
19231
19232 struct escapeMapping_t
19233 {
19234     char        ch;
19235     const char* sub;
19236 };
19237
19238 // clang-format off
19239 static escapeMapping_t s_EscapeFileMapping[] =
19240 {
19241     {':', "="},
19242     {'<', "["},
19243     {'>', "]"},
19244     {';', "~semi~"},
19245     {'|', "~bar~"},
19246     {'&', "~amp~"},
19247     {'"', "~quot~"},
19248     {'*', "~star~"},
19249     {0, nullptr}
19250 };
19251
19252 static escapeMapping_t s_EscapeMapping[] =
19253 {
19254     {'<', "&lt;"},
19255     {'>', "&gt;"},
19256     {'&', "&amp;"},
19257     {'"', "&quot;"},
19258     {0, nullptr}
19259 };
19260 // clang-format on
19261
19262 const char* Compiler::fgProcessEscapes(const char* nameIn, escapeMapping_t* map)
19263 {
19264     const char* nameOut = nameIn;
19265     unsigned    lengthOut;
19266     unsigned    index;
19267     bool        match;
19268     bool        subsitutionRequired;
19269     const char* pChar;
19270
19271     lengthOut           = 1;
19272     subsitutionRequired = false;
19273     pChar               = nameIn;
19274     while (*pChar != '\0')
19275     {
19276         match = false;
19277         index = 0;
19278         while (map[index].ch != 0)
19279         {
19280             if (*pChar == map[index].ch)
19281             {
19282                 match = true;
19283                 break;
19284             }
19285             index++;
19286         }
19287         if (match)
19288         {
19289             subsitutionRequired = true;
19290             lengthOut += (unsigned)strlen(map[index].sub);
19291         }
19292         else
19293         {
19294             lengthOut += 1;
19295         }
19296         pChar++;
19297     }
19298
19299     if (subsitutionRequired)
19300     {
19301         char* newName = (char*)compGetMem(lengthOut, CMK_DebugOnly);
19302         char* pDest;
19303         pDest = newName;
19304         pChar = nameIn;
19305         while (*pChar != '\0')
19306         {
19307             match = false;
19308             index = 0;
19309             while (map[index].ch != 0)
19310             {
19311                 if (*pChar == map[index].ch)
19312                 {
19313                     match = true;
19314                     break;
19315                 }
19316                 index++;
19317             }
19318             if (match)
19319             {
19320                 strcpy(pDest, map[index].sub);
19321                 pDest += strlen(map[index].sub);
19322             }
19323             else
19324             {
19325                 *pDest++ = *pChar;
19326             }
19327             pChar++;
19328         }
19329         *pDest++ = '\0';
19330         nameOut  = (const char*)newName;
19331     }
19332
19333     return nameOut;
19334 }
19335
19336 static void fprintfDouble(FILE* fgxFile, double value)
19337 {
19338     assert(value >= 0.0);
19339
19340     if ((value >= 0.010) || (value == 0.0))
19341     {
19342         fprintf(fgxFile, "\"%7.3f\"", value);
19343     }
19344     else if (value >= 0.00010)
19345     {
19346         fprintf(fgxFile, "\"%7.5f\"", value);
19347     }
19348     else
19349     {
19350         fprintf(fgxFile, "\"%7E\"", value);
19351     }
19352 }
19353
19354 //------------------------------------------------------------------------
19355 // fgOpenFlowGraphFile: Open a file to dump either the xml or dot format flow graph
19356 //
19357 // Arguments:
19358 //    wbDontClose - A boolean out argument that indicates whether the caller should close the file
19359 //    phase       - A phase identifier to indicate which phase is associated with the dump
19360 //    type        - A (wide) string indicating the type of dump, "dot" or "xml"
19361 //
19362 // Return Value:
19363 //    Opens a file to which a flowgraph can be dumped, whose name is based on the current
19364 //    config vales.
19365
19366 FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR type)
19367 {
19368     FILE*       fgxFile;
19369     LPCWSTR     pattern  = nullptr;
19370     LPCWSTR     filename = nullptr;
19371     LPCWSTR     pathname = nullptr;
19372     const char* escapedString;
19373     bool        createDuplicateFgxFiles = true;
19374
19375 #ifdef DEBUG
19376     if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
19377     {
19378         pattern  = JitConfig.NgenDumpFg();
19379         filename = JitConfig.NgenDumpFgFile();
19380         pathname = JitConfig.NgenDumpFgDir();
19381     }
19382     else
19383     {
19384         pattern  = JitConfig.JitDumpFg();
19385         filename = JitConfig.JitDumpFgFile();
19386         pathname = JitConfig.JitDumpFgDir();
19387     }
19388 #endif // DEBUG
19389
19390     if (fgBBcount <= 1)
19391     {
19392         return nullptr;
19393     }
19394
19395     if (pattern == nullptr)
19396     {
19397         return nullptr;
19398     }
19399
19400     if (wcslen(pattern) == 0)
19401     {
19402         return nullptr;
19403     }
19404
19405     LPCWSTR phasePattern = JitConfig.JitDumpFgPhase();
19406     LPCWSTR phaseName    = PhaseShortNames[phase];
19407     if (phasePattern == nullptr)
19408     {
19409         if (phase != PHASE_DETERMINE_FIRST_COLD_BLOCK)
19410         {
19411             return nullptr;
19412         }
19413     }
19414     else if (*phasePattern != W('*'))
19415     {
19416         if (wcsstr(phasePattern, phaseName) == nullptr)
19417         {
19418             return nullptr;
19419         }
19420     }
19421
19422     if (*pattern != W('*'))
19423     {
19424         bool hasColon = (wcschr(pattern, W(':')) != nullptr);
19425
19426         if (hasColon)
19427         {
19428             const char* className = info.compClassName;
19429             if (*pattern == W('*'))
19430             {
19431                 pattern++;
19432             }
19433             else
19434             {
19435                 while ((*pattern != W(':')) && (*pattern != W('*')))
19436                 {
19437                     if (*pattern != *className)
19438                     {
19439                         return nullptr;
19440                     }
19441
19442                     pattern++;
19443                     className++;
19444                 }
19445                 if (*pattern == W('*'))
19446                 {
19447                     pattern++;
19448                 }
19449                 else
19450                 {
19451                     if (*className != 0)
19452                     {
19453                         return nullptr;
19454                     }
19455                 }
19456             }
19457             if (*pattern != W(':'))
19458             {
19459                 return nullptr;
19460             }
19461
19462             pattern++;
19463         }
19464
19465         const char* methodName = info.compMethodName;
19466         if (*pattern == W('*'))
19467         {
19468             pattern++;
19469         }
19470         else
19471         {
19472             while ((*pattern != 0) && (*pattern != W('*')))
19473             {
19474                 if (*pattern != *methodName)
19475                 {
19476                     return nullptr;
19477                 }
19478
19479                 pattern++;
19480                 methodName++;
19481             }
19482             if (*pattern == W('*'))
19483             {
19484                 pattern++;
19485             }
19486             else
19487             {
19488                 if (*methodName != 0)
19489                 {
19490                     return nullptr;
19491                 }
19492             }
19493         }
19494         if (*pattern != 0)
19495         {
19496             return nullptr;
19497         }
19498     }
19499
19500     if (filename == nullptr)
19501     {
19502         filename = W("default");
19503     }
19504
19505     if (wcscmp(filename, W("profiled")) == 0)
19506     {
19507         if (fgFirstBB->hasProfileWeight())
19508         {
19509             createDuplicateFgxFiles = true;
19510             goto ONE_FILE_PER_METHOD;
19511         }
19512         else
19513         {
19514             return nullptr;
19515         }
19516     }
19517     if (wcscmp(filename, W("hot")) == 0)
19518     {
19519         if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT)
19520
19521         {
19522             createDuplicateFgxFiles = true;
19523             goto ONE_FILE_PER_METHOD;
19524         }
19525         else
19526         {
19527             return nullptr;
19528         }
19529     }
19530     else if (wcscmp(filename, W("cold")) == 0)
19531     {
19532         if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD)
19533         {
19534             createDuplicateFgxFiles = true;
19535             goto ONE_FILE_PER_METHOD;
19536         }
19537         else
19538         {
19539             return nullptr;
19540         }
19541     }
19542     else if (wcscmp(filename, W("jit")) == 0)
19543     {
19544         if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT)
19545         {
19546             createDuplicateFgxFiles = true;
19547             goto ONE_FILE_PER_METHOD;
19548         }
19549         else
19550         {
19551             return nullptr;
19552         }
19553     }
19554     else if (wcscmp(filename, W("all")) == 0)
19555     {
19556         createDuplicateFgxFiles = true;
19557
19558     ONE_FILE_PER_METHOD:;
19559
19560         escapedString     = fgProcessEscapes(info.compFullName, s_EscapeFileMapping);
19561         size_t wCharCount = strlen(escapedString) + wcslen(phaseName) + 1 + strlen("~999") + wcslen(type) + 1;
19562         if (pathname != nullptr)
19563         {
19564             wCharCount += wcslen(pathname) + 1;
19565         }
19566         filename = (LPCWSTR)alloca(wCharCount * sizeof(WCHAR));
19567         if (pathname != nullptr)
19568         {
19569             swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S-%s.%s"), pathname, escapedString, phaseName, type);
19570         }
19571         else
19572         {
19573             swprintf_s((LPWSTR)filename, wCharCount, W("%S.%s"), escapedString, type);
19574         }
19575         fgxFile = _wfopen(filename, W("r")); // Check if this file already exists
19576         if (fgxFile != nullptr)
19577         {
19578             // For Generic methods we will have both hot and cold versions
19579             if (createDuplicateFgxFiles == false)
19580             {
19581                 fclose(fgxFile);
19582                 return nullptr;
19583             }
19584             // Yes, this filename already exists, so create a different one by appending ~2, ~3, etc...
19585             for (int i = 2; i < 1000; i++)
19586             {
19587                 fclose(fgxFile);
19588                 if (pathname != nullptr)
19589                 {
19590                     swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S~%d.%s"), pathname, escapedString, i, type);
19591                 }
19592                 else
19593                 {
19594                     swprintf_s((LPWSTR)filename, wCharCount, W("%S~%d.%s"), escapedString, i, type);
19595                 }
19596                 fgxFile = _wfopen(filename, W("r")); // Check if this file exists
19597                 if (fgxFile == nullptr)
19598                 {
19599                     break;
19600                 }
19601             }
19602             // If we have already created 1000 files with this name then just fail
19603             if (fgxFile != nullptr)
19604             {
19605                 fclose(fgxFile);
19606                 return nullptr;
19607             }
19608         }
19609         fgxFile      = _wfopen(filename, W("a+"));
19610         *wbDontClose = false;
19611     }
19612     else if (wcscmp(filename, W("stdout")) == 0)
19613     {
19614         fgxFile      = jitstdout;
19615         *wbDontClose = true;
19616     }
19617     else if (wcscmp(filename, W("stderr")) == 0)
19618     {
19619         fgxFile      = stderr;
19620         *wbDontClose = true;
19621     }
19622     else
19623     {
19624         LPCWSTR origFilename = filename;
19625         size_t  wCharCount   = wcslen(origFilename) + wcslen(type) + 2;
19626         if (pathname != nullptr)
19627         {
19628             wCharCount += wcslen(pathname) + 1;
19629         }
19630         filename = (LPCWSTR)alloca(wCharCount * sizeof(WCHAR));
19631         if (pathname != nullptr)
19632         {
19633             swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%s.%s"), pathname, origFilename, type);
19634         }
19635         else
19636         {
19637             swprintf_s((LPWSTR)filename, wCharCount, W("%s.%s"), origFilename, type);
19638         }
19639         fgxFile      = _wfopen(filename, W("a+"));
19640         *wbDontClose = false;
19641     }
19642
19643     return fgxFile;
19644 }
19645
19646 //------------------------------------------------------------------------
19647 // fgDumpFlowGraph: Dump the xml or dot format flow graph, if enabled for this phase.
19648 //
19649 // Arguments:
19650 //    phase       - A phase identifier to indicate which phase is associated with the dump,
19651 //                  i.e. which phase has just completed.
19652 //
19653 // Return Value:
19654 //    True iff a flowgraph has been dumped.
19655 //
19656 // Notes:
19657 //    The xml dumps are the historical mechanism for dumping the flowgraph.
19658 //    The dot format can be viewed by:
19659 //    - Graphviz (http://www.graphviz.org/)
19660 //      - The command "C:\Program Files (x86)\Graphviz2.38\bin\dot.exe" -Tsvg -oFoo.svg -Kdot Foo.dot
19661 //        will produce a Foo.svg file that can be opened with any svg-capable browser (e.g. IE).
19662 //    - http://rise4fun.com/Agl/
19663 //      - Cut and paste the graph from your .dot file, replacing the digraph on the page, and then click the play
19664 //        button.
19665 //      - It will show a rotating '/' and then render the graph in the browser.
19666 //    MSAGL has also been open-sourced to https://github.com/Microsoft/automatic-graph-layout.git.
19667 //
19668 //    Here are the config values that control it:
19669 //      COMPlus_JitDumpFg       A string (ala the COMPlus_JitDump string) indicating what methods to dump flowgraphs
19670 //                              for.
19671 //      COMPlus_JitDumpFgDir    A path to a directory into which the flowgraphs will be dumped.
19672 //      COMPlus_JitDumpFgFile   The filename to use. The default is "default.[xml|dot]".
19673 //                              Note that the new graphs will be appended to this file if it already exists.
19674 //      COMPlus_JitDumpFgPhase  Phase(s) after which to dump the flowgraph.
19675 //                              Set to the short name of a phase to see the flowgraph after that phase.
19676 //                              Leave unset to dump after COLD-BLK (determine first cold block) or set to * for all
19677 //                              phases.
19678 //      COMPlus_JitDumpFgDot    Set to non-zero to emit Dot instead of Xml Flowgraph dump. (Default is xml format.)
19679
19680 bool Compiler::fgDumpFlowGraph(Phases phase)
19681 {
19682     bool result        = false;
19683     bool dontClose     = false;
19684     bool createDotFile = false;
19685     if (JitConfig.JitDumpFgDot())
19686     {
19687         createDotFile = true;
19688     }
19689
19690     FILE* fgxFile = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx"));
19691
19692     if (fgxFile == nullptr)
19693     {
19694         return false;
19695     }
19696     bool        validWeights  = fgHaveValidEdgeWeights;
19697     unsigned    calledCount   = max(fgCalledCount, BB_UNITY_WEIGHT) / BB_UNITY_WEIGHT;
19698     double      weightDivisor = (double)(calledCount * BB_UNITY_WEIGHT);
19699     const char* escapedString;
19700     const char* regionString = "NONE";
19701
19702     if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT)
19703     {
19704         regionString = "HOT";
19705     }
19706     else if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD)
19707     {
19708         regionString = "COLD";
19709     }
19710     else if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT)
19711     {
19712         regionString = "JIT";
19713     }
19714
19715     if (createDotFile)
19716     {
19717         fprintf(fgxFile, "digraph %s\n{\n", info.compMethodName);
19718         fprintf(fgxFile, "/* Method %d, after phase %s */", Compiler::jitTotalMethodCompiled, PhaseNames[phase]);
19719     }
19720     else
19721     {
19722         fprintf(fgxFile, "<method");
19723
19724         escapedString = fgProcessEscapes(info.compFullName, s_EscapeMapping);
19725         fprintf(fgxFile, "\n    name=\"%s\"", escapedString);
19726
19727         escapedString = fgProcessEscapes(info.compClassName, s_EscapeMapping);
19728         fprintf(fgxFile, "\n    className=\"%s\"", escapedString);
19729
19730         escapedString = fgProcessEscapes(info.compMethodName, s_EscapeMapping);
19731         fprintf(fgxFile, "\n    methodName=\"%s\"", escapedString);
19732         fprintf(fgxFile, "\n    ngenRegion=\"%s\"", regionString);
19733
19734         fprintf(fgxFile, "\n    bytesOfIL=\"%d\"", info.compILCodeSize);
19735         fprintf(fgxFile, "\n    localVarCount=\"%d\"", lvaCount);
19736
19737         if (fgHaveProfileData())
19738         {
19739             fprintf(fgxFile, "\n    calledCount=\"%d\"", calledCount);
19740             fprintf(fgxFile, "\n    profileData=\"true\"");
19741         }
19742         if (compHndBBtabCount > 0)
19743         {
19744             fprintf(fgxFile, "\n    hasEHRegions=\"true\"");
19745         }
19746         if (fgHasLoops)
19747         {
19748             fprintf(fgxFile, "\n    hasLoops=\"true\"");
19749         }
19750         if (validWeights)
19751         {
19752             fprintf(fgxFile, "\n    validEdgeWeights=\"true\"");
19753             if (!fgSlopUsedInEdgeWeights && !fgRangeUsedInEdgeWeights)
19754             {
19755                 fprintf(fgxFile, "\n    exactEdgeWeights=\"true\"");
19756             }
19757         }
19758         if (fgFirstColdBlock != nullptr)
19759         {
19760             fprintf(fgxFile, "\n    firstColdBlock=\"%d\"", fgFirstColdBlock->bbNum);
19761         }
19762
19763         fprintf(fgxFile, ">");
19764
19765         fprintf(fgxFile, "\n    <blocks");
19766         fprintf(fgxFile, "\n        blockCount=\"%d\"", fgBBcount);
19767         fprintf(fgxFile, ">");
19768     }
19769
19770     static const char* kindImage[] = {"EHFINALLYRET", "EHFILTERRET", "EHCATCHRET",  "THROW", "RETURN", "NONE",
19771                                       "ALWAYS",       "LEAVE",       "CALLFINALLY", "COND",  "SWITCH"};
19772
19773     BasicBlock* block;
19774     unsigned    blockOrdinal;
19775     for (block = fgFirstBB, blockOrdinal = 1; block != nullptr; block = block->bbNext, blockOrdinal++)
19776     {
19777         if (createDotFile)
19778         {
19779             // Add constraint edges to try to keep nodes ordered.
19780             // It seems to work best if these edges are all created first.
19781             switch (block->bbJumpKind)
19782             {
19783                 case BBJ_COND:
19784                 case BBJ_NONE:
19785                     assert(block->bbNext != nullptr);
19786                     fprintf(fgxFile, "    BB%02u -> BB%02u\n", block->bbNum, block->bbNext->bbNum);
19787                     break;
19788                 default:
19789                     // These may or may not have an edge to the next block.
19790                     // Add a transparent edge to keep nodes ordered.
19791                     if (block->bbNext != nullptr)
19792                     {
19793                         fprintf(fgxFile, "    BB%02u -> BB%02u [arrowtail=none,color=transparent]\n", block->bbNum,
19794                                 block->bbNext->bbNum);
19795                     }
19796             }
19797         }
19798         else
19799         {
19800             fprintf(fgxFile, "\n        <block");
19801             fprintf(fgxFile, "\n            id=\"%d\"", block->bbNum);
19802             fprintf(fgxFile, "\n            ordinal=\"%d\"", blockOrdinal);
19803             fprintf(fgxFile, "\n            jumpKind=\"%s\"", kindImage[block->bbJumpKind]);
19804             if (block->hasTryIndex())
19805             {
19806                 fprintf(fgxFile, "\n            inTry=\"%s\"", "true");
19807             }
19808             if (block->hasHndIndex())
19809             {
19810                 fprintf(fgxFile, "\n            inHandler=\"%s\"", "true");
19811             }
19812             if ((fgFirstBB->hasProfileWeight()) && ((block->bbFlags & BBF_COLD) == 0))
19813             {
19814                 fprintf(fgxFile, "\n            hot=\"true\"");
19815             }
19816             if (block->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY))
19817             {
19818                 fprintf(fgxFile, "\n            callsNew=\"true\"");
19819             }
19820             if (block->bbFlags & BBF_LOOP_HEAD)
19821             {
19822                 fprintf(fgxFile, "\n            loopHead=\"true\"");
19823             }
19824             fprintf(fgxFile, "\n            weight=");
19825             fprintfDouble(fgxFile, ((double)block->bbWeight) / weightDivisor);
19826             fprintf(fgxFile, "\n            codeEstimate=\"%d\"", fgGetCodeEstimate(block));
19827             fprintf(fgxFile, "\n            startOffset=\"%d\"", block->bbCodeOffs);
19828             fprintf(fgxFile, "\n            endOffset=\"%d\"", block->bbCodeOffsEnd);
19829             fprintf(fgxFile, ">");
19830             fprintf(fgxFile, "\n        </block>");
19831         }
19832     }
19833
19834     if (!createDotFile)
19835     {
19836         fprintf(fgxFile, "\n    </blocks>");
19837
19838         fprintf(fgxFile, "\n    <edges");
19839         fprintf(fgxFile, "\n        edgeCount=\"%d\"", fgEdgeCount);
19840         fprintf(fgxFile, ">");
19841     }
19842
19843     unsigned    edgeNum = 1;
19844     BasicBlock* bTarget;
19845     for (bTarget = fgFirstBB; bTarget != nullptr; bTarget = bTarget->bbNext)
19846     {
19847         double targetWeightDivisor;
19848         if (bTarget->bbWeight == BB_ZERO_WEIGHT)
19849         {
19850             targetWeightDivisor = 1.0;
19851         }
19852         else
19853         {
19854             targetWeightDivisor = (double)bTarget->bbWeight;
19855         }
19856
19857         flowList* edge;
19858         for (edge = bTarget->bbPreds; edge != nullptr; edge = edge->flNext, edgeNum++)
19859         {
19860             BasicBlock* bSource = edge->flBlock;
19861             double      sourceWeightDivisor;
19862             if (bSource->bbWeight == BB_ZERO_WEIGHT)
19863             {
19864                 sourceWeightDivisor = 1.0;
19865             }
19866             else
19867             {
19868                 sourceWeightDivisor = (double)bSource->bbWeight;
19869             }
19870             if (createDotFile)
19871             {
19872                 // Don't duplicate the edges we added above.
19873                 if ((bSource->bbNum == (bTarget->bbNum - 1)) &&
19874                     ((bSource->bbJumpKind == BBJ_NONE) || (bSource->bbJumpKind == BBJ_COND)))
19875                 {
19876                     continue;
19877                 }
19878                 fprintf(fgxFile, "    BB%02u -> BB%02u", bSource->bbNum, bTarget->bbNum);
19879                 if ((bSource->bbNum > bTarget->bbNum))
19880                 {
19881                     fprintf(fgxFile, "[arrowhead=normal,arrowtail=none,color=green]\n");
19882                 }
19883                 else
19884                 {
19885                     fprintf(fgxFile, "\n");
19886                 }
19887             }
19888             else
19889             {
19890                 fprintf(fgxFile, "\n        <edge");
19891                 fprintf(fgxFile, "\n            id=\"%d\"", edgeNum);
19892                 fprintf(fgxFile, "\n            source=\"%d\"", bSource->bbNum);
19893                 fprintf(fgxFile, "\n            target=\"%d\"", bTarget->bbNum);
19894                 if (bSource->bbJumpKind == BBJ_SWITCH)
19895                 {
19896                     if (edge->flDupCount >= 2)
19897                     {
19898                         fprintf(fgxFile, "\n            switchCases=\"%d\"", edge->flDupCount);
19899                     }
19900                     if (bSource->bbJumpSwt->getDefault() == bTarget)
19901                     {
19902                         fprintf(fgxFile, "\n            switchDefault=\"true\"");
19903                     }
19904                 }
19905                 if (validWeights)
19906                 {
19907                     unsigned edgeWeight = (edge->flEdgeWeightMin + edge->flEdgeWeightMax) / 2;
19908                     fprintf(fgxFile, "\n            weight=");
19909                     fprintfDouble(fgxFile, ((double)edgeWeight) / weightDivisor);
19910
19911                     if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
19912                     {
19913                         fprintf(fgxFile, "\n            minWeight=");
19914                         fprintfDouble(fgxFile, ((double)edge->flEdgeWeightMin) / weightDivisor);
19915                         fprintf(fgxFile, "\n            maxWeight=");
19916                         fprintfDouble(fgxFile, ((double)edge->flEdgeWeightMax) / weightDivisor);
19917                     }
19918
19919                     if (edgeWeight > 0)
19920                     {
19921                         if (edgeWeight < bSource->bbWeight)
19922                         {
19923                             fprintf(fgxFile, "\n            out=");
19924                             fprintfDouble(fgxFile, ((double)edgeWeight) / sourceWeightDivisor);
19925                         }
19926                         if (edgeWeight < bTarget->bbWeight)
19927                         {
19928                             fprintf(fgxFile, "\n            in=");
19929                             fprintfDouble(fgxFile, ((double)edgeWeight) / targetWeightDivisor);
19930                         }
19931                     }
19932                 }
19933             }
19934             if (!createDotFile)
19935             {
19936                 fprintf(fgxFile, ">");
19937                 fprintf(fgxFile, "\n        </edge>");
19938             }
19939         }
19940     }
19941     if (createDotFile)
19942     {
19943         fprintf(fgxFile, "}\n");
19944     }
19945     else
19946     {
19947         fprintf(fgxFile, "\n    </edges>");
19948         fprintf(fgxFile, "\n</method>\n");
19949     }
19950
19951     if (dontClose)
19952     {
19953         // fgxFile is jitstdout or stderr
19954         fprintf(fgxFile, "\n");
19955     }
19956     else
19957     {
19958         fclose(fgxFile);
19959     }
19960
19961     return result;
19962 }
19963
19964 #endif // DUMP_FLOWGRAPHS
19965
19966 /*****************************************************************************/
19967 #ifdef DEBUG
19968
19969 void Compiler::fgDispReach()
19970 {
19971     printf("------------------------------------------------\n");
19972     printf("BBnum  Reachable by \n");
19973     printf("------------------------------------------------\n");
19974
19975     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
19976     {
19977         printf("BB%02u : ", block->bbNum);
19978         BlockSetOps::Iter iter(this, block->bbReach);
19979         unsigned          bbNum = 0;
19980         while (iter.NextElem(&bbNum))
19981         {
19982             printf("BB%02u ", bbNum);
19983         }
19984         printf("\n");
19985     }
19986 }
19987
19988 void Compiler::fgDispDoms()
19989 {
19990     // Don't bother printing this when we have a large number of BasicBlocks in the method
19991     if (fgBBcount > 256)
19992     {
19993         return;
19994     }
19995
19996     printf("------------------------------------------------\n");
19997     printf("BBnum  Dominated by\n");
19998     printf("------------------------------------------------\n");
19999
20000     for (unsigned i = 1; i <= fgBBNumMax; ++i)
20001     {
20002         BasicBlock* current = fgBBInvPostOrder[i];
20003         printf("BB%02u:  ", current->bbNum);
20004         while (current != current->bbIDom)
20005         {
20006             printf("BB%02u ", current->bbNum);
20007             current = current->bbIDom;
20008         }
20009         printf("\n");
20010     }
20011 }
20012
20013 /*****************************************************************************/
20014
20015 void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 */)
20016 {
20017     const unsigned __int64 flags    = block->bbFlags;
20018     unsigned               bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax;
20019     int                    maxBlockNumWidth = CountDigits(bbNumMax);
20020     maxBlockNumWidth                        = max(maxBlockNumWidth, 2);
20021     int blockNumWidth                       = CountDigits(block->bbNum);
20022     blockNumWidth                           = max(blockNumWidth, 2);
20023     int blockNumPadding                     = maxBlockNumWidth - blockNumWidth;
20024
20025     printf("%s %2u", block->dspToString(blockNumPadding), block->bbRefs);
20026
20027     //
20028     // Display EH 'try' region index
20029     //
20030
20031     if (block->hasTryIndex())
20032     {
20033         printf(" %2u", block->getTryIndex());
20034     }
20035     else
20036     {
20037         printf("   ");
20038     }
20039
20040     //
20041     // Display EH handler region index
20042     //
20043
20044     if (block->hasHndIndex())
20045     {
20046         printf(" %2u", block->getHndIndex());
20047     }
20048     else
20049     {
20050         printf("   ");
20051     }
20052
20053     printf(" ");
20054
20055     //
20056     // Display block predecessor list
20057     //
20058
20059     unsigned charCnt;
20060     if (fgCheapPredsValid)
20061     {
20062         charCnt = block->dspCheapPreds();
20063     }
20064     else
20065     {
20066         charCnt = block->dspPreds();
20067     }
20068
20069     if (charCnt < 19)
20070     {
20071         printf("%*s", 19 - charCnt, "");
20072     }
20073
20074     printf(" ");
20075
20076     //
20077     // Display block weight
20078     //
20079
20080     if (block->isMaxBBWeight())
20081     {
20082         printf(" MAX  ");
20083     }
20084     else
20085     {
20086         BasicBlock::weight_t weight = block->getBBWeight(this);
20087
20088         if (weight > 99999) // Is it going to be more than 6 characters?
20089         {
20090             if (weight <= 99999 * BB_UNITY_WEIGHT)
20091             {
20092                 // print weight in this format ddddd.
20093                 printf("%5u.", (weight + (BB_UNITY_WEIGHT / 2)) / BB_UNITY_WEIGHT);
20094             }
20095             else // print weight in terms of k (i.e. 156k )
20096             {
20097                 // print weight in this format dddddk
20098                 BasicBlock::weight_t weightK = weight / 1000;
20099                 printf("%5uk", (weightK + (BB_UNITY_WEIGHT / 2)) / BB_UNITY_WEIGHT);
20100             }
20101         }
20102         else // print weight in this format ddd.dd
20103         {
20104             printf("%6s", refCntWtd2str(weight));
20105         }
20106     }
20107     printf(" ");
20108
20109     //
20110     // Display optional IBC weight column.
20111     // Note that iColWidth includes one character for a leading space, if there is an IBC column.
20112     //
20113
20114     if (ibcColWidth > 0)
20115     {
20116         if (block->hasProfileWeight())
20117         {
20118             printf("%*u", ibcColWidth, block->bbWeight);
20119         }
20120         else
20121         {
20122             // No IBC data. Just print spaces to align the column.
20123             printf("%*s", ibcColWidth, "");
20124         }
20125     }
20126
20127     printf(" ");
20128
20129     //
20130     // Display block IL range
20131     //
20132
20133     block->dspBlockILRange();
20134
20135     //
20136     // Display block branch target
20137     //
20138
20139     if (flags & BBF_REMOVED)
20140     {
20141         printf("[removed]       ");
20142     }
20143     else
20144     {
20145         switch (block->bbJumpKind)
20146         {
20147             case BBJ_COND:
20148                 printf("-> BB%02u%*s ( cond )", block->bbJumpDest->bbNum,
20149                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20150                 break;
20151
20152             case BBJ_CALLFINALLY:
20153                 printf("-> BB%02u%*s (callf )", block->bbJumpDest->bbNum,
20154                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20155                 break;
20156
20157             case BBJ_ALWAYS:
20158                 if (flags & BBF_KEEP_BBJ_ALWAYS)
20159                 {
20160                     printf("-> BB%02u%*s (ALWAYS)", block->bbJumpDest->bbNum,
20161                            maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20162                 }
20163                 else
20164                 {
20165                     printf("-> BB%02u%*s (always)", block->bbJumpDest->bbNum,
20166                            maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20167                 }
20168                 break;
20169
20170             case BBJ_LEAVE:
20171                 printf("-> BB%02u%*s (leave )", block->bbJumpDest->bbNum,
20172                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20173                 break;
20174
20175             case BBJ_EHFINALLYRET:
20176                 printf("%*s        (finret)", maxBlockNumWidth - 2, "");
20177                 break;
20178
20179             case BBJ_EHFILTERRET:
20180                 printf("%*s        (fltret)", maxBlockNumWidth - 2, "");
20181                 break;
20182
20183             case BBJ_EHCATCHRET:
20184                 printf("-> BB%02u%*s ( cret )", block->bbJumpDest->bbNum,
20185                        maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
20186                 break;
20187
20188             case BBJ_THROW:
20189                 printf("%*s        (throw )", maxBlockNumWidth - 2, "");
20190                 break;
20191
20192             case BBJ_RETURN:
20193                 printf("%*s        (return)", maxBlockNumWidth - 2, "");
20194                 break;
20195
20196             default:
20197                 printf("%*s                ", maxBlockNumWidth - 2, "");
20198                 break;
20199
20200             case BBJ_SWITCH:
20201                 printf("->");
20202
20203                 unsigned jumpCnt;
20204                 jumpCnt = block->bbJumpSwt->bbsCount;
20205                 BasicBlock** jumpTab;
20206                 jumpTab = block->bbJumpSwt->bbsDstTab;
20207                 int switchWidth;
20208                 switchWidth = 0;
20209                 do
20210                 {
20211                     printf("%cBB%02u", (jumpTab == block->bbJumpSwt->bbsDstTab) ? ' ' : ',', (*jumpTab)->bbNum);
20212                     switchWidth += 1 /* space/comma */ + 2 /* BB */ + max(CountDigits((*jumpTab)->bbNum), 2);
20213                 } while (++jumpTab, --jumpCnt);
20214
20215                 if (switchWidth < 7)
20216                 {
20217                     printf("%*s", 8 - switchWidth, "");
20218                 }
20219
20220                 printf(" (switch)");
20221                 break;
20222         }
20223     }
20224
20225     printf(" ");
20226
20227     //
20228     // Display block EH region and type, including nesting indicator
20229     //
20230
20231     if (block->hasTryIndex())
20232     {
20233         printf("T%d ", block->getTryIndex());
20234     }
20235     else
20236     {
20237         printf("   ");
20238     }
20239
20240     if (block->hasHndIndex())
20241     {
20242         printf("H%d ", block->getHndIndex());
20243     }
20244     else
20245     {
20246         printf("   ");
20247     }
20248
20249     if (flags & BBF_FUNCLET_BEG)
20250     {
20251         printf("F ");
20252     }
20253     else
20254     {
20255         printf("  ");
20256     }
20257
20258     int cnt = 0;
20259
20260     switch (block->bbCatchTyp)
20261     {
20262         case BBCT_NONE:
20263             break;
20264         case BBCT_FAULT:
20265             printf("fault ");
20266             cnt += 6;
20267             break;
20268         case BBCT_FINALLY:
20269             printf("finally ");
20270             cnt += 8;
20271             break;
20272         case BBCT_FILTER:
20273             printf("filter ");
20274             cnt += 7;
20275             break;
20276         case BBCT_FILTER_HANDLER:
20277             printf("filtHnd ");
20278             cnt += 8;
20279             break;
20280         default:
20281             printf("catch ");
20282             cnt += 6;
20283             break;
20284     }
20285
20286     if (block->bbCatchTyp != BBCT_NONE)
20287     {
20288         cnt += 2;
20289         printf("{ ");
20290         /* brace matching editor workaround to compensate for the preceding line: } */
20291     }
20292
20293     if (flags & BBF_TRY_BEG)
20294     {
20295         // Output a brace for every try region that this block opens
20296
20297         EHblkDsc* HBtab;
20298         EHblkDsc* HBtabEnd;
20299
20300         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
20301         {
20302             if (HBtab->ebdTryBeg == block)
20303             {
20304                 cnt += 6;
20305                 printf("try { ");
20306                 /* brace matching editor workaround to compensate for the preceding line: } */
20307             }
20308         }
20309     }
20310
20311     EHblkDsc* HBtab;
20312     EHblkDsc* HBtabEnd;
20313
20314     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
20315     {
20316         if (HBtab->ebdTryLast == block)
20317         {
20318             cnt += 2;
20319             /* brace matching editor workaround to compensate for the following line: { */
20320             printf("} ");
20321         }
20322         if (HBtab->ebdHndLast == block)
20323         {
20324             cnt += 2;
20325             /* brace matching editor workaround to compensate for the following line: { */
20326             printf("} ");
20327         }
20328         if (HBtab->HasFilter() && block->bbNext == HBtab->ebdHndBeg)
20329         {
20330             cnt += 2;
20331             /* brace matching editor workaround to compensate for the following line: { */
20332             printf("} ");
20333         }
20334     }
20335
20336     while (cnt < 12)
20337     {
20338         cnt++;
20339         printf(" ");
20340     }
20341
20342     //
20343     // Display block flags
20344     //
20345
20346     block->dspFlags();
20347
20348     printf("\n");
20349 }
20350
20351 /****************************************************************************
20352     Dump blocks from firstBlock to lastBlock.
20353 */
20354
20355 void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, bool dumpTrees)
20356 {
20357     BasicBlock* block;
20358
20359     // If any block has IBC data, we add an "IBC weight" column just before the 'IL range' column. This column is as
20360     // wide as necessary to accommodate all the various IBC weights. It's at least 4 characters wide, to accommodate
20361     // the "IBC" title and leading space.
20362     int ibcColWidth = 0;
20363     for (block = firstBlock; block != nullptr; block = block->bbNext)
20364     {
20365         if (block->hasProfileWeight())
20366         {
20367             int thisIbcWidth = CountDigits(block->bbWeight);
20368             ibcColWidth      = max(ibcColWidth, thisIbcWidth);
20369         }
20370
20371         if (block == lastBlock)
20372         {
20373             break;
20374         }
20375     }
20376     if (ibcColWidth > 0)
20377     {
20378         ibcColWidth = max(ibcColWidth, 3) + 1; // + 1 for the leading space
20379     }
20380
20381     unsigned bbNumMax         = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax;
20382     int      maxBlockNumWidth = CountDigits(bbNumMax);
20383     maxBlockNumWidth          = max(maxBlockNumWidth, 2);
20384     int padWidth              = maxBlockNumWidth - 2; // Account for functions with a large number of blocks.
20385
20386     // clang-format off
20387
20388     printf("\n");
20389     printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n",
20390         padWidth, "------------",
20391         ibcColWidth, "------------",
20392         maxBlockNumWidth, "----");
20393     printf("BBnum %*sBBid ref try hnd %s     weight  %*s%s  [IL range]     [jump]%*s    [EH region]         [flags]\n",
20394         padWidth, "",
20395         fgCheapPredsValid       ? "cheap preds" :
20396         (fgComputePredsDone     ? "preds      "
20397                                 : "           "),
20398         ((ibcColWidth > 0) ? ibcColWidth - 3 : 0), "",  // Subtract 3 for the width of "IBC", printed next.
20399         ((ibcColWidth > 0)      ? "IBC"
20400                                 : ""),
20401         maxBlockNumWidth, ""
20402         );
20403     printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n",
20404         padWidth, "------------",
20405         ibcColWidth, "------------",
20406         maxBlockNumWidth, "----");
20407
20408     // clang-format on
20409
20410     for (block = firstBlock; block; block = block->bbNext)
20411     {
20412         // First, do some checking on the bbPrev links
20413         if (block->bbPrev)
20414         {
20415             if (block->bbPrev->bbNext != block)
20416             {
20417                 printf("bad prev link\n");
20418             }
20419         }
20420         else if (block != fgFirstBB)
20421         {
20422             printf("bad prev link!\n");
20423         }
20424
20425         if (block == fgFirstColdBlock)
20426         {
20427             printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~"
20428                    "~~~~~~~~~~~~~~~~\n",
20429                    padWidth, "~~~~~~~~~~~~", ibcColWidth, "~~~~~~~~~~~~", maxBlockNumWidth, "~~~~");
20430         }
20431
20432 #if FEATURE_EH_FUNCLETS
20433         if (block == fgFirstFuncletBB)
20434         {
20435             printf("++++++%*s+++++++++++++++++++++++++++++++++++++%*s+++++++++++++++++++++++%*s++++++++++++++++++++++++"
20436                    "++++++++++++++++ funclets follow\n",
20437                    padWidth, "++++++++++++", ibcColWidth, "++++++++++++", maxBlockNumWidth, "++++");
20438         }
20439 #endif // FEATURE_EH_FUNCLETS
20440
20441         fgTableDispBasicBlock(block, ibcColWidth);
20442
20443         if (block == lastBlock)
20444         {
20445             break;
20446         }
20447     }
20448
20449     printf("------%*s-------------------------------------%*s-----------------------%*s--------------------------------"
20450            "--------\n",
20451            padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----");
20452
20453     if (dumpTrees)
20454     {
20455         fgDumpTrees(firstBlock, lastBlock);
20456     }
20457 }
20458
20459 /*****************************************************************************/
20460
20461 void Compiler::fgDispBasicBlocks(bool dumpTrees)
20462 {
20463     fgDispBasicBlocks(fgFirstBB, nullptr, dumpTrees);
20464 }
20465
20466 /*****************************************************************************/
20467 //  Increment the stmtNum and dump the tree using gtDispTree
20468 //
20469 void Compiler::fgDumpStmtTree(GenTree* stmt, unsigned bbNum)
20470 {
20471     compCurStmtNum++; // Increment the current stmtNum
20472
20473     printf("\n***** BB%02u, stmt %d\n", bbNum, compCurStmtNum);
20474
20475     if (fgOrder == FGOrderLinear || opts.compDbgInfo)
20476     {
20477         gtDispTree(stmt);
20478     }
20479     else
20480     {
20481         gtDispTree(stmt->gtStmt.gtStmtExpr);
20482     }
20483 }
20484
20485 //------------------------------------------------------------------------
20486 // Compiler::fgDumpBlock: dumps the contents of the given block to stdout.
20487 //
20488 // Arguments:
20489 //    block - The block to dump.
20490 //
20491 void Compiler::fgDumpBlock(BasicBlock* block)
20492 {
20493     printf("\n------------ ");
20494     block->dspBlockHeader(this);
20495
20496     if (!block->IsLIR())
20497     {
20498         for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
20499         {
20500             fgDumpStmtTree(stmt, block->bbNum);
20501             if (stmt == block->bbTreeList)
20502             {
20503                 block->bbStmtNum = compCurStmtNum; // Set the block->bbStmtNum
20504             }
20505         }
20506     }
20507     else
20508     {
20509         gtDispRange(LIR::AsRange(block));
20510     }
20511 }
20512
20513 /*****************************************************************************/
20514 //  Walk the BasicBlock list calling fgDumpTree once per Stmt
20515 //
20516 void Compiler::fgDumpTrees(BasicBlock* firstBlock, BasicBlock* lastBlock)
20517 {
20518     compCurStmtNum = 0; // Reset the current stmtNum
20519
20520     /* Walk the basic blocks */
20521
20522     // Note that typically we have already called fgDispBasicBlocks()
20523     //  so we don't need to print the preds and succs again here
20524     //
20525     for (BasicBlock* block = firstBlock; block; block = block->bbNext)
20526     {
20527         fgDumpBlock(block);
20528
20529         if (block == lastBlock)
20530         {
20531             break;
20532         }
20533     }
20534     printf("\n---------------------------------------------------------------------------------------------------------"
20535            "----------\n");
20536 }
20537
20538 /*****************************************************************************
20539  * Try to create as many candidates for GTF_MUL_64RSLT as possible.
20540  * We convert 'intOp1*intOp2' into 'int(long(nop(intOp1))*long(intOp2))'.
20541  */
20542
20543 /* static */
20544 Compiler::fgWalkResult Compiler::fgStress64RsltMulCB(GenTree** pTree, fgWalkData* data)
20545 {
20546     GenTree*  tree  = *pTree;
20547     Compiler* pComp = data->compiler;
20548
20549     if (tree->gtOper != GT_MUL || tree->gtType != TYP_INT || (tree->gtOverflow()))
20550     {
20551         return WALK_CONTINUE;
20552     }
20553
20554 #ifdef DEBUG
20555     if (pComp->verbose)
20556     {
20557         printf("STRESS_64RSLT_MUL before:\n");
20558         pComp->gtDispTree(tree);
20559     }
20560 #endif // DEBUG
20561
20562     // To ensure optNarrowTree() doesn't fold back to the original tree.
20563     tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, false, TYP_LONG);
20564     tree->gtOp.gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->gtOp.gtOp1);
20565     tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, false, TYP_LONG);
20566     tree->gtOp.gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp2, false, TYP_LONG);
20567     tree->gtType     = TYP_LONG;
20568     *pTree           = pComp->gtNewCastNode(TYP_INT, tree, false, TYP_INT);
20569
20570 #ifdef DEBUG
20571     if (pComp->verbose)
20572     {
20573         printf("STRESS_64RSLT_MUL after:\n");
20574         pComp->gtDispTree(*pTree);
20575     }
20576 #endif // DEBUG
20577
20578     return WALK_SKIP_SUBTREES;
20579 }
20580
20581 void Compiler::fgStress64RsltMul()
20582 {
20583     if (!compStressCompile(STRESS_64RSLT_MUL, 20))
20584     {
20585         return;
20586     }
20587
20588     fgWalkAllTreesPre(fgStress64RsltMulCB, (void*)this);
20589 }
20590
20591 // BBPredsChecker checks jumps from the block's predecessors to the block.
20592 class BBPredsChecker
20593 {
20594 public:
20595     BBPredsChecker(Compiler* compiler) : comp(compiler)
20596     {
20597     }
20598
20599     unsigned CheckBBPreds(BasicBlock* block, unsigned curTraversalStamp);
20600
20601 private:
20602     bool CheckEhTryDsc(BasicBlock* block, BasicBlock* blockPred, EHblkDsc* ehTryDsc);
20603     bool CheckEhHndDsc(BasicBlock* block, BasicBlock* blockPred, EHblkDsc* ehHndlDsc);
20604     bool CheckJump(BasicBlock* blockPred, BasicBlock* block);
20605     bool CheckEHFinalyRet(BasicBlock* blockPred, BasicBlock* block);
20606
20607 private:
20608     Compiler* comp;
20609 };
20610
20611 //------------------------------------------------------------------------
20612 // CheckBBPreds: Check basic block predecessors list.
20613 //
20614 // Notes:
20615 //   This DEBUG routine checks that all predecessors have the correct traversal stamp
20616 //   and have correct jumps to the block.
20617 //   It calculates the number of incoming edges from the internal block,
20618 //   i.e. it does not count the global incoming edge for the first block.
20619 //
20620 // Arguments:
20621 //   block - the block to process;
20622 //   curTraversalStamp - current traversal stamp to distinguish different iterations.
20623 //
20624 // Return value:
20625 //   the number of incoming edges for the block.
20626 unsigned BBPredsChecker::CheckBBPreds(BasicBlock* block, unsigned curTraversalStamp)
20627 {
20628     if (comp->fgCheapPredsValid)
20629     {
20630         return 0;
20631     }
20632
20633     if (!comp->fgComputePredsDone)
20634     {
20635         assert(block->bbPreds == nullptr);
20636         return 0;
20637     }
20638
20639     unsigned blockRefs = 0;
20640     for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
20641     {
20642         blockRefs += pred->flDupCount;
20643
20644         BasicBlock* blockPred = pred->flBlock;
20645
20646         // Make sure this pred is part of the BB list.
20647         assert(blockPred->bbTraversalStamp == curTraversalStamp);
20648
20649         EHblkDsc* ehTryDsc = comp->ehGetBlockTryDsc(block);
20650         if (ehTryDsc != nullptr)
20651         {
20652             assert(CheckEhTryDsc(block, blockPred, ehTryDsc));
20653         }
20654
20655         EHblkDsc* ehHndDsc = comp->ehGetBlockHndDsc(block);
20656         if (ehHndDsc != nullptr)
20657         {
20658             assert(CheckEhHndDsc(block, blockPred, ehHndDsc));
20659         }
20660
20661         assert(CheckJump(blockPred, block));
20662     }
20663     return blockRefs;
20664 }
20665
20666 bool BBPredsChecker::CheckEhTryDsc(BasicBlock* block, BasicBlock* blockPred, EHblkDsc* ehTryDsc)
20667 {
20668     // You can jump to the start of a try
20669     if (ehTryDsc->ebdTryBeg == block)
20670     {
20671         return true;
20672     }
20673
20674     // You can jump within the same try region
20675     if (comp->bbInTryRegions(block->getTryIndex(), blockPred))
20676     {
20677         return true;
20678     }
20679
20680     // The catch block can jump back into the middle of the try
20681     if (comp->bbInCatchHandlerRegions(block, blockPred))
20682     {
20683         return true;
20684     }
20685
20686     // The end of a finally region is a BBJ_EHFINALLYRET block (during importing, BBJ_LEAVE) which
20687     // is marked as "returning" to the BBJ_ALWAYS block following the BBJ_CALLFINALLY
20688     // block that does a local call to the finally. This BBJ_ALWAYS is within
20689     // the try region protected by the finally (for x86, ARM), but that's ok.
20690     BasicBlock* prevBlock = block->bbPrev;
20691     if (prevBlock->bbJumpKind == BBJ_CALLFINALLY && block->bbJumpKind == BBJ_ALWAYS &&
20692         blockPred->bbJumpKind == BBJ_EHFINALLYRET)
20693     {
20694         return true;
20695     }
20696
20697     printf("Jump into the middle of try region: BB%02u branches to BB%02u\n", blockPred->bbNum, block->bbNum);
20698     assert(!"Jump into middle of try region");
20699     return false;
20700 }
20701
20702 bool BBPredsChecker::CheckEhHndDsc(BasicBlock* block, BasicBlock* blockPred, EHblkDsc* ehHndlDsc)
20703 {
20704     // You can do a BBJ_EHFINALLYRET or BBJ_EHFILTERRET into a handler region
20705     if ((blockPred->bbJumpKind == BBJ_EHFINALLYRET) || (blockPred->bbJumpKind == BBJ_EHFILTERRET))
20706     {
20707         return true;
20708     }
20709
20710     // Our try block can call our finally block
20711     if ((block->bbCatchTyp == BBCT_FINALLY) && (blockPred->bbJumpKind == BBJ_CALLFINALLY) &&
20712         comp->ehCallFinallyInCorrectRegion(blockPred, block->getHndIndex()))
20713     {
20714         return true;
20715     }
20716
20717     // You can jump within the same handler region
20718     if (comp->bbInHandlerRegions(block->getHndIndex(), blockPred))
20719     {
20720         return true;
20721     }
20722
20723     // A filter can jump to the start of the filter handler
20724     if (ehHndlDsc->HasFilter())
20725     {
20726         return true;
20727     }
20728
20729     printf("Jump into the middle of handler region: BB%02u branches to BB%02u\n", blockPred->bbNum, block->bbNum);
20730     assert(!"Jump into the middle of handler region");
20731     return false;
20732 }
20733
20734 bool BBPredsChecker::CheckJump(BasicBlock* blockPred, BasicBlock* block)
20735 {
20736     switch (blockPred->bbJumpKind)
20737     {
20738         case BBJ_COND:
20739             assert(blockPred->bbNext == block || blockPred->bbJumpDest == block);
20740             return true;
20741
20742         case BBJ_NONE:
20743             assert(blockPred->bbNext == block);
20744             return true;
20745
20746         case BBJ_CALLFINALLY:
20747         case BBJ_ALWAYS:
20748         case BBJ_EHCATCHRET:
20749         case BBJ_EHFILTERRET:
20750             assert(blockPred->bbJumpDest == block);
20751             return true;
20752
20753         case BBJ_EHFINALLYRET:
20754             assert(CheckEHFinalyRet(blockPred, block));
20755             return true;
20756
20757         case BBJ_THROW:
20758         case BBJ_RETURN:
20759             assert(!"THROW and RETURN block cannot be in the predecessor list!");
20760             break;
20761
20762         case BBJ_SWITCH:
20763         {
20764             unsigned jumpCnt = blockPred->bbJumpSwt->bbsCount;
20765
20766             for (unsigned i = 0; i < jumpCnt; ++i)
20767             {
20768                 BasicBlock* jumpTab = blockPred->bbJumpSwt->bbsDstTab[i];
20769                 assert(jumpTab != nullptr);
20770                 if (block == jumpTab)
20771                 {
20772                     return true;
20773                 }
20774             }
20775
20776             assert(!"SWITCH in the predecessor list with no jump label to BLOCK!");
20777         }
20778         break;
20779
20780         default:
20781             assert(!"Unexpected bbJumpKind");
20782             break;
20783     }
20784     return false;
20785 }
20786
20787 bool BBPredsChecker::CheckEHFinalyRet(BasicBlock* blockPred, BasicBlock* block)
20788 {
20789
20790     // If the current block is a successor to a BBJ_EHFINALLYRET (return from finally),
20791     // then the lexically previous block should be a call to the same finally.
20792     // Verify all of that.
20793
20794     unsigned    hndIndex = blockPred->getHndIndex();
20795     EHblkDsc*   ehDsc    = comp->ehGetDsc(hndIndex);
20796     BasicBlock* finBeg   = ehDsc->ebdHndBeg;
20797
20798     // Because there is no bbPrev, we have to search for the lexically previous
20799     // block.  We can shorten the search by only looking in places where it is legal
20800     // to have a call to the finally.
20801
20802     BasicBlock* begBlk;
20803     BasicBlock* endBlk;
20804     comp->ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
20805
20806     for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
20807     {
20808         if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
20809         {
20810             continue;
20811         }
20812
20813         if (block == bcall->bbNext)
20814         {
20815             return true;
20816         }
20817     }
20818
20819 #if FEATURE_EH_FUNCLETS
20820
20821     if (comp->fgFuncletsCreated)
20822     {
20823         // There is no easy way to search just the funclets that were pulled out of
20824         // the corresponding try body, so instead we search all the funclets, and if
20825         // we find a potential 'hit' we check if the funclet we're looking at is
20826         // from the correct try region.
20827
20828         for (BasicBlock* bcall = comp->fgFirstFuncletBB; bcall != nullptr; bcall = bcall->bbNext)
20829         {
20830             if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
20831             {
20832                 continue;
20833             }
20834
20835             if (block != bcall->bbNext)
20836             {
20837                 continue;
20838             }
20839
20840             if (comp->ehCallFinallyInCorrectRegion(bcall, hndIndex))
20841             {
20842                 return true;
20843             }
20844         }
20845     }
20846
20847 #endif // FEATURE_EH_FUNCLETS
20848
20849     assert(!"BBJ_EHFINALLYRET predecessor of block that doesn't follow a BBJ_CALLFINALLY!");
20850     return false;
20851 }
20852
20853 // This variable is used to generate "traversal labels": one-time constants with which
20854 // we label basic blocks that are members of the basic block list, in order to have a
20855 // fast, high-probability test for membership in that list.  Type is "volatile" because
20856 // it's incremented with an atomic operation, which wants a volatile type; "long" so that
20857 // wrap-around to 0 (which I think has the highest probability of accidental collision) is
20858 // postponed a *long* time.
20859 static volatile int bbTraverseLabel = 1;
20860
20861 /*****************************************************************************
20862  *
20863  * A DEBUG routine to check the consistency of the flowgraph,
20864  * i.e. bbNum, bbRefs, bbPreds have to be up to date.
20865  *
20866  *****************************************************************************/
20867
20868 void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, bool checkBBRefs /* = true  */)
20869 {
20870 #ifdef DEBUG
20871     if (verbose)
20872     {
20873         printf("*************** In fgDebugCheckBBlist\n");
20874     }
20875 #endif // DEBUG
20876
20877     fgDebugCheckBlockLinks();
20878
20879     if (fgBBcount > 10000 && expensiveDebugCheckLevel < 1)
20880     {
20881         // The basic block checks are too expensive if there are too many blocks,
20882         // so give up unless we've been told to try hard.
20883         return;
20884     }
20885
20886     DWORD startTickCount = GetTickCount();
20887
20888 #if FEATURE_EH_FUNCLETS
20889     bool reachedFirstFunclet = false;
20890     if (fgFuncletsCreated)
20891     {
20892         //
20893         // Make sure that fgFirstFuncletBB is accurate.
20894         // It should be the first basic block in a handler region.
20895         //
20896         if (fgFirstFuncletBB != nullptr)
20897         {
20898             assert(fgFirstFuncletBB->hasHndIndex() == true);
20899             assert(fgFirstFuncletBB->bbFlags & BBF_FUNCLET_BEG);
20900         }
20901     }
20902 #endif // FEATURE_EH_FUNCLETS
20903
20904     /* Check bbNum, bbRefs and bbPreds */
20905     // First, pick a traversal stamp, and label all the blocks with it.
20906     unsigned curTraversalStamp = unsigned(InterlockedIncrement((LONG*)&bbTraverseLabel));
20907     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
20908     {
20909         block->bbTraversalStamp = curTraversalStamp;
20910     }
20911
20912     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
20913     {
20914         if (checkBBNum)
20915         {
20916             // Check that bbNum is sequential
20917             assert(block->bbNext == nullptr || (block->bbNum + 1 == block->bbNext->bbNum));
20918         }
20919
20920         // If the block is a BBJ_COND, a BBJ_SWITCH or a
20921         // lowered GT_SWITCH_TABLE node then make sure it
20922         // ends with a conditional jump or a GT_SWITCH
20923
20924         if (block->bbJumpKind == BBJ_COND)
20925         {
20926             assert(block->lastNode()->gtNext == nullptr && block->lastNode()->OperIsConditionalJump());
20927         }
20928         else if (block->bbJumpKind == BBJ_SWITCH)
20929         {
20930             assert(block->lastNode()->gtNext == nullptr &&
20931                    (block->lastNode()->gtOper == GT_SWITCH || block->lastNode()->gtOper == GT_SWITCH_TABLE));
20932         }
20933         else if (!(block->bbJumpKind == BBJ_ALWAYS || block->bbJumpKind == BBJ_RETURN))
20934         {
20935             // this block cannot have a poll
20936             assert(!(block->bbFlags & BBF_NEEDS_GCPOLL));
20937         }
20938
20939         if (block->bbCatchTyp == BBCT_FILTER)
20940         {
20941             if (!fgCheapPredsValid) // Don't check cheap preds
20942             {
20943                 // A filter has no predecessors
20944                 assert(block->bbPreds == nullptr);
20945             }
20946         }
20947
20948 #if FEATURE_EH_FUNCLETS
20949         if (fgFuncletsCreated)
20950         {
20951             //
20952             // There should be no handler blocks until
20953             // we get to the fgFirstFuncletBB block,
20954             // then every block should be a handler block
20955             //
20956             if (!reachedFirstFunclet)
20957             {
20958                 if (block == fgFirstFuncletBB)
20959                 {
20960                     assert(block->hasHndIndex() == true);
20961                     reachedFirstFunclet = true;
20962                 }
20963                 else
20964                 {
20965                     assert(block->hasHndIndex() == false);
20966                 }
20967             }
20968             else // reachedFirstFunclet
20969             {
20970                 assert(block->hasHndIndex() == true);
20971             }
20972         }
20973 #endif // FEATURE_EH_FUNCLETS
20974
20975         if (checkBBRefs)
20976         {
20977             assert(fgComputePredsDone);
20978         }
20979
20980         BBPredsChecker checker(this);
20981         unsigned       blockRefs = checker.CheckBBPreds(block, curTraversalStamp);
20982
20983         // First basic block has an additional global incoming edge.
20984         if (block == fgFirstBB)
20985         {
20986             blockRefs += 1;
20987         }
20988
20989         /* Check the bbRefs */
20990         if (checkBBRefs)
20991         {
20992             if (block->bbRefs != blockRefs)
20993             {
20994                 // Check to see if this block is the beginning of a filter or a handler and adjust the ref count
20995                 // appropriately.
20996                 for (EHblkDsc *HBtab = compHndBBtab, *HBtabEnd = &compHndBBtab[compHndBBtabCount]; HBtab != HBtabEnd;
20997                      HBtab++)
20998                 {
20999                     if (HBtab->ebdHndBeg == block)
21000                     {
21001                         blockRefs++;
21002                     }
21003                     if (HBtab->HasFilter() && (HBtab->ebdFilter == block))
21004                     {
21005                         blockRefs++;
21006                     }
21007                 }
21008             }
21009
21010             assert(block->bbRefs == blockRefs);
21011         }
21012
21013         /* Check that BBF_HAS_HANDLER is valid bbTryIndex */
21014         if (block->hasTryIndex())
21015         {
21016             assert(block->getTryIndex() < compHndBBtabCount);
21017         }
21018
21019         /* Check if BBF_RUN_RARELY is set that we have bbWeight of zero */
21020         if (block->isRunRarely())
21021         {
21022             assert(block->bbWeight == BB_ZERO_WEIGHT);
21023         }
21024         else
21025         {
21026             assert(block->bbWeight > BB_ZERO_WEIGHT);
21027         }
21028     }
21029
21030     // Make sure the one return BB is not changed.
21031     if (genReturnBB != nullptr)
21032     {
21033         assert(genReturnBB->bbTreeList);
21034         assert(genReturnBB->IsLIR() || genReturnBB->bbTreeList->gtOper == GT_STMT);
21035         assert(genReturnBB->IsLIR() || genReturnBB->bbTreeList->gtType == TYP_VOID);
21036     }
21037
21038     // The general encoder/decoder (currently) only reports "this" as a generics context as a stack location,
21039     // so we mark info.compThisArg as lvAddrTaken to ensure that it is not enregistered. Otherwise, it should
21040     // not be address-taken.  This variable determines if the address-taken-ness of "thisArg" is "OK".
21041     bool copiedForGenericsCtxt;
21042 #ifndef JIT32_GCENCODER
21043     copiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0);
21044 #else  // JIT32_GCENCODER
21045     copiedForGenericsCtxt = FALSE;
21046 #endif // JIT32_GCENCODER
21047
21048     // This if only in support of the noway_asserts it contains.
21049     if (info.compIsStatic)
21050     {
21051         // For static method, should have never grabbed the temp.
21052         assert(lvaArg0Var == BAD_VAR_NUM);
21053     }
21054     else
21055     {
21056         // For instance method:
21057         assert(info.compThisArg != BAD_VAR_NUM);
21058         bool compThisArgAddrExposedOK = !lvaTable[info.compThisArg].lvAddrExposed;
21059
21060 #ifndef JIT32_GCENCODER
21061         compThisArgAddrExposedOK = compThisArgAddrExposedOK || copiedForGenericsCtxt;
21062 #endif // !JIT32_GCENCODER
21063
21064         // Should never expose the address of arg 0 or write to arg 0.
21065         // In addition, lvArg0Var should remain 0 if arg0 is not
21066         // written to or address-exposed.
21067         assert(compThisArgAddrExposedOK && !lvaTable[info.compThisArg].lvHasILStoreOp &&
21068                (lvaArg0Var == info.compThisArg ||
21069                 lvaArg0Var != info.compThisArg && (lvaTable[lvaArg0Var].lvAddrExposed ||
21070                                                    lvaTable[lvaArg0Var].lvHasILStoreOp || copiedForGenericsCtxt)));
21071     }
21072 }
21073
21074 /*****************************************************************************
21075  *
21076  * A DEBUG routine to check the that the exception flags are correctly set.
21077  *
21078  ****************************************************************************/
21079
21080 void Compiler::fgDebugCheckFlags(GenTree* tree)
21081 {
21082     noway_assert(tree->gtOper != GT_STMT);
21083
21084     const genTreeOps oper      = tree->OperGet();
21085     const unsigned   kind      = tree->OperKind();
21086     unsigned         treeFlags = tree->gtFlags & GTF_ALL_EFFECT;
21087     unsigned         chkFlags  = 0;
21088
21089     if (tree->OperMayThrow(this))
21090     {
21091         chkFlags |= GTF_EXCEPT;
21092     }
21093
21094     if (tree->OperRequiresCallFlag(this))
21095     {
21096         chkFlags |= GTF_CALL;
21097     }
21098
21099     /* Is this a leaf node? */
21100
21101     if (kind & GTK_LEAF)
21102     {
21103         switch (oper)
21104         {
21105             case GT_CLS_VAR:
21106                 chkFlags |= GTF_GLOB_REF;
21107                 break;
21108
21109             case GT_CATCH_ARG:
21110                 chkFlags |= GTF_ORDER_SIDEEFF;
21111                 break;
21112
21113             case GT_MEMORYBARRIER:
21114                 chkFlags |= GTF_GLOB_REF | GTF_ASG;
21115                 break;
21116
21117             default:
21118                 break;
21119         }
21120     }
21121
21122     /* Is it a 'simple' unary/binary operator? */
21123
21124     else if (kind & GTK_SMPOP)
21125     {
21126         GenTree* op1 = tree->gtOp.gtOp1;
21127         GenTree* op2 = tree->gtGetOp2IfPresent();
21128
21129         // During GS work, we make shadow copies for params.
21130         // In gsParamsToShadows(), we create a shadow var of TYP_INT for every small type param.
21131         // Then in gsReplaceShadowParams(), we change the gtLclNum to the shadow var.
21132         // We also change the types of the local var tree and the assignment tree to TYP_INT if necessary.
21133         // However, since we don't morph the tree at this late stage. Manually propagating
21134         // TYP_INT up to the GT_ASG tree is only correct if we don't need to propagate the TYP_INT back up.
21135         // The following checks will ensure this.
21136
21137         // Is the left child of "tree" a GT_ASG?
21138         //
21139         // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
21140         // (or) If GT_ASG is the left child of a GT_COMMA, the type of the GT_COMMA node will
21141         // be determined by its right child. So we don't need to propagate TYP_INT up either. We are fine.
21142         if (op1 && op1->gtOper == GT_ASG)
21143         {
21144             assert(tree->gtType == TYP_VOID || tree->gtOper == GT_COMMA);
21145         }
21146
21147         // Is the right child of "tree" a GT_ASG?
21148         //
21149         // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
21150         if (op2 && op2->gtOper == GT_ASG)
21151         {
21152             assert(tree->gtType == TYP_VOID);
21153         }
21154
21155         switch (oper)
21156         {
21157             case GT_QMARK:
21158                 if (op1->OperIsCompare())
21159                 {
21160                     noway_assert(op1->gtFlags & GTF_DONT_CSE);
21161                 }
21162                 else
21163                 {
21164                     noway_assert((op1->gtOper == GT_CNS_INT) &&
21165                                  ((op1->gtIntCon.gtIconVal == 0) || (op1->gtIntCon.gtIconVal == 1)));
21166                 }
21167                 break;
21168
21169             case GT_LIST:
21170             case GT_FIELD_LIST:
21171                 if ((op2 != nullptr) && op2->OperIsAnyList())
21172                 {
21173                     ArrayStack<GenTree*> stack(this);
21174                     while ((tree->gtGetOp2() != nullptr) && tree->gtGetOp2()->OperIsAnyList())
21175                     {
21176                         stack.Push(tree);
21177                         tree = tree->gtGetOp2();
21178                     }
21179
21180                     fgDebugCheckFlags(tree);
21181
21182                     while (stack.Height() > 0)
21183                     {
21184                         tree = stack.Pop();
21185                         assert((tree->gtFlags & GTF_REVERSE_OPS) == 0);
21186                         fgDebugCheckFlags(tree->gtOp.gtOp1);
21187                         chkFlags |= (tree->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT);
21188                         chkFlags |= (tree->gtGetOp2()->gtFlags & GTF_ALL_EFFECT);
21189                         fgDebugCheckFlagsHelper(tree, (tree->gtFlags & GTF_ALL_EFFECT), chkFlags);
21190                     }
21191
21192                     return;
21193                 }
21194                 break;
21195
21196             default:
21197                 break;
21198         }
21199
21200         /* Recursively check the subtrees */
21201
21202         if (op1)
21203         {
21204             fgDebugCheckFlags(op1);
21205         }
21206         if (op2)
21207         {
21208             fgDebugCheckFlags(op2);
21209         }
21210
21211         if (op1)
21212         {
21213             chkFlags |= (op1->gtFlags & GTF_ALL_EFFECT);
21214         }
21215         if (op2)
21216         {
21217             chkFlags |= (op2->gtFlags & GTF_ALL_EFFECT);
21218         }
21219
21220         // We reuse the value of GTF_REVERSE_OPS for a GT_IND-specific flag,
21221         // so exempt that (unary) operator.
21222         if (tree->OperGet() != GT_IND && tree->gtFlags & GTF_REVERSE_OPS)
21223         {
21224             /* Must have two operands if GTF_REVERSE is set */
21225             noway_assert(op1 && op2);
21226
21227             /* Make sure that the order of side effects has not been swapped. */
21228
21229             /* However CSE may introduce an assignment after the reverse flag
21230                was set and thus GTF_ASG cannot be considered here. */
21231
21232             /* For a GT_ASG(GT_IND(x), y) we are interested in the side effects of x */
21233             GenTree* op1p;
21234             if (GenTree::OperIsAssignment(oper) && (op1->gtOper == GT_IND))
21235             {
21236                 op1p = op1->gtOp.gtOp1;
21237             }
21238             else
21239             {
21240                 op1p = op1;
21241             }
21242
21243             /* This isn't true any more with the sticky GTF_REVERSE */
21244             /*
21245             // if op1p has side effects, then op2 cannot have side effects
21246             if (op1p->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
21247             {
21248                 if (op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
21249                     gtDispTree(tree);
21250                 noway_assert(!(op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG)));
21251             }
21252             */
21253         }
21254
21255         if (tree->OperRequiresAsgFlag())
21256         {
21257             chkFlags |= GTF_ASG;
21258         }
21259
21260         if (oper == GT_ADDR && (op1->OperIsLocal() || op1->gtOper == GT_CLS_VAR ||
21261                                 (op1->gtOper == GT_IND && op1->gtOp.gtOp1->gtOper == GT_CLS_VAR_ADDR)))
21262         {
21263             /* &aliasedVar doesn't need GTF_GLOB_REF, though alisasedVar does.
21264                Similarly for clsVar */
21265             treeFlags |= GTF_GLOB_REF;
21266         }
21267     }
21268
21269     /* See what kind of a special operator we have here */
21270
21271     else
21272     {
21273         switch (tree->OperGet())
21274         {
21275             case GT_CALL:
21276
21277                 GenTree*     args;
21278                 GenTree*     argx;
21279                 GenTreeCall* call;
21280
21281                 call = tree->AsCall();
21282
21283                 if (call->gtCallObjp)
21284                 {
21285                     fgDebugCheckFlags(call->gtCallObjp);
21286                     chkFlags |= (call->gtCallObjp->gtFlags & GTF_SIDE_EFFECT);
21287
21288                     if (call->gtCallObjp->gtFlags & GTF_ASG)
21289                     {
21290                         treeFlags |= GTF_ASG;
21291                     }
21292                 }
21293
21294                 for (args = call->gtCallArgs; args; args = args->gtOp.gtOp2)
21295                 {
21296                     argx = args->gtOp.gtOp1;
21297                     fgDebugCheckFlags(argx);
21298
21299                     chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT);
21300
21301                     if (argx->gtFlags & GTF_ASG)
21302                     {
21303                         treeFlags |= GTF_ASG;
21304                     }
21305                 }
21306
21307                 for (args = call->gtCallLateArgs; args; args = args->gtOp.gtOp2)
21308                 {
21309                     argx = args->gtOp.gtOp1;
21310                     fgDebugCheckFlags(argx);
21311
21312                     chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT);
21313
21314                     if (argx->gtFlags & GTF_ASG)
21315                     {
21316                         treeFlags |= GTF_ASG;
21317                     }
21318                 }
21319
21320                 if ((call->gtCallType == CT_INDIRECT) && (call->gtCallCookie != nullptr))
21321                 {
21322                     fgDebugCheckFlags(call->gtCallCookie);
21323                     chkFlags |= (call->gtCallCookie->gtFlags & GTF_SIDE_EFFECT);
21324                 }
21325
21326                 if (call->gtCallType == CT_INDIRECT)
21327                 {
21328                     fgDebugCheckFlags(call->gtCallAddr);
21329                     chkFlags |= (call->gtCallAddr->gtFlags & GTF_SIDE_EFFECT);
21330                 }
21331
21332                 if (call->IsUnmanaged() && (call->gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL))
21333                 {
21334                     if (call->gtCallArgs->gtOp.gtOp1->OperGet() == GT_NOP)
21335                     {
21336                         noway_assert(call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL ||
21337                                      call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF);
21338                     }
21339                     else
21340                     {
21341                         noway_assert(call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL ||
21342                                      call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF);
21343                     }
21344                 }
21345                 break;
21346
21347             case GT_ARR_ELEM:
21348
21349                 GenTree* arrObj;
21350                 unsigned dim;
21351
21352                 arrObj = tree->gtArrElem.gtArrObj;
21353                 fgDebugCheckFlags(arrObj);
21354                 chkFlags |= (arrObj->gtFlags & GTF_ALL_EFFECT);
21355
21356                 for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
21357                 {
21358                     fgDebugCheckFlags(tree->gtArrElem.gtArrInds[dim]);
21359                     chkFlags |= tree->gtArrElem.gtArrInds[dim]->gtFlags & GTF_ALL_EFFECT;
21360                 }
21361                 break;
21362
21363             case GT_ARR_OFFSET:
21364
21365                 fgDebugCheckFlags(tree->gtArrOffs.gtOffset);
21366                 chkFlags |= (tree->gtArrOffs.gtOffset->gtFlags & GTF_ALL_EFFECT);
21367                 fgDebugCheckFlags(tree->gtArrOffs.gtIndex);
21368                 chkFlags |= (tree->gtArrOffs.gtIndex->gtFlags & GTF_ALL_EFFECT);
21369                 fgDebugCheckFlags(tree->gtArrOffs.gtArrObj);
21370                 chkFlags |= (tree->gtArrOffs.gtArrObj->gtFlags & GTF_ALL_EFFECT);
21371                 break;
21372
21373             case GT_ARR_BOUNDS_CHECK:
21374 #ifdef FEATURE_SIMD
21375             case GT_SIMD_CHK:
21376 #endif // FEATURE_SIMD
21377 #ifdef FEATURE_HW_INTRINSICS
21378             case GT_HW_INTRINSIC_CHK:
21379 #endif // FEATURE_HW_INTRINSICS
21380
21381                 GenTreeBoundsChk* bndsChk;
21382                 bndsChk = tree->AsBoundsChk();
21383                 fgDebugCheckFlags(bndsChk->gtIndex);
21384                 chkFlags |= (bndsChk->gtIndex->gtFlags & GTF_ALL_EFFECT);
21385                 fgDebugCheckFlags(bndsChk->gtArrLen);
21386                 chkFlags |= (bndsChk->gtArrLen->gtFlags & GTF_ALL_EFFECT);
21387                 break;
21388
21389             case GT_CMPXCHG:
21390
21391                 chkFlags |= (GTF_GLOB_REF | GTF_ASG);
21392                 GenTreeCmpXchg* cmpXchg;
21393                 cmpXchg = tree->AsCmpXchg();
21394                 fgDebugCheckFlags(cmpXchg->gtOpLocation);
21395                 chkFlags |= (cmpXchg->gtOpLocation->gtFlags & GTF_ALL_EFFECT);
21396                 fgDebugCheckFlags(cmpXchg->gtOpValue);
21397                 chkFlags |= (cmpXchg->gtOpValue->gtFlags & GTF_ALL_EFFECT);
21398                 fgDebugCheckFlags(cmpXchg->gtOpComparand);
21399                 chkFlags |= (cmpXchg->gtOpComparand->gtFlags & GTF_ALL_EFFECT);
21400                 break;
21401
21402             case GT_STORE_DYN_BLK:
21403             case GT_DYN_BLK:
21404
21405                 GenTreeDynBlk* dynBlk;
21406                 dynBlk = tree->AsDynBlk();
21407                 fgDebugCheckFlags(dynBlk->gtDynamicSize);
21408                 chkFlags |= (dynBlk->gtDynamicSize->gtFlags & GTF_ALL_EFFECT);
21409                 fgDebugCheckFlags(dynBlk->Addr());
21410                 chkFlags |= (dynBlk->Addr()->gtFlags & GTF_ALL_EFFECT);
21411                 if (tree->OperGet() == GT_STORE_DYN_BLK)
21412                 {
21413                     fgDebugCheckFlags(dynBlk->Data());
21414                     chkFlags |= (dynBlk->Data()->gtFlags & GTF_ALL_EFFECT);
21415                 }
21416                 break;
21417
21418             default:
21419
21420 #ifdef DEBUG
21421                 gtDispTree(tree);
21422 #endif
21423
21424                 assert(!"Unknown operator for fgDebugCheckFlags");
21425                 break;
21426         }
21427     }
21428
21429     fgDebugCheckFlagsHelper(tree, treeFlags, chkFlags);
21430 }
21431
21432 //------------------------------------------------------------------------------
21433 // fgDebugCheckFlagsHelper : Check if all bits that are set in chkFlags are also set in treeFlags.
21434 //
21435 //
21436 // Arguments:
21437 //    tree  - Tree whose flags are being checked
21438 //    treeFlags - Actual flags on the tree
21439 //    chkFlags - Expected flags
21440 //
21441 // Note:
21442 //    Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled.
21443
21444 void Compiler::fgDebugCheckFlagsHelper(GenTree* tree, unsigned treeFlags, unsigned chkFlags)
21445 {
21446     if (chkFlags & ~treeFlags)
21447     {
21448         // Print the tree so we can see it in the log.
21449         printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
21450         GenTree::gtDispFlags(chkFlags & ~treeFlags, GTF_DEBUG_NONE);
21451         printf("\n");
21452         gtDispTree(tree);
21453
21454         noway_assert(!"Missing flags on tree");
21455
21456         // Print the tree again so we can see it right after we hook up the debugger.
21457         printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
21458         GenTree::gtDispFlags(chkFlags & ~treeFlags, GTF_DEBUG_NONE);
21459         printf("\n");
21460         gtDispTree(tree);
21461     }
21462     else if (treeFlags & ~chkFlags)
21463     {
21464         // TODO: We are currently only checking extra GTF_EXCEPT, GTF_ASG, and GTF_CALL flags.
21465         if ((treeFlags & ~chkFlags & ~GTF_GLOB_REF & ~GTF_ORDER_SIDEEFF) != 0)
21466         {
21467             // Print the tree so we can see it in the log.
21468             printf("Extra flags on parent tree [%X]: ", tree);
21469             GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE);
21470             printf("\n");
21471             gtDispTree(tree);
21472
21473             noway_assert(!"Extra flags on tree");
21474
21475             // Print the tree again so we can see it right after we hook up the debugger.
21476             printf("Extra flags on parent tree [%X]: ", tree);
21477             GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE);
21478             printf("\n");
21479             gtDispTree(tree);
21480         }
21481     }
21482 }
21483
21484 // DEBUG routine to check correctness of the internal gtNext, gtPrev threading of a statement.
21485 // This threading is only valid when fgStmtListThreaded is true.
21486 // This calls an alternate method for FGOrderLinear.
21487 void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node)
21488 {
21489     // LIR blocks are checked using BasicBlock::CheckLIR().
21490     if (block->IsLIR())
21491     {
21492         LIR::AsRange(block).CheckLIR(this);
21493         // TODO: return?
21494     }
21495
21496     GenTreeStmt* stmt = node->AsStmt();
21497
21498     assert(fgStmtListThreaded);
21499
21500     noway_assert(stmt->gtStmtList);
21501
21502     // The first node's gtPrev must be nullptr (the gtPrev list is not circular).
21503     // The last node's gtNext must be nullptr (the gtNext list is not circular). This is tested if the loop below
21504     // terminates.
21505     assert(stmt->gtStmtList->gtPrev == nullptr);
21506
21507     for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext)
21508     {
21509         if (tree->gtPrev)
21510         {
21511             noway_assert(tree->gtPrev->gtNext == tree);
21512         }
21513         else
21514         {
21515             noway_assert(tree == stmt->gtStmtList);
21516         }
21517
21518         if (tree->gtNext)
21519         {
21520             noway_assert(tree->gtNext->gtPrev == tree);
21521         }
21522         else
21523         {
21524             noway_assert(tree == stmt->gtStmtExpr);
21525         }
21526
21527         /* Cross-check gtPrev,gtNext with gtOp for simple trees */
21528
21529         GenTree* expectedPrevTree = nullptr;
21530
21531         if (tree->OperIsLeaf())
21532         {
21533             if (tree->gtOper == GT_CATCH_ARG)
21534             {
21535                 // The GT_CATCH_ARG should always have GTF_ORDER_SIDEEFF set
21536                 noway_assert(tree->gtFlags & GTF_ORDER_SIDEEFF);
21537                 // The GT_CATCH_ARG has to be the first thing evaluated
21538                 noway_assert(stmt == block->FirstNonPhiDef());
21539                 noway_assert(stmt->gtStmtList->gtOper == GT_CATCH_ARG);
21540                 // The root of the tree should have GTF_ORDER_SIDEEFF set
21541                 noway_assert(stmt->gtStmtExpr->gtFlags & GTF_ORDER_SIDEEFF);
21542             }
21543         }
21544
21545         if (tree->OperIsUnary() && tree->gtOp.gtOp1)
21546         {
21547             expectedPrevTree = tree->gtOp.gtOp1;
21548         }
21549         else if (tree->OperIsBinary() && tree->gtOp.gtOp1)
21550         {
21551             switch (tree->gtOper)
21552             {
21553                 case GT_QMARK:
21554                     expectedPrevTree =
21555                         tree->gtOp.gtOp2->AsColon()->ThenNode(); // "then" operand of the GT_COLON (generated second).
21556                     break;
21557
21558                 case GT_COLON:
21559                     expectedPrevTree = tree->AsColon()->ElseNode(); // "else" branch result (generated first).
21560                     break;
21561
21562                 default:
21563                     if (tree->gtOp.gtOp2)
21564                     {
21565                         if (tree->gtFlags & GTF_REVERSE_OPS)
21566                         {
21567                             expectedPrevTree = tree->gtOp.gtOp1;
21568                         }
21569                         else
21570                         {
21571                             expectedPrevTree = tree->gtOp.gtOp2;
21572                         }
21573                     }
21574                     else
21575                     {
21576                         expectedPrevTree = tree->gtOp.gtOp1;
21577                     }
21578                     break;
21579             }
21580         }
21581
21582         noway_assert(expectedPrevTree == nullptr ||     // No expectations about the prev node
21583                      tree->gtPrev == expectedPrevTree); // The "normal" case
21584     }
21585 }
21586
21587 /*****************************************************************************
21588  *
21589  * A DEBUG routine to check the correctness of the links between GT_STMT nodes
21590  * and ordinary nodes within a statement.
21591  *
21592  ****************************************************************************/
21593
21594 void Compiler::fgDebugCheckLinks(bool morphTrees)
21595 {
21596     // This used to be only on for stress, and there was a comment stating that
21597     // it was "quite an expensive operation" but I did not find that to be true.
21598     // Set DO_SANITY_DEBUG_CHECKS to false to revert to that behavior.
21599     const bool DO_SANITY_DEBUG_CHECKS = true;
21600
21601     if (!DO_SANITY_DEBUG_CHECKS && !compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))
21602     {
21603         return;
21604     }
21605
21606     fgDebugCheckBlockLinks();
21607
21608     /* For each basic block check the bbTreeList links */
21609     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
21610     {
21611         if (block->IsLIR())
21612         {
21613             LIR::AsRange(block).CheckLIR(this);
21614         }
21615         else
21616         {
21617             fgDebugCheckStmtsList(block, morphTrees);
21618         }
21619     }
21620
21621     fgDebugCheckNodesUniqueness();
21622 }
21623
21624 //------------------------------------------------------------------------------
21625 // fgDebugCheckStmtsList : Perfoms the set of checks:
21626 //    - all statements in the block are linked correctly
21627 //    - check statements flags
21628 //    - check nodes gtNext and gtPrev values, if the node list is threaded
21629 //
21630 // Arguments:
21631 //    block  - the block to check statements in
21632 //    morphTrees - try to morph trees in the checker
21633 //
21634 // Note:
21635 //    Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled.
21636
21637 void Compiler::fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees)
21638 {
21639     for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
21640     {
21641         /* Verify that bbTreeList is threaded correctly */
21642         /* Note that for the GT_STMT list, the gtPrev list is circular. The gtNext list is not: gtNext of the
21643         * last GT_STMT in a block is nullptr. */
21644
21645         noway_assert(stmt->gtPrev);
21646
21647         if (stmt == block->bbTreeList)
21648         {
21649             noway_assert(stmt->gtPrev->gtNext == nullptr);
21650         }
21651         else
21652         {
21653             noway_assert(stmt->gtPrev->gtNext == stmt);
21654         }
21655
21656         if (stmt->gtNext)
21657         {
21658             noway_assert(stmt->gtNext->gtPrev == stmt);
21659         }
21660         else
21661         {
21662             noway_assert(block->lastStmt() == stmt);
21663         }
21664
21665         /* For each statement check that the exception flags are properly set */
21666
21667         noway_assert(stmt->gtStmtExpr);
21668
21669         if (verbose && 0)
21670         {
21671             gtDispTree(stmt->gtStmtExpr);
21672         }
21673
21674         fgDebugCheckFlags(stmt->gtStmtExpr);
21675
21676         // Not only will this stress fgMorphBlockStmt(), but we also get all the checks
21677         // done by fgMorphTree()
21678
21679         if (morphTrees)
21680         {
21681             // If 'stmt' is removed from the block, start a new check for the current block,
21682             // break the current check.
21683             if (fgMorphBlockStmt(block, stmt DEBUGARG("test morphing")))
21684             {
21685                 fgDebugCheckStmtsList(block, morphTrees);
21686                 break;
21687             }
21688         }
21689
21690         /* For each GT_STMT node check that the nodes are threaded correcly - gtStmtList */
21691
21692         if (fgStmtListThreaded)
21693         {
21694             fgDebugCheckNodeLinks(block, stmt);
21695         }
21696     }
21697 }
21698
21699 // ensure that bbNext and bbPrev are consistent
21700 void Compiler::fgDebugCheckBlockLinks()
21701 {
21702     assert(fgFirstBB->bbPrev == nullptr);
21703
21704     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
21705     {
21706         if (block->bbNext)
21707         {
21708             assert(block->bbNext->bbPrev == block);
21709         }
21710         else
21711         {
21712             assert(block == fgLastBB);
21713         }
21714
21715         if (block->bbPrev)
21716         {
21717             assert(block->bbPrev->bbNext == block);
21718         }
21719         else
21720         {
21721             assert(block == fgFirstBB);
21722         }
21723
21724         // If this is a switch, check that the tables are consistent.
21725         // Note that we don't call GetSwitchDescMap(), because it has the side-effect
21726         // of allocating it if it is not present.
21727         if (block->bbJumpKind == BBJ_SWITCH && m_switchDescMap != nullptr)
21728         {
21729             SwitchUniqueSuccSet uniqueSuccSet;
21730             if (m_switchDescMap->Lookup(block, &uniqueSuccSet))
21731             {
21732                 // Create a set with all the successors. Don't use BlockSet, so we don't need to worry
21733                 // about the BlockSet epoch.
21734                 BitVecTraits bitVecTraits(fgBBNumMax + 1, this);
21735                 BitVec       succBlocks(BitVecOps::MakeEmpty(&bitVecTraits));
21736                 BasicBlock** jumpTable = block->bbJumpSwt->bbsDstTab;
21737                 unsigned     jumpCount = block->bbJumpSwt->bbsCount;
21738                 for (unsigned i = 0; i < jumpCount; i++)
21739                 {
21740                     BitVecOps::AddElemD(&bitVecTraits, succBlocks, jumpTable[i]->bbNum);
21741                 }
21742                 // Now we should have a set of unique successors that matches what's in the switchMap.
21743                 // First, check the number of entries, then make sure all the blocks in uniqueSuccSet
21744                 // are in the BlockSet.
21745                 unsigned count = BitVecOps::Count(&bitVecTraits, succBlocks);
21746                 assert(uniqueSuccSet.numDistinctSuccs == count);
21747                 for (unsigned i = 0; i < uniqueSuccSet.numDistinctSuccs; i++)
21748                 {
21749                     assert(BitVecOps::IsMember(&bitVecTraits, succBlocks, uniqueSuccSet.nonDuplicates[i]->bbNum));
21750                 }
21751             }
21752         }
21753     }
21754 }
21755
21756 // UniquenessCheckWalker keeps data that is neccesary to check
21757 // that each tree has it is own unique id and they do not repeat.
21758 class UniquenessCheckWalker
21759 {
21760 public:
21761     UniquenessCheckWalker(Compiler* comp)
21762         : comp(comp), nodesVecTraits(comp->compGenTreeID, comp), uniqueNodes(BitVecOps::MakeEmpty(&nodesVecTraits))
21763     {
21764     }
21765
21766     //------------------------------------------------------------------------
21767     // fgMarkTreeId: Visit all subtrees in the tree and check gtTreeIDs.
21768     //
21769     // Arguments:
21770     //    pTree     - Pointer to the tree to walk
21771     //    fgWalkPre - the UniquenessCheckWalker instance
21772     //
21773     static Compiler::fgWalkResult MarkTreeId(GenTree** pTree, Compiler::fgWalkData* fgWalkPre)
21774     {
21775         UniquenessCheckWalker* walker   = static_cast<UniquenessCheckWalker*>(fgWalkPre->pCallbackData);
21776         unsigned               gtTreeID = (*pTree)->gtTreeID;
21777         walker->CheckTreeId(gtTreeID);
21778         return Compiler::WALK_CONTINUE;
21779     }
21780
21781     //------------------------------------------------------------------------
21782     // CheckTreeId: Check that this tree was not visit before and memorize it as visited.
21783     //
21784     // Arguments:
21785     //    gtTreeID - identificator of GenTree.
21786     //
21787     void CheckTreeId(unsigned gtTreeID)
21788     {
21789         assert(!BitVecOps::IsMember(&nodesVecTraits, uniqueNodes, gtTreeID));
21790         BitVecOps::AddElemD(&nodesVecTraits, uniqueNodes, gtTreeID);
21791     }
21792
21793 private:
21794     Compiler*    comp;
21795     BitVecTraits nodesVecTraits;
21796     BitVec       uniqueNodes;
21797 };
21798
21799 //------------------------------------------------------------------------------
21800 // fgDebugCheckNodesUniqueness: Check that each tree in the method has its own unique gtTreeId.
21801 //
21802 void Compiler::fgDebugCheckNodesUniqueness()
21803 {
21804     UniquenessCheckWalker walker(this);
21805
21806     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
21807     {
21808         if (block->IsLIR())
21809         {
21810             for (GenTree* i : LIR::AsRange(block))
21811             {
21812                 walker.CheckTreeId(i->gtTreeID);
21813             }
21814         }
21815         else
21816         {
21817             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
21818             {
21819                 GenTree* root = stmt->gtStmtExpr;
21820                 fgWalkTreePre(&root, UniquenessCheckWalker::MarkTreeId, &walker);
21821             }
21822         }
21823     }
21824 }
21825
21826 /*****************************************************************************/
21827 #endif // DEBUG
21828 /*****************************************************************************/
21829
21830 //------------------------------------------------------------------------
21831 // fgCheckForInlineDepthAndRecursion: compute depth of the candidate, and
21832 // check for recursion.
21833 //
21834 // Return Value:
21835 //    The depth of the inline candidate. The root method is a depth 0, top-level
21836 //    candidates at depth 1, etc.
21837 //
21838 // Notes:
21839 //    We generally disallow recursive inlines by policy. However, they are
21840 //    supported by the underlying machinery.
21841 //
21842 //    Likewise the depth limit is a policy consideration, and serves mostly
21843 //    as a safeguard to prevent runaway inlining of small methods.
21844 //
21845 unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo)
21846 {
21847     BYTE*          candidateCode = inlineInfo->inlineCandidateInfo->methInfo.ILCode;
21848     InlineContext* inlineContext = inlineInfo->iciStmt->gtInlineContext;
21849     InlineResult*  inlineResult  = inlineInfo->inlineResult;
21850
21851     // There should be a context for all candidates.
21852     assert(inlineContext != nullptr);
21853     int depth = 0;
21854
21855     for (; inlineContext != nullptr; inlineContext = inlineContext->GetParent())
21856     {
21857
21858         depth++;
21859
21860         if (inlineContext->GetCode() == candidateCode)
21861         {
21862             // This inline candidate has the same IL code buffer as an already
21863             // inlined method does.
21864             inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_RECURSIVE);
21865             break;
21866         }
21867
21868         if (depth > InlineStrategy::IMPLEMENTATION_MAX_INLINE_DEPTH)
21869         {
21870             break;
21871         }
21872     }
21873
21874     inlineResult->NoteInt(InlineObservation::CALLSITE_DEPTH, depth);
21875     return depth;
21876 }
21877
21878 /*****************************************************************************
21879  *
21880  *  Inlining phase
21881  */
21882
21883 void Compiler::fgInline()
21884 {
21885     if (!opts.OptEnabled(CLFLG_INLINING))
21886     {
21887         return;
21888     }
21889
21890 #ifdef DEBUG
21891     if (verbose)
21892     {
21893         printf("*************** In fgInline()\n");
21894     }
21895 #endif // DEBUG
21896
21897     BasicBlock* block = fgFirstBB;
21898     noway_assert(block != nullptr);
21899
21900     // Set the root inline context on all statements
21901     InlineContext* rootContext = m_inlineStrategy->GetRootContext();
21902
21903     for (; block != nullptr; block = block->bbNext)
21904     {
21905         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
21906         {
21907             stmt->gtInlineContext = rootContext;
21908         }
21909     }
21910
21911     // Reset block back to start for inlining
21912     block = fgFirstBB;
21913
21914     do
21915     {
21916         /* Make the current basic block address available globally */
21917
21918         compCurBB = block;
21919
21920         GenTreeStmt* stmt;
21921         GenTree*     expr;
21922
21923         for (stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
21924         {
21925             expr = stmt->gtStmtExpr;
21926
21927             // See if we can expand the inline candidate
21928             if ((expr->gtOper == GT_CALL) && ((expr->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0))
21929             {
21930                 GenTreeCall* call = expr->AsCall();
21931                 InlineResult inlineResult(this, call, stmt, "fgInline");
21932
21933                 fgMorphStmt = stmt;
21934
21935                 fgMorphCallInline(call, &inlineResult);
21936
21937                 if (stmt->gtStmtExpr->IsNothingNode())
21938                 {
21939                     fgRemoveStmt(block, stmt);
21940                     continue;
21941                 }
21942             }
21943             else
21944             {
21945 #ifdef DEBUG
21946                 // Look for non-candidates.
21947                 fgWalkTreePre(&stmt->gtStmtExpr, fgFindNonInlineCandidate, stmt);
21948 #endif
21949             }
21950
21951             // See if we need to replace the return value place holder.
21952             // Also, see if this update enables further devirtualization.
21953             fgWalkTreePre(&stmt->gtStmtExpr, fgUpdateInlineReturnExpressionPlaceHolder, (void*)this);
21954
21955             // See if stmt is of the form GT_COMMA(call, nop)
21956             // If yes, we can get rid of GT_COMMA.
21957             if (expr->OperGet() == GT_COMMA && expr->gtOp.gtOp1->OperGet() == GT_CALL &&
21958                 expr->gtOp.gtOp2->OperGet() == GT_NOP)
21959             {
21960                 stmt->gtStmtExpr = expr->gtOp.gtOp1;
21961             }
21962         }
21963
21964         block = block->bbNext;
21965
21966     } while (block);
21967
21968 #ifdef DEBUG
21969
21970     // Check that we should not have any inline candidate or return value place holder left.
21971
21972     block = fgFirstBB;
21973     noway_assert(block);
21974
21975     do
21976     {
21977         GenTreeStmt* stmt;
21978
21979         for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
21980         {
21981             // Call Compiler::fgDebugCheckInlineCandidates on each node
21982             fgWalkTreePre(&stmt->gtStmtExpr, fgDebugCheckInlineCandidates);
21983         }
21984
21985         block = block->bbNext;
21986
21987     } while (block);
21988
21989     fgVerifyHandlerTab();
21990
21991     if (verbose)
21992     {
21993         printf("*************** After fgInline()\n");
21994         fgDispBasicBlocks(true);
21995         fgDispHandlerTab();
21996     }
21997
21998     if (verbose || fgPrintInlinedMethods)
21999     {
22000         printf("**************** Inline Tree\n");
22001         m_inlineStrategy->Dump();
22002     }
22003
22004 #endif // DEBUG
22005 }
22006
22007 #ifdef DEBUG
22008
22009 //------------------------------------------------------------------------
22010 // fgFindNonInlineCandidate: tree walk helper to ensure that a tree node
22011 // that is not an inline candidate is noted as a failed inline.
22012 //
22013 // Arguments:
22014 //    pTree - pointer to pointer tree node being walked
22015 //    data  - contextual data for the walk
22016 //
22017 // Return Value:
22018 //    walk result
22019 //
22020 // Note:
22021 //    Invokes fgNoteNonInlineCandidate on the nodes it finds.
22022
22023 Compiler::fgWalkResult Compiler::fgFindNonInlineCandidate(GenTree** pTree, fgWalkData* data)
22024 {
22025     GenTree* tree = *pTree;
22026     if (tree->gtOper == GT_CALL)
22027     {
22028         Compiler*    compiler = data->compiler;
22029         GenTreeStmt* stmt     = (GenTreeStmt*)data->pCallbackData;
22030         GenTreeCall* call     = tree->AsCall();
22031
22032         compiler->fgNoteNonInlineCandidate(stmt, call);
22033     }
22034     return WALK_CONTINUE;
22035 }
22036
22037 //------------------------------------------------------------------------
22038 // fgNoteNonInlineCandidate: account for inlining failures in calls
22039 // not marked as inline candidates.
22040 //
22041 // Arguments:
22042 //    stmt  - statement containing the call
22043 //    call  - the call itself
22044 //
22045 // Notes:
22046 //    Used in debug only to try and place descriptions of inline failures
22047 //    into the proper context in the inline tree.
22048
22049 void Compiler::fgNoteNonInlineCandidate(GenTreeStmt* stmt, GenTreeCall* call)
22050 {
22051     InlineResult      inlineResult(this, call, nullptr, "fgNotInlineCandidate");
22052     InlineObservation currentObservation = InlineObservation::CALLSITE_NOT_CANDIDATE;
22053
22054     // Try and recover the reason left behind when the jit decided
22055     // this call was not a candidate.
22056     InlineObservation priorObservation = call->gtInlineObservation;
22057
22058     if (InlIsValidObservation(priorObservation))
22059     {
22060         currentObservation = priorObservation;
22061     }
22062
22063     // Propagate the prior failure observation to this result.
22064     inlineResult.NotePriorFailure(currentObservation);
22065     inlineResult.SetReported();
22066
22067     if (call->gtCallType == CT_USER_FUNC)
22068     {
22069         // Create InlineContext for the failure
22070         m_inlineStrategy->NewFailure(stmt, &inlineResult);
22071     }
22072 }
22073
22074 #endif
22075
22076 #if FEATURE_MULTIREG_RET
22077
22078 /*********************************************************************************
22079  *
22080  * tree - The node which needs to be converted to a struct pointer.
22081  *
22082  *  Return the pointer by either __replacing__ the tree node with a suitable pointer
22083  *  type or __without replacing__ and just returning a subtree or by __modifying__
22084  *  a subtree.
22085  */
22086 GenTree* Compiler::fgGetStructAsStructPtr(GenTree* tree)
22087 {
22088     noway_assert((tree->gtOper == GT_LCL_VAR) || (tree->gtOper == GT_FIELD) || (tree->gtOper == GT_IND) ||
22089                  (tree->gtOper == GT_BLK) || (tree->gtOper == GT_OBJ) || tree->OperIsSIMD() ||
22090                  // tree->gtOper == GT_CALL     || cannot get address of call.
22091                  // tree->gtOper == GT_MKREFANY || inlining should've been aborted due to mkrefany opcode.
22092                  // tree->gtOper == GT_RET_EXPR || cannot happen after fgUpdateInlineReturnExpressionPlaceHolder
22093                  (tree->gtOper == GT_COMMA));
22094
22095     switch (tree->OperGet())
22096     {
22097         case GT_BLK:
22098         case GT_OBJ:
22099         case GT_IND:
22100             return tree->gtOp.gtOp1;
22101
22102         case GT_COMMA:
22103             tree->gtOp.gtOp2 = fgGetStructAsStructPtr(tree->gtOp.gtOp2);
22104             tree->gtType     = TYP_BYREF;
22105             return tree;
22106
22107         default:
22108             return gtNewOperNode(GT_ADDR, TYP_BYREF, tree);
22109     }
22110 }
22111
22112 /***************************************************************************************************
22113  * child     - The inlinee of the retExpr node.
22114  * retClsHnd - The struct class handle of the type of the inlinee.
22115  *
22116  * Assign the inlinee to a tmp, if it is a call, just assign it to a lclVar, else we can
22117  * use a copyblock to do the assignment.
22118  */
22119 GenTree* Compiler::fgAssignStructInlineeToVar(GenTree* child, CORINFO_CLASS_HANDLE retClsHnd)
22120 {
22121     assert(child->gtOper != GT_RET_EXPR && child->gtOper != GT_MKREFANY);
22122
22123     unsigned tmpNum = lvaGrabTemp(false DEBUGARG("RetBuf for struct inline return candidates."));
22124     lvaSetStruct(tmpNum, retClsHnd, false);
22125     var_types structType = lvaTable[tmpNum].lvType;
22126
22127     GenTree* dst = gtNewLclvNode(tmpNum, structType);
22128
22129     // If we have a call, we'd like it to be: V00 = call(), but first check if
22130     // we have a ", , , call()" -- this is very defensive as we may never get
22131     // an inlinee that is made of commas. If the inlinee is not a call, then
22132     // we use a copy block to do the assignment.
22133     GenTree* src       = child;
22134     GenTree* lastComma = nullptr;
22135     while (src->gtOper == GT_COMMA)
22136     {
22137         lastComma = src;
22138         src       = src->gtOp.gtOp2;
22139     }
22140
22141     GenTree* newInlinee = nullptr;
22142     if (src->gtOper == GT_CALL)
22143     {
22144         // If inlinee was just a call, new inlinee is v05 = call()
22145         newInlinee = gtNewAssignNode(dst, src);
22146
22147         // When returning a multi-register value in a local var, make sure the variable is
22148         // marked as lvIsMultiRegRet, so it does not get promoted.
22149         if (src->AsCall()->HasMultiRegRetVal())
22150         {
22151             lvaTable[tmpNum].lvIsMultiRegRet = true;
22152         }
22153
22154         // If inlinee was comma, but a deeper call, new inlinee is (, , , v05 = call())
22155         if (child->gtOper == GT_COMMA)
22156         {
22157             lastComma->gtOp.gtOp2 = newInlinee;
22158             newInlinee            = child;
22159         }
22160     }
22161     else
22162     {
22163         // Inlinee is not a call, so just create a copy block to the tmp.
22164         src              = child;
22165         GenTree* dstAddr = fgGetStructAsStructPtr(dst);
22166         GenTree* srcAddr = fgGetStructAsStructPtr(src);
22167         newInlinee       = gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false);
22168     }
22169
22170     GenTree* production = gtNewLclvNode(tmpNum, structType);
22171     return gtNewOperNode(GT_COMMA, structType, newInlinee, production);
22172 }
22173
22174 /***************************************************************************************************
22175  * tree      - The tree pointer that has one of its child nodes as retExpr.
22176  * child     - The inlinee child.
22177  * retClsHnd - The struct class handle of the type of the inlinee.
22178  *
22179  * V04 = call() assignments are okay as we codegen it. Everything else needs to be a copy block or
22180  * would need a temp. For example, a cast(ldobj) will then be, cast(v05 = ldobj, v05); But it is
22181  * a very rare (or impossible) scenario that we'd have a retExpr transform into a ldobj other than
22182  * a lclVar/call. So it is not worthwhile to do pattern matching optimizations like addr(ldobj(op1))
22183  * can just be op1.
22184  */
22185 void Compiler::fgAttachStructInlineeToAsg(GenTree* tree, GenTree* child, CORINFO_CLASS_HANDLE retClsHnd)
22186 {
22187     // We are okay to have:
22188     // 1. V02 = call();
22189     // 2. copyBlk(dstAddr, srcAddr);
22190     assert(tree->gtOper == GT_ASG);
22191
22192     // We have an assignment, we codegen only V05 = call().
22193     if (child->gtOper == GT_CALL && tree->gtOp.gtOp1->gtOper == GT_LCL_VAR)
22194     {
22195         // If it is a multireg return on x64/ux, the local variable should be marked as lvIsMultiRegRet
22196         if (child->AsCall()->HasMultiRegRetVal())
22197         {
22198             unsigned lclNum                  = tree->gtOp.gtOp1->gtLclVarCommon.gtLclNum;
22199             lvaTable[lclNum].lvIsMultiRegRet = true;
22200         }
22201         return;
22202     }
22203
22204     GenTree* dstAddr = fgGetStructAsStructPtr(tree->gtOp.gtOp1);
22205     GenTree* srcAddr = fgGetStructAsStructPtr(
22206         (child->gtOper == GT_CALL)
22207             ? fgAssignStructInlineeToVar(child, retClsHnd) // Assign to a variable if it is a call.
22208             : child);                                      // Just get the address, if not a call.
22209
22210     tree->ReplaceWith(gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false), this);
22211 }
22212
22213 #endif // FEATURE_MULTIREG_RET
22214
22215 //------------------------------------------------------------------------
22216 // fgUpdateInlineReturnExpressionPlaceHolder: callback to replace the
22217 // inline return expression placeholder.
22218 //
22219 // Arguments:
22220 //    pTree -- pointer to tree to examine for updates
22221 //    data  -- context data for the tree walk
22222 //
22223 // Returns:
22224 //    fgWalkResult indicating the walk should continue; that
22225 //    is we wish to fully explore the tree.
22226 //
22227 // Notes:
22228 //    Looks for GT_RET_EXPR nodes that arose from tree splitting done
22229 //    during importation for inline candidates, and replaces them.
22230 //
22231 //    For successful inlines, substitutes the return value expression
22232 //    from the inline body for the GT_RET_EXPR.
22233 //
22234 //    For failed inlines, rejoins the original call into the tree from
22235 //    whence it was split during importation.
22236 //
22237 //    The code doesn't actually know if the corresponding inline
22238 //    succeeded or not; it relies on the fact that gtInlineCandidate
22239 //    initially points back at the call and is modified in place to
22240 //    the inlinee return expression if the inline is successful (see
22241 //    tail end of fgInsertInlineeBlocks for the update of iciCall).
22242 //
22243 //    If the parent of the GT_RET_EXPR is a virtual call,
22244 //    devirtualization is attempted. This should only succeed in the
22245 //    successful inline case, when the inlinee's return value
22246 //    expression provides a better type than the return type of the
22247 //    method. Note for failed inlines, the devirtualizer can only go
22248 //    by the return type, and any devirtualization that type enabled
22249 //    would have already happened during importation.
22250 //
22251 //    If the return type is a struct type and we're on a platform
22252 //    where structs can be returned in multiple registers, ensure the
22253 //    call has a suitable parent.
22254
22255 Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTree** pTree, fgWalkData* data)
22256 {
22257     GenTree*             tree      = *pTree;
22258     Compiler*            comp      = data->compiler;
22259     CORINFO_CLASS_HANDLE retClsHnd = NO_CLASS_HANDLE;
22260
22261     if (tree->gtOper == GT_RET_EXPR)
22262     {
22263         // We are going to copy the tree from the inlinee,
22264         // so record the handle now.
22265         //
22266         if (varTypeIsStruct(tree))
22267         {
22268             retClsHnd = tree->gtRetExpr.gtRetClsHnd;
22269         }
22270
22271         do
22272         {
22273             // Obtained the expanded inline candidate
22274             GenTree* inlineCandidate = tree->gtRetExpr.gtInlineCandidate;
22275
22276 #ifdef DEBUG
22277             if (comp->verbose)
22278             {
22279                 printf("\nReplacing the return expression placeholder ");
22280                 printTreeID(tree);
22281                 printf(" with ");
22282                 printTreeID(inlineCandidate);
22283                 printf("\n");
22284                 // Dump out the old return expression placeholder it will be overwritten by the ReplaceWith below
22285                 comp->gtDispTree(tree);
22286             }
22287 #endif // DEBUG
22288
22289             tree->ReplaceWith(inlineCandidate, comp);
22290
22291 #ifdef DEBUG
22292             if (comp->verbose)
22293             {
22294                 printf("\nInserting the inline return expression\n");
22295                 comp->gtDispTree(tree);
22296                 printf("\n");
22297             }
22298 #endif // DEBUG
22299         } while (tree->gtOper == GT_RET_EXPR);
22300
22301         // Now see if this return value expression feeds the 'this'
22302         // object at a virtual call site.
22303         //
22304         // Note for void returns where the inline failed, the
22305         // GT_RET_EXPR may be top-level.
22306         //
22307         // May miss cases where there are intermediaries between call
22308         // and this, eg commas.
22309         GenTree* parentTree = data->parent;
22310
22311         if ((parentTree != nullptr) && (parentTree->gtOper == GT_CALL))
22312         {
22313             GenTreeCall* call  = parentTree->AsCall();
22314             bool tryLateDevirt = call->IsVirtual() && (call->gtCallObjp == tree) && (call->gtCallType == CT_USER_FUNC);
22315
22316 #ifdef DEBUG
22317             tryLateDevirt = tryLateDevirt && (JitConfig.JitEnableLateDevirtualization() == 1);
22318 #endif // DEBUG
22319
22320             if (tryLateDevirt)
22321             {
22322 #ifdef DEBUG
22323                 if (comp->verbose)
22324                 {
22325                     printf("**** Late devirt opportunity\n");
22326                     comp->gtDispTree(call);
22327                 }
22328 #endif // DEBUG
22329
22330                 CORINFO_METHOD_HANDLE  method      = call->gtCallMethHnd;
22331                 unsigned               methodFlags = 0;
22332                 CORINFO_CONTEXT_HANDLE context     = nullptr;
22333                 comp->impDevirtualizeCall(call, &method, &methodFlags, &context, nullptr);
22334             }
22335         }
22336     }
22337
22338 #if FEATURE_MULTIREG_RET
22339
22340     // Did we record a struct return class handle above?
22341     //
22342     if (retClsHnd != NO_CLASS_HANDLE)
22343     {
22344         // Is this a type that is returned in multiple registers?
22345         // if so we need to force into into a form we accept.
22346         // i.e. LclVar = call()
22347         //
22348         if (comp->IsMultiRegReturnedType(retClsHnd))
22349         {
22350             GenTree* parent = data->parent;
22351             // See assert below, we only look one level above for an asg parent.
22352             if (parent->gtOper == GT_ASG)
22353             {
22354                 // Either lhs is a call V05 = call(); or lhs is addr, and asg becomes a copyBlk.
22355                 comp->fgAttachStructInlineeToAsg(parent, tree, retClsHnd);
22356             }
22357             else
22358             {
22359                 // Just assign the inlinee to a variable to keep it simple.
22360                 tree->ReplaceWith(comp->fgAssignStructInlineeToVar(tree, retClsHnd), comp);
22361             }
22362         }
22363     }
22364
22365 #if defined(DEBUG)
22366
22367     // Make sure we don't have a tree like so: V05 = (, , , retExpr);
22368     // Since we only look one level above for the parent for '=' and
22369     // do not check if there is a series of COMMAs. See above.
22370     // Importer and FlowGraph will not generate such a tree, so just
22371     // leaving an assert in here. This can be fixed by looking ahead
22372     // when we visit GT_ASG similar to fgAttachStructInlineeToAsg.
22373     //
22374     if ((tree->gtOper == GT_ASG) && (tree->gtOp.gtOp2->gtOper == GT_COMMA))
22375     {
22376         GenTree* comma;
22377         for (comma = tree->gtOp.gtOp2; comma->gtOper == GT_COMMA; comma = comma->gtOp.gtOp2)
22378         {
22379             // empty
22380         }
22381
22382         noway_assert(!varTypeIsStruct(comma) || comma->gtOper != GT_RET_EXPR ||
22383                      !comp->IsMultiRegReturnedType(comma->gtRetExpr.gtRetClsHnd));
22384     }
22385
22386 #endif // defined(DEBUG)
22387 #endif // FEATURE_MULTIREG_RET
22388
22389     return WALK_CONTINUE;
22390 }
22391
22392 #ifdef DEBUG
22393
22394 /*****************************************************************************
22395  * Callback to make sure there is no more GT_RET_EXPR and GTF_CALL_INLINE_CANDIDATE nodes.
22396  */
22397
22398 /* static */
22399 Compiler::fgWalkResult Compiler::fgDebugCheckInlineCandidates(GenTree** pTree, fgWalkData* data)
22400 {
22401     GenTree* tree = *pTree;
22402     if (tree->gtOper == GT_CALL)
22403     {
22404         assert((tree->gtFlags & GTF_CALL_INLINE_CANDIDATE) == 0);
22405     }
22406     else
22407     {
22408         assert(tree->gtOper != GT_RET_EXPR);
22409     }
22410
22411     return WALK_CONTINUE;
22412 }
22413
22414 #endif // DEBUG
22415
22416 void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineResult)
22417 {
22418     noway_assert(call->gtOper == GT_CALL);
22419     noway_assert((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0);
22420     noway_assert(opts.OptEnabled(CLFLG_INLINING));
22421
22422     // This is the InlineInfo struct representing a method to be inlined.
22423     InlineInfo inlineInfo;
22424     memset(&inlineInfo, 0, sizeof(inlineInfo));
22425     CORINFO_METHOD_HANDLE fncHandle = call->gtCallMethHnd;
22426
22427     inlineInfo.fncHandle              = fncHandle;
22428     inlineInfo.iciCall                = call;
22429     inlineInfo.iciStmt                = fgMorphStmt;
22430     inlineInfo.iciBlock               = compCurBB;
22431     inlineInfo.thisDereferencedFirst  = false;
22432     inlineInfo.retExpr                = nullptr;
22433     inlineInfo.retExprClassHnd        = nullptr;
22434     inlineInfo.retExprClassHndIsExact = false;
22435     inlineInfo.inlineResult           = inlineResult;
22436 #ifdef FEATURE_SIMD
22437     inlineInfo.hasSIMDTypeArgLocalOrReturn = false;
22438 #endif // FEATURE_SIMD
22439
22440     InlineCandidateInfo* inlineCandidateInfo = call->gtInlineCandidateInfo;
22441     noway_assert(inlineCandidateInfo);
22442     // Store the link to inlineCandidateInfo into inlineInfo
22443     inlineInfo.inlineCandidateInfo = inlineCandidateInfo;
22444
22445     unsigned inlineDepth = fgCheckInlineDepthAndRecursion(&inlineInfo);
22446
22447     if (inlineResult->IsFailure())
22448     {
22449 #ifdef DEBUG
22450         if (verbose)
22451         {
22452             printf("Recursive or deep inline recursion detected. Will not expand this INLINECANDIDATE \n");
22453         }
22454 #endif // DEBUG
22455         return;
22456     }
22457
22458     // Set the trap to catch all errors (including recoverable ones from the EE)
22459     struct Param
22460     {
22461         Compiler*             pThis;
22462         GenTree*              call;
22463         CORINFO_METHOD_HANDLE fncHandle;
22464         InlineCandidateInfo*  inlineCandidateInfo;
22465         InlineInfo*           inlineInfo;
22466     } param;
22467     memset(&param, 0, sizeof(param));
22468
22469     param.pThis               = this;
22470     param.call                = call;
22471     param.fncHandle           = fncHandle;
22472     param.inlineCandidateInfo = inlineCandidateInfo;
22473     param.inlineInfo          = &inlineInfo;
22474     bool success              = eeRunWithErrorTrap<Param>(
22475         [](Param* pParam) {
22476             // Init the local var info of the inlinee
22477             pParam->pThis->impInlineInitVars(pParam->inlineInfo);
22478
22479             if (pParam->inlineInfo->inlineResult->IsCandidate())
22480             {
22481                 /* Clear the temp table */
22482                 memset(pParam->inlineInfo->lclTmpNum, -1, sizeof(pParam->inlineInfo->lclTmpNum));
22483
22484                 //
22485                 // Prepare the call to jitNativeCode
22486                 //
22487
22488                 pParam->inlineInfo->InlinerCompiler = pParam->pThis;
22489                 if (pParam->pThis->impInlineInfo == nullptr)
22490                 {
22491                     pParam->inlineInfo->InlineRoot = pParam->pThis;
22492                 }
22493                 else
22494                 {
22495                     pParam->inlineInfo->InlineRoot = pParam->pThis->impInlineInfo->InlineRoot;
22496                 }
22497                 pParam->inlineInfo->argCnt                   = pParam->inlineCandidateInfo->methInfo.args.totalILArgs();
22498                 pParam->inlineInfo->tokenLookupContextHandle = pParam->inlineCandidateInfo->exactContextHnd;
22499
22500                 JITLOG_THIS(pParam->pThis,
22501                             (LL_INFO100000, "INLINER: inlineInfo.tokenLookupContextHandle for %s set to 0x%p:\n",
22502                              pParam->pThis->eeGetMethodFullName(pParam->fncHandle),
22503                              pParam->pThis->dspPtr(pParam->inlineInfo->tokenLookupContextHandle)));
22504
22505                 JitFlags compileFlagsForInlinee = *pParam->pThis->opts.jitFlags;
22506
22507                 // The following flags are lost when inlining.
22508                 // (This is checked in Compiler::compInitOptions().)
22509                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_BBOPT);
22510                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_BBINSTR);
22511                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_PROF_ENTERLEAVE);
22512                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_EnC);
22513                 compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_INFO);
22514
22515                 compileFlagsForInlinee.Set(JitFlags::JIT_FLAG_SKIP_VERIFICATION);
22516
22517 #ifdef DEBUG
22518                 if (pParam->pThis->verbose)
22519                 {
22520                     printf("\nInvoking compiler for the inlinee method %s :\n",
22521                            pParam->pThis->eeGetMethodFullName(pParam->fncHandle));
22522                 }
22523 #endif // DEBUG
22524
22525                 int result =
22526                     jitNativeCode(pParam->fncHandle, pParam->inlineCandidateInfo->methInfo.scope,
22527                                   pParam->pThis->info.compCompHnd, &pParam->inlineCandidateInfo->methInfo,
22528                                   (void**)pParam->inlineInfo, nullptr, &compileFlagsForInlinee, pParam->inlineInfo);
22529
22530                 if (result != CORJIT_OK)
22531                 {
22532                     // If we haven't yet determined why this inline fails, use
22533                     // a catch-all something bad happened observation.
22534                     InlineResult* innerInlineResult = pParam->inlineInfo->inlineResult;
22535
22536                     if (!innerInlineResult->IsFailure())
22537                     {
22538                         innerInlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_FAILURE);
22539                     }
22540                 }
22541             }
22542         },
22543         &param);
22544     if (!success)
22545     {
22546 #ifdef DEBUG
22547         if (verbose)
22548         {
22549             printf("\nInlining failed due to an exception during invoking the compiler for the inlinee method %s.\n",
22550                    eeGetMethodFullName(fncHandle));
22551         }
22552 #endif // DEBUG
22553
22554         // If we haven't yet determined why this inline fails, use
22555         // a catch-all something bad happened observation.
22556         if (!inlineResult->IsFailure())
22557         {
22558             inlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_ERROR);
22559         }
22560     }
22561
22562     if (inlineResult->IsFailure())
22563     {
22564         return;
22565     }
22566
22567 #ifdef DEBUG
22568     if (0 && verbose)
22569     {
22570         printf("\nDone invoking compiler for the inlinee method %s\n", eeGetMethodFullName(fncHandle));
22571     }
22572 #endif // DEBUG
22573
22574     // If there is non-NULL return, but we haven't set the pInlineInfo->retExpr,
22575     // That means we haven't imported any BB that contains CEE_RET opcode.
22576     // (This could happen for example for a BBJ_THROW block fall through a BBJ_RETURN block which
22577     // causes the BBJ_RETURN block not to be imported at all.)
22578     // Fail the inlining attempt
22579     if (inlineCandidateInfo->fncRetType != TYP_VOID && inlineInfo.retExpr == nullptr)
22580     {
22581 #ifdef DEBUG
22582         if (verbose)
22583         {
22584             printf("\nInlining failed because pInlineInfo->retExpr is not set in the inlinee method %s.\n",
22585                    eeGetMethodFullName(fncHandle));
22586         }
22587 #endif // DEBUG
22588         inlineResult->NoteFatal(InlineObservation::CALLEE_LACKS_RETURN);
22589         return;
22590     }
22591
22592     if (inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_SPECULATIVE)
22593     {
22594         // we defer the call to initClass() until inlining is completed in case it fails. If inlining succeeds,
22595         // we will call initClass().
22596         if (!(info.compCompHnd->initClass(nullptr /* field */, fncHandle /* method */,
22597                                           inlineCandidateInfo->exactContextHnd /* context */) &
22598               CORINFO_INITCLASS_INITIALIZED))
22599         {
22600             inlineResult->NoteFatal(InlineObservation::CALLEE_CLASS_INIT_FAILURE);
22601             return;
22602         }
22603     }
22604
22605     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
22606     // The inlining attempt cannot be failed starting from this point.
22607     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
22608
22609     // We've successfully obtain the list of inlinee's basic blocks.
22610     // Let's insert it to inliner's basic block list.
22611     fgInsertInlineeBlocks(&inlineInfo);
22612
22613 #ifdef DEBUG
22614
22615     if (verbose || fgPrintInlinedMethods)
22616     {
22617         printf("Successfully inlined %s (%d IL bytes) (depth %d) [%s]\n", eeGetMethodFullName(fncHandle),
22618                inlineCandidateInfo->methInfo.ILCodeSize, inlineDepth, inlineResult->ReasonString());
22619     }
22620
22621     if (verbose)
22622     {
22623         printf("--------------------------------------------------------------------------------------------\n");
22624     }
22625 #endif // DEBUG
22626
22627 #if defined(DEBUG)
22628     impInlinedCodeSize += inlineCandidateInfo->methInfo.ILCodeSize;
22629 #endif
22630
22631     // We inlined...
22632     inlineResult->NoteSuccess();
22633 }
22634
22635 //------------------------------------------------------------------------
22636 // fgInsertInlineeBlocks: incorporate statements for an inline into the
22637 // root method.
22638 //
22639 // Arguments:
22640 //    inlineInfo -- info for the inline
22641 //
22642 // Notes:
22643 //    The inlining attempt cannot be failed once this method is called.
22644 //
22645 //    Adds all inlinee statements, plus any glue statements needed
22646 //    either before or after the inlined call.
22647 //
22648 //    Updates flow graph and assigns weights to inlinee
22649 //    blocks. Currently does not attempt to read IBC data for the
22650 //    inlinee.
22651 //
22652 //    Updates relevant root method status flags (eg optMethodFlags) to
22653 //    include information from the inlinee.
22654 //
22655 //    Marks newly added statements with an appropriate inline context.
22656
22657 void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo)
22658 {
22659     GenTreeCall* iciCall  = pInlineInfo->iciCall;
22660     GenTreeStmt* iciStmt  = pInlineInfo->iciStmt;
22661     BasicBlock*  iciBlock = pInlineInfo->iciBlock;
22662     BasicBlock*  block;
22663
22664     // We can write better assert here. For example, we can check that
22665     // iciBlock contains iciStmt, which in turn contains iciCall.
22666     noway_assert(iciBlock->bbTreeList != nullptr);
22667     noway_assert(iciStmt->gtStmtExpr != nullptr);
22668     noway_assert(iciCall->gtOper == GT_CALL);
22669
22670 #ifdef DEBUG
22671
22672     GenTree* currentDumpStmt = nullptr;
22673
22674     if (verbose)
22675     {
22676         printf("\n\n----------- Statements (and blocks) added due to the inlining of call ");
22677         printTreeID(iciCall);
22678         printf(" -----------\n");
22679     }
22680
22681 #endif // DEBUG
22682
22683     // Create a new inline context and mark the inlined statements with it
22684     InlineContext* calleeContext = m_inlineStrategy->NewSuccess(pInlineInfo);
22685
22686     for (block = InlineeCompiler->fgFirstBB; block != nullptr; block = block->bbNext)
22687     {
22688         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
22689         {
22690             stmt->gtInlineContext = calleeContext;
22691         }
22692     }
22693
22694     // Prepend statements
22695     GenTree* stmtAfter = fgInlinePrependStatements(pInlineInfo);
22696
22697 #ifdef DEBUG
22698     if (verbose)
22699     {
22700         currentDumpStmt = stmtAfter;
22701         printf("\nInlinee method body:");
22702     }
22703 #endif // DEBUG
22704
22705     BasicBlock* topBlock    = iciBlock;
22706     BasicBlock* bottomBlock = nullptr;
22707
22708     if (InlineeCompiler->fgBBcount == 1)
22709     {
22710         // When fgBBCount is 1 we will always have a non-NULL fgFirstBB
22711         //
22712         PREFAST_ASSUME(InlineeCompiler->fgFirstBB != nullptr);
22713
22714         // DDB 91389: Don't throw away the (only) inlinee block
22715         // when its return type is not BBJ_RETURN.
22716         // In other words, we need its BBJ_ to perform the right thing.
22717         if (InlineeCompiler->fgFirstBB->bbJumpKind == BBJ_RETURN)
22718         {
22719             // Inlinee contains just one BB. So just insert its statement list to topBlock.
22720             if (InlineeCompiler->fgFirstBB->bbTreeList)
22721             {
22722                 stmtAfter = fgInsertStmtListAfter(iciBlock, stmtAfter, InlineeCompiler->fgFirstBB->bbTreeList);
22723
22724                 // Copy inlinee bbFlags to caller bbFlags.
22725                 const unsigned __int64 inlineeBlockFlags = InlineeCompiler->fgFirstBB->bbFlags;
22726                 noway_assert((inlineeBlockFlags & BBF_HAS_JMP) == 0);
22727                 noway_assert((inlineeBlockFlags & BBF_KEEP_BBJ_ALWAYS) == 0);
22728                 iciBlock->bbFlags |= inlineeBlockFlags;
22729             }
22730
22731 #ifdef DEBUG
22732             if (verbose)
22733             {
22734                 noway_assert(currentDumpStmt);
22735
22736                 if (currentDumpStmt != stmtAfter)
22737                 {
22738                     do
22739                     {
22740                         currentDumpStmt = currentDumpStmt->gtNext;
22741
22742                         printf("\n");
22743
22744                         noway_assert(currentDumpStmt->gtOper == GT_STMT);
22745
22746                         gtDispTree(currentDumpStmt);
22747                         printf("\n");
22748
22749                     } while (currentDumpStmt != stmtAfter);
22750                 }
22751             }
22752 #endif // DEBUG
22753
22754             // Append statements to null out gc ref locals, if necessary.
22755             fgInlineAppendStatements(pInlineInfo, iciBlock, stmtAfter);
22756
22757             goto _Done;
22758         }
22759     }
22760
22761     //
22762     // ======= Inserting inlinee's basic blocks ===============
22763     //
22764
22765     bottomBlock             = fgNewBBafter(topBlock->bbJumpKind, topBlock, true);
22766     bottomBlock->bbRefs     = 1;
22767     bottomBlock->bbJumpDest = topBlock->bbJumpDest;
22768     bottomBlock->inheritWeight(topBlock);
22769
22770     topBlock->bbJumpKind = BBJ_NONE;
22771
22772     // Update block flags
22773     {
22774         const unsigned __int64 originalFlags = topBlock->bbFlags;
22775         noway_assert((originalFlags & BBF_SPLIT_NONEXIST) == 0);
22776         topBlock->bbFlags &= ~(BBF_SPLIT_LOST);
22777         bottomBlock->bbFlags |= originalFlags & BBF_SPLIT_GAINED;
22778     }
22779
22780     //
22781     // Split statements between topBlock and bottomBlock
22782     //
22783     GenTree* topBlock_Begin;
22784     GenTree* topBlock_End;
22785     GenTree* bottomBlock_Begin;
22786     GenTree* bottomBlock_End;
22787
22788     topBlock_Begin    = nullptr;
22789     topBlock_End      = nullptr;
22790     bottomBlock_Begin = nullptr;
22791     bottomBlock_End   = nullptr;
22792
22793     //
22794     // First figure out bottomBlock_Begin
22795     //
22796
22797     bottomBlock_Begin = stmtAfter->gtNext;
22798
22799     if (topBlock->bbTreeList == nullptr)
22800     {
22801         // topBlock is empty before the split.
22802         // In this case, both topBlock and bottomBlock should be empty
22803         noway_assert(bottomBlock_Begin == nullptr);
22804         topBlock->bbTreeList    = nullptr;
22805         bottomBlock->bbTreeList = nullptr;
22806     }
22807     else if (topBlock->bbTreeList == bottomBlock_Begin)
22808     {
22809         noway_assert(bottomBlock_Begin);
22810
22811         // topBlock contains at least one statement before the split.
22812         // And the split is before the first statement.
22813         // In this case, topBlock should be empty, and everything else should be moved to the bottonBlock.
22814         bottomBlock->bbTreeList = topBlock->bbTreeList;
22815         topBlock->bbTreeList    = nullptr;
22816     }
22817     else if (bottomBlock_Begin == nullptr)
22818     {
22819         noway_assert(topBlock->bbTreeList);
22820
22821         // topBlock contains at least one statement before the split.
22822         // And the split is at the end of the topBlock.
22823         // In this case, everything should be kept in the topBlock, and the bottomBlock should be empty
22824
22825         bottomBlock->bbTreeList = nullptr;
22826     }
22827     else
22828     {
22829         noway_assert(topBlock->bbTreeList);
22830         noway_assert(bottomBlock_Begin);
22831
22832         // This is the normal case where both blocks should contain at least one statement.
22833         topBlock_Begin = topBlock->bbTreeList;
22834         noway_assert(topBlock_Begin);
22835         topBlock_End = bottomBlock_Begin->gtPrev;
22836         noway_assert(topBlock_End);
22837         bottomBlock_End = topBlock->lastStmt();
22838         noway_assert(bottomBlock_End);
22839
22840         // Break the linkage between 2 blocks.
22841         topBlock_End->gtNext = nullptr;
22842
22843         // Fix up all the pointers.
22844         topBlock->bbTreeList         = topBlock_Begin;
22845         topBlock->bbTreeList->gtPrev = topBlock_End;
22846
22847         bottomBlock->bbTreeList         = bottomBlock_Begin;
22848         bottomBlock->bbTreeList->gtPrev = bottomBlock_End;
22849     }
22850
22851     //
22852     // Set the try and handler index and fix the jump types of inlinee's blocks.
22853     //
22854
22855     bool inheritWeight;
22856     inheritWeight = true; // The firstBB does inherit the weight from the iciBlock
22857
22858     for (block = InlineeCompiler->fgFirstBB; block != nullptr; block = block->bbNext)
22859     {
22860         noway_assert(!block->hasTryIndex());
22861         noway_assert(!block->hasHndIndex());
22862         block->copyEHRegion(iciBlock);
22863         block->bbFlags |= iciBlock->bbFlags & BBF_BACKWARD_JUMP;
22864
22865         if (iciStmt->gtStmtILoffsx != BAD_IL_OFFSET)
22866         {
22867             block->bbCodeOffs    = jitGetILoffs(iciStmt->gtStmtILoffsx);
22868             block->bbCodeOffsEnd = block->bbCodeOffs + 1; // TODO: is code size of 1 some magic number for inlining?
22869         }
22870         else
22871         {
22872             block->bbCodeOffs    = 0; // TODO: why not BAD_IL_OFFSET?
22873             block->bbCodeOffsEnd = 0;
22874             block->bbFlags |= BBF_INTERNAL;
22875         }
22876
22877         if (block->bbJumpKind == BBJ_RETURN)
22878         {
22879             inheritWeight = true; // A return block does inherit the weight from the iciBlock
22880             noway_assert((block->bbFlags & BBF_HAS_JMP) == 0);
22881             if (block->bbNext)
22882             {
22883                 block->bbJumpKind = BBJ_ALWAYS;
22884                 block->bbJumpDest = bottomBlock;
22885 #ifdef DEBUG
22886                 if (verbose)
22887                 {
22888                     printf("\nConvert bbJumpKind of BB%02u to BBJ_ALWAYS to bottomBlock BB%02u\n", block->bbNum,
22889                            bottomBlock->bbNum);
22890                 }
22891 #endif // DEBUG
22892             }
22893             else
22894             {
22895 #ifdef DEBUG
22896                 if (verbose)
22897                 {
22898                     printf("\nConvert bbJumpKind of BB%02u to BBJ_NONE\n", block->bbNum);
22899                 }
22900 #endif // DEBUG
22901                 block->bbJumpKind = BBJ_NONE;
22902             }
22903         }
22904         if (inheritWeight)
22905         {
22906             block->inheritWeight(iciBlock);
22907             inheritWeight = false;
22908         }
22909         else
22910         {
22911             block->modifyBBWeight(iciBlock->bbWeight / 2);
22912         }
22913     }
22914
22915     // Insert inlinee's blocks into inliner's block list.
22916     topBlock->setNext(InlineeCompiler->fgFirstBB);
22917     InlineeCompiler->fgLastBB->setNext(bottomBlock);
22918
22919     //
22920     // Add inlinee's block count to inliner's.
22921     //
22922     fgBBcount += InlineeCompiler->fgBBcount;
22923
22924     // Append statements to null out gc ref locals, if necessary.
22925     fgInlineAppendStatements(pInlineInfo, bottomBlock, nullptr);
22926
22927 #ifdef DEBUG
22928     if (verbose)
22929     {
22930         fgDispBasicBlocks(InlineeCompiler->fgFirstBB, InlineeCompiler->fgLastBB, true);
22931     }
22932 #endif // DEBUG
22933
22934 _Done:
22935
22936     //
22937     // At this point, we have successully inserted inlinee's code.
22938     //
22939
22940     //
22941     // Copy out some flags
22942     //
22943     compLongUsed |= InlineeCompiler->compLongUsed;
22944     compFloatingPointUsed |= InlineeCompiler->compFloatingPointUsed;
22945     compLocallocUsed |= InlineeCompiler->compLocallocUsed;
22946     compLocallocOptimized |= InlineeCompiler->compLocallocOptimized;
22947     compQmarkUsed |= InlineeCompiler->compQmarkUsed;
22948     compUnsafeCastUsed |= InlineeCompiler->compUnsafeCastUsed;
22949     compNeedsGSSecurityCookie |= InlineeCompiler->compNeedsGSSecurityCookie;
22950     compGSReorderStackLayout |= InlineeCompiler->compGSReorderStackLayout;
22951
22952 #ifdef FEATURE_SIMD
22953     if (InlineeCompiler->usesSIMDTypes())
22954     {
22955         setUsesSIMDTypes(true);
22956     }
22957 #endif // FEATURE_SIMD
22958
22959     // Update unmanaged call count
22960     info.compCallUnmanaged += InlineeCompiler->info.compCallUnmanaged;
22961
22962 // Update optMethodFlags
22963
22964 #ifdef DEBUG
22965     unsigned optMethodFlagsBefore = optMethodFlags;
22966 #endif
22967
22968     optMethodFlags |= InlineeCompiler->optMethodFlags;
22969
22970 #ifdef DEBUG
22971     if (optMethodFlags != optMethodFlagsBefore)
22972     {
22973         JITDUMP("INLINER: Updating optMethodFlags --  root:%0x callee:%0x new:%0x\n", optMethodFlagsBefore,
22974                 InlineeCompiler->optMethodFlags, optMethodFlags);
22975     }
22976 #endif
22977
22978     // If there is non-NULL return, replace the GT_CALL with its return value expression,
22979     // so later it will be picked up by the GT_RET_EXPR node.
22980     if ((pInlineInfo->inlineCandidateInfo->fncRetType != TYP_VOID) || (iciCall->gtReturnType == TYP_STRUCT))
22981     {
22982         noway_assert(pInlineInfo->retExpr);
22983 #ifdef DEBUG
22984         if (verbose)
22985         {
22986             printf("\nReturn expression for call at ");
22987             printTreeID(iciCall);
22988             printf(" is\n");
22989             gtDispTree(pInlineInfo->retExpr);
22990         }
22991 #endif // DEBUG
22992         // Replace the call with the return expression
22993         iciCall->ReplaceWith(pInlineInfo->retExpr, this);
22994     }
22995
22996     //
22997     // Detach the GT_CALL node from the original statement by hanging a "nothing" node under it,
22998     // so that fgMorphStmts can remove the statement once we return from here.
22999     //
23000     iciStmt->gtStmtExpr = gtNewNothingNode();
23001 }
23002
23003 //------------------------------------------------------------------------
23004 // fgInlinePrependStatements: prepend statements needed to match up
23005 // caller and inlined callee
23006 //
23007 // Arguments:
23008 //    inlineInfo -- info for the inline
23009 //
23010 // Return Value:
23011 //    The last statement that was added, or the original call if no
23012 //    statements were added.
23013 //
23014 // Notes:
23015 //    Statements prepended may include the following:
23016 //    * This pointer null check
23017 //    * Class initialization
23018 //    * Zeroing of must-init locals in the callee
23019 //    * Passing of call arguments via temps
23020 //
23021 //    Newly added statements are placed just after the original call
23022 //    and are are given the same inline context as the call any calls
23023 //    added here will appear to have been part of the immediate caller.
23024
23025 GenTree* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
23026 {
23027     BasicBlock*  block        = inlineInfo->iciBlock;
23028     GenTreeStmt* callStmt     = inlineInfo->iciStmt;
23029     IL_OFFSETX   callILOffset = callStmt->gtStmtILoffsx;
23030     GenTreeStmt* postStmt     = callStmt->gtNextStmt;
23031     GenTree*     afterStmt    = callStmt; // afterStmt is the place where the new statements should be inserted after.
23032     GenTree*     newStmt      = nullptr;
23033     GenTreeCall* call         = inlineInfo->iciCall->AsCall();
23034
23035     noway_assert(call->gtOper == GT_CALL);
23036
23037 #ifdef DEBUG
23038     if (0 && verbose)
23039     {
23040         printf("\nfgInlinePrependStatements for iciCall= ");
23041         printTreeID(call);
23042         printf(":\n");
23043     }
23044 #endif
23045
23046     // Prepend statements for any initialization / side effects
23047
23048     InlArgInfo*    inlArgInfo = inlineInfo->inlArgInfo;
23049     InlLclVarInfo* lclVarInfo = inlineInfo->lclVarInfo;
23050
23051     GenTree* tree;
23052
23053     // Create the null check statement (but not appending it to the statement list yet) for the 'this' pointer if
23054     // necessary.
23055     // The NULL check should be done after "argument setup statements".
23056     // The only reason we move it here is for calling "impInlineFetchArg(0,..." to reserve a temp
23057     // for the "this" pointer.
23058     // Note: Here we no longer do the optimization that was done by thisDereferencedFirst in the old inliner.
23059     // However the assetionProp logic will remove any unecessary null checks that we may have added
23060     //
23061     GenTree* nullcheck = nullptr;
23062
23063     if (call->gtFlags & GTF_CALL_NULLCHECK && !inlineInfo->thisDereferencedFirst)
23064     {
23065         // Call impInlineFetchArg to "reserve" a temp for the "this" pointer.
23066         nullcheck = gtNewOperNode(GT_IND, TYP_INT, impInlineFetchArg(0, inlArgInfo, lclVarInfo));
23067         nullcheck->gtFlags |= GTF_EXCEPT;
23068
23069         // The NULL-check statement will be inserted to the statement list after those statements
23070         // that assign arguments to temps and before the actual body of the inlinee method.
23071     }
23072
23073     /* Treat arguments that had to be assigned to temps */
23074     if (inlineInfo->argCnt)
23075     {
23076
23077 #ifdef DEBUG
23078         if (verbose)
23079         {
23080             printf("\nArguments setup:\n");
23081         }
23082 #endif // DEBUG
23083
23084         for (unsigned argNum = 0; argNum < inlineInfo->argCnt; argNum++)
23085         {
23086             const InlArgInfo& argInfo        = inlArgInfo[argNum];
23087             const bool        argIsSingleDef = !argInfo.argHasLdargaOp && !argInfo.argHasStargOp;
23088             GenTree* const    argNode        = inlArgInfo[argNum].argNode;
23089
23090             if (argInfo.argHasTmp)
23091             {
23092                 noway_assert(argInfo.argIsUsed);
23093
23094                 /* argBashTmpNode is non-NULL iff the argument's value was
23095                    referenced exactly once by the original IL. This offers an
23096                    oppportunity to avoid an intermediate temp and just insert
23097                    the original argument tree.
23098
23099                    However, if the temp node has been cloned somewhere while
23100                    importing (e.g. when handling isinst or dup), or if the IL
23101                    took the address of the argument, then argBashTmpNode will
23102                    be set (because the value was only explicitly retrieved
23103                    once) but the optimization cannot be applied.
23104                  */
23105
23106                 GenTree* argSingleUseNode = argInfo.argBashTmpNode;
23107
23108                 if ((argSingleUseNode != nullptr) && !(argSingleUseNode->gtFlags & GTF_VAR_CLONED) && argIsSingleDef)
23109                 {
23110                     // Change the temp in-place to the actual argument.
23111                     // We currently do not support this for struct arguments, so it must not be a GT_OBJ.
23112                     assert(argNode->gtOper != GT_OBJ);
23113                     argSingleUseNode->ReplaceWith(argNode, this);
23114                     continue;
23115                 }
23116                 else
23117                 {
23118                     // We're going to assign the argument value to the
23119                     // temp we use for it in the inline body.
23120                     const unsigned  tmpNum  = argInfo.argTmpNum;
23121                     const var_types argType = lclVarInfo[argNum].lclTypeInfo;
23122
23123                     // Create the temp assignment for this argument
23124                     CORINFO_CLASS_HANDLE structHnd = DUMMY_INIT(0);
23125
23126                     if (varTypeIsStruct(argType))
23127                     {
23128                         structHnd = gtGetStructHandleIfPresent(argNode);
23129                         noway_assert(structHnd != NO_CLASS_HANDLE);
23130                     }
23131
23132                     // Unsafe value cls check is not needed for
23133                     // argTmpNum here since in-linee compiler instance
23134                     // would have iterated over these and marked them
23135                     // accordingly.
23136                     impAssignTempGen(tmpNum, argNode, structHnd, (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset,
23137                                      block);
23138
23139                     // We used to refine the temp type here based on
23140                     // the actual arg, but we now do this up front, when
23141                     // creating the temp, over in impInlineFetchArg.
23142                     CLANG_FORMAT_COMMENT_ANCHOR;
23143
23144 #ifdef DEBUG
23145                     if (verbose)
23146                     {
23147                         gtDispTree(afterStmt);
23148                     }
23149 #endif // DEBUG
23150                 }
23151             }
23152             else if (argInfo.argIsByRefToStructLocal)
23153             {
23154                 // Do nothing. Arg was directly substituted as we read
23155                 // the inlinee.
23156             }
23157             else
23158             {
23159                 /* The argument is either not used or a const or lcl var */
23160
23161                 noway_assert(!argInfo.argIsUsed || argInfo.argIsInvariant || argInfo.argIsLclVar);
23162
23163                 /* Make sure we didnt change argNode's along the way, or else
23164                    subsequent uses of the arg would have worked with the bashed value */
23165                 if (argInfo.argIsInvariant)
23166                 {
23167                     assert(argNode->OperIsConst() || argNode->gtOper == GT_ADDR);
23168                 }
23169                 noway_assert((argInfo.argIsLclVar == 0) ==
23170                              (argNode->gtOper != GT_LCL_VAR || (argNode->gtFlags & GTF_GLOB_REF)));
23171
23172                 /* If the argument has side effects, append it */
23173
23174                 if (argInfo.argHasSideEff)
23175                 {
23176                     noway_assert(argInfo.argIsUsed == false);
23177                     newStmt     = nullptr;
23178                     bool append = true;
23179
23180                     if (argNode->gtOper == GT_OBJ || argNode->gtOper == GT_MKREFANY)
23181                     {
23182                         // Don't put GT_OBJ node under a GT_COMMA.
23183                         // Codegen can't deal with it.
23184                         // Just hang the address here in case there are side-effect.
23185                         newStmt = gtNewStmt(gtUnusedValNode(argNode->gtOp.gtOp1), callILOffset);
23186                     }
23187                     else
23188                     {
23189                         // In some special cases, unused args with side effects can
23190                         // trigger further changes.
23191                         //
23192                         // (1) If the arg is a static field access and the field access
23193                         // was produced by a call to EqualityComparer<T>.get_Default, the
23194                         // helper call to ensure the field has a value can be suppressed.
23195                         // This helper call is marked as a "Special DCE" helper during
23196                         // importation, over in fgGetStaticsCCtorHelper.
23197                         //
23198                         // (2) NYI. If, after tunneling through GT_RET_VALs, we find that
23199                         // the actual arg expression has no side effects, we can skip
23200                         // appending all together. This will help jit TP a bit.
23201                         //
23202                         // Chase through any GT_RET_EXPRs to find the actual argument
23203                         // expression.
23204                         GenTree* actualArgNode = argNode->gtRetExprVal();
23205
23206                         // For case (1)
23207                         //
23208                         // Look for the following tree shapes
23209                         // prejit: (IND (ADD (CONST, CALL(special dce helper...))))
23210                         // jit   : (COMMA (CALL(special dce helper...), (FIELD ...)))
23211                         if (actualArgNode->gtOper == GT_COMMA)
23212                         {
23213                             // Look for (COMMA (CALL(special dce helper...), (FIELD ...)))
23214                             GenTree* op1 = actualArgNode->gtOp.gtOp1;
23215                             GenTree* op2 = actualArgNode->gtOp.gtOp2;
23216                             if (op1->IsCall() && ((op1->gtCall.gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) &&
23217                                 (op2->gtOper == GT_FIELD) && ((op2->gtFlags & GTF_EXCEPT) == 0))
23218                             {
23219                                 JITDUMP("\nPerforming special dce on unused arg [%06u]:"
23220                                         " actual arg [%06u] helper call [%06u]\n",
23221                                         argNode->gtTreeID, actualArgNode->gtTreeID, op1->gtTreeID);
23222                                 // Drop the whole tree
23223                                 append = false;
23224                             }
23225                         }
23226                         else if (actualArgNode->gtOper == GT_IND)
23227                         {
23228                             // Look for (IND (ADD (CONST, CALL(special dce helper...))))
23229                             GenTree* addr = actualArgNode->gtOp.gtOp1;
23230
23231                             if (addr->gtOper == GT_ADD)
23232                             {
23233                                 GenTree* op1 = addr->gtOp.gtOp1;
23234                                 GenTree* op2 = addr->gtOp.gtOp2;
23235                                 if (op1->IsCall() &&
23236                                     ((op1->gtCall.gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) &&
23237                                     op2->IsCnsIntOrI())
23238                                 {
23239                                     // Drop the whole tree
23240                                     JITDUMP("\nPerforming special dce on unused arg [%06u]:"
23241                                             " actual arg [%06u] helper call [%06u]\n",
23242                                             argNode->gtTreeID, actualArgNode->gtTreeID, op1->gtTreeID);
23243                                     append = false;
23244                                 }
23245                             }
23246                         }
23247                     }
23248
23249                     if (!append)
23250                     {
23251                         assert(newStmt == nullptr);
23252                         JITDUMP("Arg tree side effects were discardable, not appending anything for arg\n");
23253                     }
23254                     else
23255                     {
23256                         // If we don't have something custom to append,
23257                         // just append the arg node as an unused value.
23258                         if (newStmt == nullptr)
23259                         {
23260                             newStmt = gtNewStmt(gtUnusedValNode(argNode), callILOffset);
23261                         }
23262
23263                         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
23264 #ifdef DEBUG
23265                         if (verbose)
23266                         {
23267                             gtDispTree(afterStmt);
23268                         }
23269 #endif // DEBUG
23270                     }
23271                 }
23272                 else if (argNode->IsBoxedValue())
23273                 {
23274                     // Try to clean up any unnecessary boxing side effects
23275                     // since the box itself will be ignored.
23276                     gtTryRemoveBoxUpstreamEffects(argNode);
23277                 }
23278             }
23279         }
23280     }
23281
23282     // Add the CCTOR check if asked for.
23283     // Note: We no longer do the optimization that is done before by staticAccessedFirstUsingHelper in the old inliner.
23284     //       Therefore we might prepend redundant call to HELPER.CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
23285     //       before the inlined method body, even if a static field of this type was accessed in the inlinee
23286     //       using a helper before any other observable side-effect.
23287
23288     if (inlineInfo->inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_USE_HELPER)
23289     {
23290         CORINFO_CONTEXT_HANDLE exactContext = inlineInfo->inlineCandidateInfo->exactContextHnd;
23291         CORINFO_CLASS_HANDLE   exactClass;
23292
23293         if (((SIZE_T)exactContext & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
23294         {
23295             exactClass = CORINFO_CLASS_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK);
23296         }
23297         else
23298         {
23299             exactClass = info.compCompHnd->getMethodClass(
23300                 CORINFO_METHOD_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK));
23301         }
23302
23303         tree      = fgGetSharedCCtor(exactClass);
23304         newStmt   = gtNewStmt(tree, callILOffset);
23305         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
23306     }
23307
23308     // Insert the nullcheck statement now.
23309     if (nullcheck)
23310     {
23311         newStmt   = gtNewStmt(nullcheck, callILOffset);
23312         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
23313     }
23314
23315     //
23316     // Now zero-init inlinee locals
23317     //
23318
23319     CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
23320
23321     unsigned lclCnt = InlineeMethodInfo->locals.numArgs;
23322
23323     // Does callee contain any zero-init local?
23324     if ((lclCnt != 0) && (InlineeMethodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0)
23325     {
23326
23327 #ifdef DEBUG
23328         if (verbose)
23329         {
23330             printf("\nZero init inlinee locals:\n");
23331         }
23332 #endif // DEBUG
23333
23334         for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++)
23335         {
23336             unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
23337
23338             // Is the local used at all?
23339             if (tmpNum != BAD_VAR_NUM)
23340             {
23341                 var_types lclTyp = (var_types)lvaTable[tmpNum].lvType;
23342                 noway_assert(lclTyp == lclVarInfo[lclNum + inlineInfo->argCnt].lclTypeInfo);
23343
23344                 if (!varTypeIsStruct(lclTyp))
23345                 {
23346                     // Unsafe value cls check is not needed here since in-linee compiler instance would have
23347                     // iterated over locals and marked accordingly.
23348                     impAssignTempGen(tmpNum, gtNewZeroConNode(genActualType(lclTyp)), NO_CLASS_HANDLE,
23349                                      (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset, block);
23350                 }
23351                 else
23352                 {
23353                     CORINFO_CLASS_HANDLE structType =
23354                         lclVarInfo[lclNum + inlineInfo->argCnt].lclVerTypeInfo.GetClassHandle();
23355
23356                     if (fgStructTempNeedsExplicitZeroInit(lvaTable + tmpNum, block))
23357                     {
23358                         tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp),              // Dest
23359                                               gtNewIconNode(0),                           // Value
23360                                               info.compCompHnd->getClassSize(structType), // Size
23361                                               false,                                      // isVolatile
23362                                               false);                                     // not copyBlock
23363
23364                         newStmt   = gtNewStmt(tree, callILOffset);
23365                         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
23366                     }
23367                 }
23368
23369 #ifdef DEBUG
23370                 if (verbose)
23371                 {
23372                     gtDispTree(afterStmt);
23373                 }
23374 #endif // DEBUG
23375             }
23376         }
23377     }
23378
23379     // Update any newly added statements with the appropriate context.
23380     InlineContext* context = callStmt->gtInlineContext;
23381     assert(context != nullptr);
23382     for (GenTreeStmt* addedStmt = callStmt->gtNextStmt; addedStmt != postStmt; addedStmt = addedStmt->gtNextStmt)
23383     {
23384         assert(addedStmt->gtInlineContext == nullptr);
23385         addedStmt->gtInlineContext = context;
23386     }
23387
23388     return afterStmt;
23389 }
23390
23391 //------------------------------------------------------------------------
23392 // fgInlineAppendStatements: Append statements that are needed
23393 // after the inlined call.
23394 //
23395 // Arguments:
23396 //    inlineInfo - information about the inline
23397 //    block      - basic block for the new statements
23398 //    stmtAfter  - (optional) insertion point for mid-block cases
23399 //
23400 // Notes:
23401 //    If the call we're inlining is in tail position then
23402 //    we skip nulling the locals, since it can interfere
23403 //    with tail calls introduced by the local.
23404
23405 void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTree* stmtAfter)
23406 {
23407     // If this inlinee was passed a runtime lookup generic context and
23408     // ignores it, we can decrement the "generic context was used" ref
23409     // count, because we created a new lookup tree and incremented the
23410     // count when we imported the type parameter argument to pass to
23411     // the inlinee. See corresponding logic in impImportCall that
23412     // checks the sig for CORINFO_CALLCONV_PARAMTYPE.
23413     //
23414     // Does this method require a context (type) parameter?
23415     if ((inlineInfo->inlineCandidateInfo->methInfo.args.callConv & CORINFO_CALLCONV_PARAMTYPE) != 0)
23416     {
23417         // Did the computation of that parameter require the
23418         // caller to perform a runtime lookup?
23419         if (inlineInfo->inlineCandidateInfo->exactContextNeedsRuntimeLookup)
23420         {
23421             // Fetch the temp for the generic context as it would
23422             // appear in the inlinee's body.
23423             const unsigned typeCtxtArg = inlineInfo->typeContextArg;
23424             const unsigned tmpNum      = inlineInfo->lclTmpNum[typeCtxtArg];
23425
23426             // Was it used in the inline body?
23427             if (tmpNum == BAD_VAR_NUM)
23428             {
23429                 // No -- so the associated runtime lookup is not needed
23430                 // and also no longer provides evidence that the generic
23431                 // context should be kept alive.
23432                 JITDUMP("Inlinee ignores runtime lookup generics context\n");
23433                 assert(lvaGenericsContextUseCount > 0);
23434                 lvaGenericsContextUseCount--;
23435             }
23436         }
23437     }
23438
23439     // Null out any gc ref locals
23440     if (!inlineInfo->HasGcRefLocals())
23441     {
23442         // No ref locals, nothing to do.
23443         JITDUMP("fgInlineAppendStatements: no gc ref inline locals.\n");
23444         return;
23445     }
23446
23447     if (inlineInfo->iciCall->IsImplicitTailCall())
23448     {
23449         JITDUMP("fgInlineAppendStatements: implicit tail call; skipping nulling.\n");
23450         return;
23451     }
23452
23453     JITDUMP("fgInlineAppendStatements: nulling out gc ref inlinee locals.\n");
23454
23455     GenTree*             callStmt          = inlineInfo->iciStmt;
23456     IL_OFFSETX           callILOffset      = callStmt->gtStmt.gtStmtILoffsx;
23457     CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
23458     const unsigned       lclCnt            = InlineeMethodInfo->locals.numArgs;
23459     InlLclVarInfo*       lclVarInfo        = inlineInfo->lclVarInfo;
23460     unsigned             gcRefLclCnt       = inlineInfo->numberOfGcRefLocals;
23461     const unsigned       argCnt            = inlineInfo->argCnt;
23462
23463     noway_assert(callStmt->gtOper == GT_STMT);
23464
23465     for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++)
23466     {
23467         // Is the local a gc ref type? Need to look at the
23468         // inline info for this since we will not have local
23469         // temps for unused inlinee locals.
23470         const var_types lclTyp = lclVarInfo[argCnt + lclNum].lclTypeInfo;
23471
23472         if (!varTypeIsGC(lclTyp))
23473         {
23474             // Nope, nothing to null out.
23475             continue;
23476         }
23477
23478         // Ensure we're examining just the right number of locals.
23479         assert(gcRefLclCnt > 0);
23480         gcRefLclCnt--;
23481
23482         // Fetch the temp for this inline local
23483         const unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
23484
23485         // Is the local used at all?
23486         if (tmpNum == BAD_VAR_NUM)
23487         {
23488             // Nope, nothing to null out.
23489             continue;
23490         }
23491
23492         // Local was used, make sure the type is consistent.
23493         assert(lvaTable[tmpNum].lvType == lclTyp);
23494
23495         // Does the local we're about to null out appear in the return
23496         // expression?  If so we somehow messed up and didn't properly
23497         // spill the return value. See impInlineFetchLocal.
23498         GenTree* retExpr = inlineInfo->retExpr;
23499         if (retExpr != nullptr)
23500         {
23501             const bool interferesWithReturn = gtHasRef(inlineInfo->retExpr, tmpNum, false);
23502             noway_assert(!interferesWithReturn);
23503         }
23504
23505         // Assign null to the local.
23506         GenTree* nullExpr = gtNewTempAssign(tmpNum, gtNewZeroConNode(lclTyp));
23507         GenTree* nullStmt = gtNewStmt(nullExpr, callILOffset);
23508
23509         if (stmtAfter == nullptr)
23510         {
23511             stmtAfter = fgInsertStmtAtBeg(block, nullStmt);
23512         }
23513         else
23514         {
23515             stmtAfter = fgInsertStmtAfter(block, stmtAfter, nullStmt);
23516         }
23517
23518 #ifdef DEBUG
23519         if (verbose)
23520         {
23521             gtDispTree(nullStmt);
23522         }
23523 #endif // DEBUG
23524     }
23525
23526     // There should not be any GC ref locals left to null out.
23527     assert(gcRefLclCnt == 0);
23528 }
23529
23530 /*****************************************************************************/
23531 /*static*/
23532 Compiler::fgWalkResult Compiler::fgChkThrowCB(GenTree** pTree, fgWalkData* data)
23533 {
23534     GenTree* tree = *pTree;
23535
23536     // If this tree doesn't have the EXCEPT flag set, then there is no
23537     // way any of the child nodes could throw, so we can stop recursing.
23538     if (!(tree->gtFlags & GTF_EXCEPT))
23539     {
23540         return Compiler::WALK_SKIP_SUBTREES;
23541     }
23542
23543     switch (tree->gtOper)
23544     {
23545         case GT_MUL:
23546         case GT_ADD:
23547         case GT_SUB:
23548         case GT_CAST:
23549             if (tree->gtOverflow())
23550             {
23551                 return Compiler::WALK_ABORT;
23552             }
23553             break;
23554
23555         case GT_INDEX:
23556         case GT_INDEX_ADDR:
23557             // These two call CORINFO_HELP_RNGCHKFAIL for Debug code
23558             if (tree->gtFlags & GTF_INX_RNGCHK)
23559             {
23560                 return Compiler::WALK_ABORT;
23561             }
23562             break;
23563
23564         case GT_ARR_BOUNDS_CHECK:
23565             return Compiler::WALK_ABORT;
23566
23567         default:
23568             break;
23569     }
23570
23571     return Compiler::WALK_CONTINUE;
23572 }
23573
23574 /*****************************************************************************/
23575 /*static*/
23576 Compiler::fgWalkResult Compiler::fgChkLocAllocCB(GenTree** pTree, fgWalkData* data)
23577 {
23578     GenTree* tree = *pTree;
23579
23580     if (tree->gtOper == GT_LCLHEAP)
23581     {
23582         return Compiler::WALK_ABORT;
23583     }
23584
23585     return Compiler::WALK_CONTINUE;
23586 }
23587
23588 /*****************************************************************************/
23589 /*static*/
23590 Compiler::fgWalkResult Compiler::fgChkQmarkCB(GenTree** pTree, fgWalkData* data)
23591 {
23592     GenTree* tree = *pTree;
23593
23594     if (tree->gtOper == GT_QMARK)
23595     {
23596         return Compiler::WALK_ABORT;
23597     }
23598
23599     return Compiler::WALK_CONTINUE;
23600 }
23601
23602 void Compiler::fgLclFldAssign(unsigned lclNum)
23603 {
23604     assert(varTypeIsStruct(lvaTable[lclNum].lvType));
23605     if (lvaTable[lclNum].lvPromoted && lvaTable[lclNum].lvFieldCnt > 1)
23606     {
23607         lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField));
23608     }
23609 }
23610
23611 //------------------------------------------------------------------------
23612 // fgRemoveEmptyFinally: Remove try/finallys where the finally is empty
23613 //
23614 // Notes:
23615 //    Removes all try/finallys in the method with empty finallys.
23616 //    These typically arise from inlining empty Dispose methods.
23617 //
23618 //    Converts callfinally to a jump to the finally continuation.
23619 //    Removes the finally, and reparents all blocks in the try to the
23620 //    enclosing try or method region.
23621 //
23622 //    Currently limited to trivially empty finallys: those with one basic
23623 //    block containing only single RETFILT statement. It is possible but
23624 //    not likely that more complex-looking finallys will eventually become
23625 //    empty (from say subsequent optimization). An SPMI run with
23626 //    just the "detection" part of this phase run after optimization
23627 //    found only one example where a new empty finally was detected.
23628
23629 void Compiler::fgRemoveEmptyFinally()
23630 {
23631     JITDUMP("\n*************** In fgRemoveEmptyFinally()\n");
23632
23633 #if FEATURE_EH_FUNCLETS
23634     // We need to do this transformation before funclets are created.
23635     assert(!fgFuncletsCreated);
23636 #endif // FEATURE_EH_FUNCLETS
23637
23638     // Assume we don't need to update the bbPreds lists.
23639     assert(!fgComputePredsDone);
23640
23641     if (compHndBBtabCount == 0)
23642     {
23643         JITDUMP("No EH in this method, nothing to remove.\n");
23644         return;
23645     }
23646
23647     if (opts.MinOpts())
23648     {
23649         JITDUMP("Method compiled with minOpts, no removal.\n");
23650         return;
23651     }
23652
23653     if (opts.compDbgCode)
23654     {
23655         JITDUMP("Method compiled with debug codegen, no removal.\n");
23656         return;
23657     }
23658
23659 #ifdef DEBUG
23660     if (verbose)
23661     {
23662         printf("\n*************** Before fgRemoveEmptyFinally()\n");
23663         fgDispBasicBlocks();
23664         fgDispHandlerTab();
23665         printf("\n");
23666     }
23667 #endif // DEBUG
23668
23669     // Look for finallys or faults that are empty.
23670     unsigned finallyCount = 0;
23671     unsigned emptyCount   = 0;
23672     unsigned XTnum        = 0;
23673     while (XTnum < compHndBBtabCount)
23674     {
23675         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
23676
23677         // Check if this is a try/finally.  We could also look for empty
23678         // try/fault but presumably those are rare.
23679         if (!HBtab->HasFinallyHandler())
23680         {
23681             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
23682             XTnum++;
23683             continue;
23684         }
23685
23686         finallyCount++;
23687
23688         // Look at blocks involved.
23689         BasicBlock* const firstBlock = HBtab->ebdHndBeg;
23690         BasicBlock* const lastBlock  = HBtab->ebdHndLast;
23691
23692         // Limit for now to finallys that are single blocks.
23693         if (firstBlock != lastBlock)
23694         {
23695             JITDUMP("EH#%u finally has multiple basic blocks; skipping.\n", XTnum);
23696             XTnum++;
23697             continue;
23698         }
23699
23700         // Limit for now to finallys that contain only a GT_RETFILT.
23701         bool isEmpty = true;
23702
23703         for (GenTreeStmt* stmt = firstBlock->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
23704         {
23705             GenTree* stmtExpr = stmt->gtStmtExpr;
23706
23707             if (stmtExpr->gtOper != GT_RETFILT)
23708             {
23709                 isEmpty = false;
23710                 break;
23711             }
23712         }
23713
23714         if (!isEmpty)
23715         {
23716             JITDUMP("EH#%u finally is not empty; skipping.\n", XTnum);
23717             XTnum++;
23718             continue;
23719         }
23720
23721         JITDUMP("EH#%u has empty finally, removing the region.\n", XTnum);
23722
23723         // Find all the call finallys that invoke this finally,
23724         // and modify them to jump to the return point.
23725         BasicBlock* firstCallFinallyRangeBlock = nullptr;
23726         BasicBlock* endCallFinallyRangeBlock   = nullptr;
23727         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
23728
23729         BasicBlock* currentBlock = firstCallFinallyRangeBlock;
23730
23731         while (currentBlock != endCallFinallyRangeBlock)
23732         {
23733             BasicBlock* nextBlock = currentBlock->bbNext;
23734
23735             if ((currentBlock->bbJumpKind == BBJ_CALLFINALLY) && (currentBlock->bbJumpDest == firstBlock))
23736             {
23737                 // Retarget the call finally to jump to the return
23738                 // point.
23739                 //
23740                 // We don't expect to see retless finallys here, since
23741                 // the finally is empty.
23742                 noway_assert(currentBlock->isBBCallAlwaysPair());
23743
23744                 BasicBlock* const leaveBlock          = currentBlock->bbNext;
23745                 BasicBlock* const postTryFinallyBlock = leaveBlock->bbJumpDest;
23746
23747                 noway_assert(leaveBlock->bbJumpKind == BBJ_ALWAYS);
23748
23749                 currentBlock->bbJumpDest = postTryFinallyBlock;
23750                 currentBlock->bbJumpKind = BBJ_ALWAYS;
23751
23752                 // Ref count updates.
23753                 fgAddRefPred(postTryFinallyBlock, currentBlock);
23754                 // fgRemoveRefPred(firstBlock, currentBlock);
23755
23756                 // Delete the leave block, which should be marked as
23757                 // keep always.
23758                 assert((leaveBlock->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
23759                 nextBlock = leaveBlock->bbNext;
23760
23761                 leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
23762                 fgRemoveBlock(leaveBlock, true);
23763
23764                 // Cleanup the postTryFinallyBlock
23765                 fgCleanupContinuation(postTryFinallyBlock);
23766
23767                 // Make sure iteration isn't going off the deep end.
23768                 assert(leaveBlock != endCallFinallyRangeBlock);
23769             }
23770
23771             currentBlock = nextBlock;
23772         }
23773
23774         // Handler block should now be unreferenced, since the only
23775         // explicit references to it were in call finallys.
23776         firstBlock->bbRefs = 0;
23777
23778         // Remove the handler block.
23779         const bool unreachable = true;
23780         firstBlock->bbFlags &= ~BBF_DONT_REMOVE;
23781         fgRemoveBlock(firstBlock, unreachable);
23782
23783         // Find enclosing try region for the try, if any, and update
23784         // the try region. Note the handler region (if any) won't
23785         // change.
23786         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
23787         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
23788         assert(firstTryBlock->getTryIndex() == XTnum);
23789
23790         for (BasicBlock* block = firstTryBlock; block != nullptr; block = block->bbNext)
23791         {
23792             // Look for blocks directly contained in this try, and
23793             // update the try region appropriately.
23794             //
23795             // Try region for blocks transitively contained (say in a
23796             // child try) will get updated by the subsequent call to
23797             // fgRemoveEHTableEntry.
23798             if (block->getTryIndex() == XTnum)
23799             {
23800                 if (firstBlock->hasTryIndex())
23801                 {
23802                     block->setTryIndex(firstBlock->getTryIndex());
23803                 }
23804                 else
23805                 {
23806                     block->clearTryIndex();
23807                 }
23808             }
23809
23810             if (block == firstTryBlock)
23811             {
23812                 assert((block->bbFlags & BBF_TRY_BEG) != 0);
23813                 block->bbFlags &= ~BBF_TRY_BEG;
23814             }
23815
23816             if (block == lastTryBlock)
23817             {
23818                 break;
23819             }
23820         }
23821
23822         // Remove the try-finally EH region. This will compact the EH table
23823         // so XTnum now points at the next entry.
23824         fgRemoveEHTableEntry(XTnum);
23825
23826         emptyCount++;
23827     }
23828
23829     if (emptyCount > 0)
23830     {
23831         JITDUMP("fgRemoveEmptyFinally() removed %u try-finally clauses from %u finallys\n", emptyCount, finallyCount);
23832         fgOptimizedFinally = true;
23833
23834 #ifdef DEBUG
23835         if (verbose)
23836         {
23837             printf("\n*************** After fgRemoveEmptyFinally()\n");
23838             fgDispBasicBlocks();
23839             fgDispHandlerTab();
23840             printf("\n");
23841         }
23842
23843         fgVerifyHandlerTab();
23844         fgDebugCheckBBlist(false, false);
23845
23846 #endif // DEBUG
23847     }
23848 }
23849
23850 //------------------------------------------------------------------------
23851 // fgRemoveEmptyTry: Optimize try/finallys where the try is empty
23852 //
23853 // Notes:
23854 //    In runtimes where thread abort is not possible, `try {} finally {S}`
23855 //    can be optimized to simply `S`. This method looks for such
23856 //    cases and removes the try-finally from the EH table, making
23857 //    suitable flow, block flag, statement, and region updates.
23858 //
23859 //    This optimization is not legal in runtimes that support thread
23860 //    abort because those runtimes ensure that a finally is completely
23861 //    executed before continuing to process the thread abort.  With
23862 //    this optimization, the code block `S` can lose special
23863 //    within-finally status and so complete execution is no longer
23864 //    guaranteed.
23865
23866 void Compiler::fgRemoveEmptyTry()
23867 {
23868     JITDUMP("\n*************** In fgRemoveEmptyTry()\n");
23869
23870 #if FEATURE_EH_FUNCLETS
23871     // We need to do this transformation before funclets are created.
23872     assert(!fgFuncletsCreated);
23873 #endif // FEATURE_EH_FUNCLETS
23874
23875     // Assume we don't need to update the bbPreds lists.
23876     assert(!fgComputePredsDone);
23877
23878 #ifdef FEATURE_CORECLR
23879     bool enableRemoveEmptyTry = true;
23880 #else
23881     // Code in a finally gets special treatment in the presence of
23882     // thread abort.
23883     bool enableRemoveEmptyTry = false;
23884 #endif // FEATURE_CORECLR
23885
23886 #ifdef DEBUG
23887     // Allow override to enable/disable.
23888     enableRemoveEmptyTry = (JitConfig.JitEnableRemoveEmptyTry() == 1);
23889 #endif // DEBUG
23890
23891     if (!enableRemoveEmptyTry)
23892     {
23893         JITDUMP("Empty try removal disabled.\n");
23894         return;
23895     }
23896
23897     if (compHndBBtabCount == 0)
23898     {
23899         JITDUMP("No EH in this method, nothing to remove.\n");
23900         return;
23901     }
23902
23903     if (opts.MinOpts())
23904     {
23905         JITDUMP("Method compiled with minOpts, no removal.\n");
23906         return;
23907     }
23908
23909     if (opts.compDbgCode)
23910     {
23911         JITDUMP("Method compiled with debug codegen, no removal.\n");
23912         return;
23913     }
23914
23915 #ifdef DEBUG
23916     if (verbose)
23917     {
23918         printf("\n*************** Before fgRemoveEmptyTry()\n");
23919         fgDispBasicBlocks();
23920         fgDispHandlerTab();
23921         printf("\n");
23922     }
23923 #endif // DEBUG
23924
23925     // Look for try-finallys where the try is empty.
23926     unsigned emptyCount = 0;
23927     unsigned XTnum      = 0;
23928     while (XTnum < compHndBBtabCount)
23929     {
23930         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
23931
23932         // Check if this is a try/finally.  We could also look for empty
23933         // try/fault but presumably those are rare.
23934         if (!HBtab->HasFinallyHandler())
23935         {
23936             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
23937             XTnum++;
23938             continue;
23939         }
23940
23941         // Examine the try region
23942         BasicBlock* const firstTryBlock     = HBtab->ebdTryBeg;
23943         BasicBlock* const lastTryBlock      = HBtab->ebdTryLast;
23944         BasicBlock* const firstHandlerBlock = HBtab->ebdHndBeg;
23945         BasicBlock* const lastHandlerBlock  = HBtab->ebdHndLast;
23946         BasicBlock* const endHandlerBlock   = lastHandlerBlock->bbNext;
23947
23948         assert(firstTryBlock->getTryIndex() == XTnum);
23949
23950         // Limit for now to trys that contain only a callfinally pair
23951         // or branch to same.
23952         if (!firstTryBlock->isEmpty())
23953         {
23954             JITDUMP("EH#%u first try block BB%02u not empty; skipping.\n", XTnum, firstTryBlock->bbNum);
23955             XTnum++;
23956             continue;
23957         }
23958
23959 #if FEATURE_EH_CALLFINALLY_THUNKS
23960
23961         // Look for blocks that are always jumps to a call finally
23962         // pair that targets the finally
23963         if (firstTryBlock->bbJumpKind != BBJ_ALWAYS)
23964         {
23965             JITDUMP("EH#%u first try block BB%02u not jump to a callfinally; skipping.\n", XTnum, firstTryBlock->bbNum);
23966             XTnum++;
23967             continue;
23968         }
23969
23970         BasicBlock* const callFinally = firstTryBlock->bbJumpDest;
23971
23972         // Look for call always pair. Note this will also disqualify
23973         // empty try removal in cases where the finally doesn't
23974         // return.
23975         if (!callFinally->isBBCallAlwaysPair() || (callFinally->bbJumpDest != firstHandlerBlock))
23976         {
23977             JITDUMP("EH#%u first try block BB%02u always jumps but not to a callfinally; skipping.\n", XTnum,
23978                     firstTryBlock->bbNum);
23979             XTnum++;
23980             continue;
23981         }
23982
23983         // Try itself must be a single block.
23984         if (firstTryBlock != lastTryBlock)
23985         {
23986             JITDUMP("EH#%u first try block BB%02u not only block in try; skipping.\n", XTnum,
23987                     firstTryBlock->bbNext->bbNum);
23988             XTnum++;
23989             continue;
23990         }
23991
23992 #else
23993         // Look for call always pair within the try itself. Note this
23994         // will also disqualify empty try removal in cases where the
23995         // finally doesn't return.
23996         if (!firstTryBlock->isBBCallAlwaysPair() || (firstTryBlock->bbJumpDest != firstHandlerBlock))
23997         {
23998             JITDUMP("EH#%u first try block BB%02u not a callfinally; skipping.\n", XTnum, firstTryBlock->bbNum);
23999             XTnum++;
24000             continue;
24001         }
24002
24003         BasicBlock* const callFinally = firstTryBlock;
24004
24005         // Try must be a callalways pair of blocks.
24006         if (firstTryBlock->bbNext != lastTryBlock)
24007         {
24008             JITDUMP("EH#%u block BB%02u not last block in try; skipping.\n", XTnum, firstTryBlock->bbNext->bbNum);
24009             XTnum++;
24010             continue;
24011         }
24012
24013 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24014
24015         JITDUMP("EH#%u has empty try, removing the try region and promoting the finally.\n", XTnum);
24016
24017         // There should be just one callfinally that invokes this
24018         // finally, the one we found above. Verify this.
24019         BasicBlock* firstCallFinallyRangeBlock = nullptr;
24020         BasicBlock* endCallFinallyRangeBlock   = nullptr;
24021         bool        verifiedSingleCallfinally  = true;
24022         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
24023
24024         for (BasicBlock* block = firstCallFinallyRangeBlock; block != endCallFinallyRangeBlock; block = block->bbNext)
24025         {
24026             if ((block->bbJumpKind == BBJ_CALLFINALLY) && (block->bbJumpDest == firstHandlerBlock))
24027             {
24028                 assert(block->isBBCallAlwaysPair());
24029
24030                 if (block != callFinally)
24031                 {
24032                     JITDUMP("EH#%u found unexpected callfinally BB%02u; skipping.\n");
24033                     verifiedSingleCallfinally = false;
24034                     break;
24035                 }
24036
24037                 block = block->bbNext;
24038             }
24039         }
24040
24041         if (!verifiedSingleCallfinally)
24042         {
24043             JITDUMP("EH#%u -- unexpectedly -- has multiple callfinallys; skipping.\n");
24044             XTnum++;
24045             assert(verifiedSingleCallfinally);
24046             continue;
24047         }
24048
24049         // Time to optimize.
24050         //
24051         // (1) Convert the callfinally to a normal jump to the handler
24052         callFinally->bbJumpKind = BBJ_ALWAYS;
24053
24054         // Identify the leave block and the continuation
24055         BasicBlock* const leave        = callFinally->bbNext;
24056         BasicBlock* const continuation = leave->bbJumpDest;
24057
24058         // (2) Cleanup the leave so it can be deleted by subsequent opts
24059         assert((leave->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
24060         leave->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
24061
24062         // (3) Cleanup the continuation
24063         fgCleanupContinuation(continuation);
24064
24065         // (4) Find enclosing try region for the try, if any, and
24066         // update the try region for the blocks in the try. Note the
24067         // handler region (if any) won't change.
24068         //
24069         // Kind of overkill to loop here, but hey.
24070         for (BasicBlock* block = firstTryBlock; block != nullptr; block = block->bbNext)
24071         {
24072             // Look for blocks directly contained in this try, and
24073             // update the try region appropriately.
24074             //
24075             // The try region for blocks transitively contained (say in a
24076             // child try) will get updated by the subsequent call to
24077             // fgRemoveEHTableEntry.
24078             if (block->getTryIndex() == XTnum)
24079             {
24080                 if (firstHandlerBlock->hasTryIndex())
24081                 {
24082                     block->setTryIndex(firstHandlerBlock->getTryIndex());
24083                 }
24084                 else
24085                 {
24086                     block->clearTryIndex();
24087                 }
24088             }
24089
24090             if (block == firstTryBlock)
24091             {
24092                 assert((block->bbFlags & BBF_TRY_BEG) != 0);
24093                 block->bbFlags &= ~BBF_TRY_BEG;
24094             }
24095
24096             if (block == lastTryBlock)
24097             {
24098                 break;
24099             }
24100         }
24101
24102         // (5) Update the directly contained handler blocks' handler index.
24103         // Handler index of any nested blocks will update when we
24104         // remove the EH table entry.  Change handler exits to jump to
24105         // the continuation.  Clear catch type on handler entry.
24106         // Decrement nesting level of enclosed GT_END_LFINs.
24107         for (BasicBlock* block = firstHandlerBlock; block != endHandlerBlock; block = block->bbNext)
24108         {
24109             if (block == firstHandlerBlock)
24110             {
24111                 block->bbCatchTyp = BBCT_NONE;
24112             }
24113
24114             if (block->getHndIndex() == XTnum)
24115             {
24116                 if (firstTryBlock->hasHndIndex())
24117                 {
24118                     block->setHndIndex(firstTryBlock->getHndIndex());
24119                 }
24120                 else
24121                 {
24122                     block->clearHndIndex();
24123                 }
24124
24125                 if (block->bbJumpKind == BBJ_EHFINALLYRET)
24126                 {
24127                     GenTreeStmt* finallyRet     = block->lastStmt();
24128                     GenTree*     finallyRetExpr = finallyRet->gtStmtExpr;
24129                     assert(finallyRetExpr->gtOper == GT_RETFILT);
24130                     fgRemoveStmt(block, finallyRet);
24131                     block->bbJumpKind = BBJ_ALWAYS;
24132                     block->bbJumpDest = continuation;
24133                     fgAddRefPred(continuation, block);
24134                 }
24135             }
24136
24137 #if !FEATURE_EH_FUNCLETS
24138             // If we're in a non-funclet model, decrement the nesting
24139             // level of any GT_END_LFIN we find in the handler region,
24140             // since we're removing the enclosing handler.
24141             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
24142             {
24143                 GenTree* expr = stmt->gtStmtExpr;
24144                 if (expr->gtOper == GT_END_LFIN)
24145                 {
24146                     const unsigned nestLevel = expr->gtVal.gtVal1;
24147                     assert(nestLevel > 0);
24148                     expr->gtVal.gtVal1 = nestLevel - 1;
24149                 }
24150             }
24151 #endif // !FEATURE_EH_FUNCLETS
24152         }
24153
24154         // (6) Remove the try-finally EH region. This will compact the
24155         // EH table so XTnum now points at the next entry and will update
24156         // the EH region indices of any nested EH in the (former) handler.
24157         fgRemoveEHTableEntry(XTnum);
24158
24159         // Another one bites the dust...
24160         emptyCount++;
24161     }
24162
24163     if (emptyCount > 0)
24164     {
24165         JITDUMP("fgRemoveEmptyTry() optimized %u empty-try try-finally clauses\n", emptyCount);
24166         fgOptimizedFinally = true;
24167
24168 #ifdef DEBUG
24169         if (verbose)
24170         {
24171             printf("\n*************** After fgRemoveEmptyTry()\n");
24172             fgDispBasicBlocks();
24173             fgDispHandlerTab();
24174             printf("\n");
24175         }
24176
24177         fgVerifyHandlerTab();
24178         fgDebugCheckBBlist(false, false);
24179
24180 #endif // DEBUG
24181     }
24182 }
24183
24184 //------------------------------------------------------------------------
24185 // fgCloneFinally: Optimize normal exit path from a try/finally
24186 //
24187 // Notes:
24188 //    Handles finallys that are not enclosed by or enclosing other
24189 //    handler regions.
24190 //
24191 //    Converts the "normal exit" callfinally to a jump to a cloned copy
24192 //    of the finally, which in turn jumps to the finally continuation.
24193 //
24194 //    If all callfinallys for a given finally are converted to jump to
24195 //    the clone, the try-finally is modified into a try-fault,
24196 //    distingushable from organic try-faults by handler type
24197 //    EH_HANDLER_FAULT_WAS_FINALLY vs the organic EH_HANDLER_FAULT.
24198 //
24199 //    Does not yet handle thread abort. The open issues here are how
24200 //    to maintain the proper description of the cloned finally blocks
24201 //    as a handler (for thread abort purposes), how to prevent code
24202 //    motion in or out of these blocks, and how to report this cloned
24203 //    handler to the runtime. Some building blocks for thread abort
24204 //    exist (see below) but more work needed.
24205 //
24206 //    The first and last blocks of the cloned finally are marked with
24207 //    BBF_CLONED_FINALLY_BEGIN and BBF_CLONED_FINALLY_END. However
24208 //    these markers currently can get lost during subsequent
24209 //    optimizations.
24210
24211 void Compiler::fgCloneFinally()
24212 {
24213     JITDUMP("\n*************** In fgCloneFinally()\n");
24214
24215 #if FEATURE_EH_FUNCLETS
24216     // We need to do this transformation before funclets are created.
24217     assert(!fgFuncletsCreated);
24218 #endif // FEATURE_EH_FUNCLETS
24219
24220     // Assume we don't need to update the bbPreds lists.
24221     assert(!fgComputePredsDone);
24222
24223 #ifdef FEATURE_CORECLR
24224     bool enableCloning = true;
24225 #else
24226     // Finally cloning currently doesn't provide sufficient protection
24227     // for the cloned code in the presence of thread abort.
24228     bool enableCloning = false;
24229 #endif // FEATURE_CORECLR
24230
24231 #ifdef DEBUG
24232     // Allow override to enable/disable.
24233     enableCloning = (JitConfig.JitEnableFinallyCloning() == 1);
24234 #endif // DEBUG
24235
24236     if (!enableCloning)
24237     {
24238         JITDUMP("Finally cloning disabled.\n");
24239         return;
24240     }
24241
24242     if (compHndBBtabCount == 0)
24243     {
24244         JITDUMP("No EH in this method, no cloning.\n");
24245         return;
24246     }
24247
24248     if (opts.MinOpts())
24249     {
24250         JITDUMP("Method compiled with minOpts, no cloning.\n");
24251         return;
24252     }
24253
24254     if (opts.compDbgCode)
24255     {
24256         JITDUMP("Method compiled with debug codegen, no cloning.\n");
24257         return;
24258     }
24259
24260 #ifdef DEBUG
24261     if (verbose)
24262     {
24263         printf("\n*************** Before fgCloneFinally()\n");
24264         fgDispBasicBlocks();
24265         fgDispHandlerTab();
24266         printf("\n");
24267     }
24268
24269     // Verify try-finally exits look good before we start.
24270     fgDebugCheckTryFinallyExits();
24271
24272 #endif // DEBUG
24273
24274     // Look for finallys that are not contained within other handlers,
24275     // and which do not themselves contain EH.
24276     //
24277     // Note these cases potentially could be handled, but are less
24278     // obviously profitable and require modification of the handler
24279     // table.
24280     unsigned  XTnum      = 0;
24281     EHblkDsc* HBtab      = compHndBBtab;
24282     unsigned  cloneCount = 0;
24283     for (; XTnum < compHndBBtabCount; XTnum++, HBtab++)
24284     {
24285         // Check if this is a try/finally
24286         if (!HBtab->HasFinallyHandler())
24287         {
24288             JITDUMP("EH#%u is not a try-finally; skipping.\n", XTnum);
24289             continue;
24290         }
24291
24292         // Check if enclosed by another handler.
24293         const unsigned enclosingHandlerRegion = ehGetEnclosingHndIndex(XTnum);
24294
24295         if (enclosingHandlerRegion != EHblkDsc::NO_ENCLOSING_INDEX)
24296         {
24297             JITDUMP("EH#%u is enclosed by handler EH#%u; skipping.\n", XTnum, enclosingHandlerRegion);
24298             continue;
24299         }
24300
24301         bool     containsEH                   = false;
24302         unsigned exampleEnclosedHandlerRegion = 0;
24303
24304         // Only need to look at lower numbered regions because the
24305         // handler table is ordered by nesting.
24306         for (unsigned i = 0; i < XTnum; i++)
24307         {
24308             if (ehGetEnclosingHndIndex(i) == XTnum)
24309             {
24310                 exampleEnclosedHandlerRegion = i;
24311                 containsEH                   = true;
24312                 break;
24313             }
24314         }
24315
24316         if (containsEH)
24317         {
24318             JITDUMP("Finally for EH#%u encloses handler EH#%u; skipping.\n", XTnum, exampleEnclosedHandlerRegion);
24319             continue;
24320         }
24321
24322         // Look at blocks involved.
24323         BasicBlock* const firstBlock = HBtab->ebdHndBeg;
24324         BasicBlock* const lastBlock  = HBtab->ebdHndLast;
24325         assert(firstBlock != nullptr);
24326         assert(lastBlock != nullptr);
24327         BasicBlock* nextBlock       = lastBlock->bbNext;
24328         unsigned    regionBBCount   = 0;
24329         unsigned    regionStmtCount = 0;
24330         bool        hasFinallyRet   = false;
24331         bool        isAllRare       = true;
24332         bool        hasSwitch       = false;
24333
24334         for (const BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
24335         {
24336             if (block->bbJumpKind == BBJ_SWITCH)
24337             {
24338                 hasSwitch = true;
24339                 break;
24340             }
24341
24342             regionBBCount++;
24343
24344             // Should we compute statement cost here, or is it
24345             // premature...? For now just count statements I guess.
24346             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
24347             {
24348                 regionStmtCount++;
24349             }
24350
24351             hasFinallyRet = hasFinallyRet || (block->bbJumpKind == BBJ_EHFINALLYRET);
24352             isAllRare     = isAllRare && block->isRunRarely();
24353         }
24354
24355         // Skip cloning if the finally has a switch.
24356         if (hasSwitch)
24357         {
24358             JITDUMP("Finally in EH#%u has a switch; skipping.\n", XTnum);
24359             continue;
24360         }
24361
24362         // Skip cloning if the finally must throw.
24363         if (!hasFinallyRet)
24364         {
24365             JITDUMP("Finally in EH#%u does not return; skipping.\n", XTnum);
24366             continue;
24367         }
24368
24369         // Skip cloning if the finally is rarely run code.
24370         if (isAllRare)
24371         {
24372             JITDUMP("Finally in EH#%u is run rarely; skipping.\n", XTnum);
24373             continue;
24374         }
24375
24376         // Empirical studies from CoreCLR and CoreFX show that less
24377         // that 1% of finally regions have more than 15
24378         // statements. So, to avoid potentially excessive code growth,
24379         // only clone finallys that have 15 or fewer statements.
24380         const unsigned stmtCountLimit = 15;
24381         if (regionStmtCount > stmtCountLimit)
24382         {
24383             JITDUMP("Finally in EH#%u has %u statements, limit is %u; skipping.\n", XTnum, regionStmtCount,
24384                     stmtCountLimit);
24385             continue;
24386         }
24387
24388         JITDUMP("EH#%u is a candidate for finally cloning:"
24389                 " %u blocks, %u statements\n",
24390                 XTnum, regionBBCount, regionStmtCount);
24391
24392         // Walk the try region backwards looking for the last block
24393         // that transfers control to a callfinally.
24394         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
24395         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
24396         assert(firstTryBlock->getTryIndex() == XTnum);
24397         assert(bbInTryRegions(XTnum, lastTryBlock));
24398         BasicBlock* const beforeTryBlock = firstTryBlock->bbPrev;
24399
24400         BasicBlock* normalCallFinallyBlock   = nullptr;
24401         BasicBlock* normalCallFinallyReturn  = nullptr;
24402         BasicBlock* cloneInsertAfter         = HBtab->ebdTryLast;
24403         bool        tryToRelocateCallFinally = false;
24404
24405         for (BasicBlock* block = lastTryBlock; block != beforeTryBlock; block = block->bbPrev)
24406         {
24407 #if FEATURE_EH_CALLFINALLY_THUNKS
24408             // Look for blocks that are always jumps to a call finally
24409             // pair that targets our finally.
24410             if (block->bbJumpKind != BBJ_ALWAYS)
24411             {
24412                 continue;
24413             }
24414
24415             BasicBlock* const jumpDest = block->bbJumpDest;
24416
24417             if (!jumpDest->isBBCallAlwaysPair() || (jumpDest->bbJumpDest != firstBlock))
24418             {
24419                 continue;
24420             }
24421 #else
24422             // Look for call finally pair directly within the try
24423             if (!block->isBBCallAlwaysPair() || (block->bbJumpDest != firstBlock))
24424             {
24425                 continue;
24426             }
24427
24428             BasicBlock* const jumpDest = block;
24429 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24430
24431             // Found our block.
24432             BasicBlock* const finallyReturnBlock  = jumpDest->bbNext;
24433             BasicBlock* const postTryFinallyBlock = finallyReturnBlock->bbJumpDest;
24434
24435             normalCallFinallyBlock  = jumpDest;
24436             normalCallFinallyReturn = postTryFinallyBlock;
24437
24438 #if FEATURE_EH_CALLFINALLY_THUNKS
24439             // When there are callfinally thunks, we don't expect to see the
24440             // callfinally within a handler region either.
24441             assert(!jumpDest->hasHndIndex());
24442
24443             // Update the clone insertion point to just after the
24444             // call always pair.
24445             cloneInsertAfter = finallyReturnBlock;
24446
24447             // We will consider moving the callfinally so we can fall
24448             // through from the try into the clone.
24449             tryToRelocateCallFinally = true;
24450
24451             JITDUMP("Chose path to clone: try block BB%02u jumps to callfinally at BB%02u;"
24452                     " the call returns to BB%02u which jumps to BB%02u\n",
24453                     block->bbNum, jumpDest->bbNum, finallyReturnBlock->bbNum, postTryFinallyBlock->bbNum);
24454 #else
24455             JITDUMP("Chose path to clone: try block BB%02u is a callfinally;"
24456                     " the call returns to BB%02u which jumps to BB%02u\n",
24457                     block->bbNum, finallyReturnBlock->bbNum, postTryFinallyBlock->bbNum);
24458 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24459
24460             break;
24461         }
24462
24463         // If there is no call to the finally, don't clone.
24464         if (normalCallFinallyBlock == nullptr)
24465         {
24466             JITDUMP("EH#%u: no calls from the try to the finally, skipping.\n", XTnum);
24467             continue;
24468         }
24469
24470         JITDUMP("Will update callfinally block BB%02u to jump to the clone;"
24471                 " clone will jump to BB%02u\n",
24472                 normalCallFinallyBlock->bbNum, normalCallFinallyReturn->bbNum);
24473
24474         // If there are multiple callfinallys and we're in the
24475         // callfinally thunk model, all the callfinallys are placed
24476         // just outside the try region. We'd like our chosen
24477         // callfinally to come first after the try, so we can fall out of the try
24478         // into the clone.
24479         BasicBlock* firstCallFinallyRangeBlock = nullptr;
24480         BasicBlock* endCallFinallyRangeBlock   = nullptr;
24481         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
24482
24483         if (tryToRelocateCallFinally)
24484         {
24485             BasicBlock* firstCallFinallyBlock = nullptr;
24486
24487             for (BasicBlock* block = firstCallFinallyRangeBlock; block != endCallFinallyRangeBlock;
24488                  block             = block->bbNext)
24489             {
24490                 if (block->isBBCallAlwaysPair())
24491                 {
24492                     if (block->bbJumpDest == firstBlock)
24493                     {
24494                         firstCallFinallyBlock = block;
24495                         break;
24496                     }
24497                 }
24498             }
24499
24500             // We better have found at least one call finally.
24501             assert(firstCallFinallyBlock != nullptr);
24502
24503             // If there is more than one callfinally, move the one we are
24504             // going to retarget to be first in the callfinally range.
24505             if (firstCallFinallyBlock != normalCallFinallyBlock)
24506             {
24507                 JITDUMP("Moving callfinally BB%02u to be first in line, before BB%02u\n", normalCallFinallyBlock->bbNum,
24508                         firstCallFinallyBlock->bbNum);
24509
24510                 BasicBlock* const firstToMove      = normalCallFinallyBlock;
24511                 BasicBlock* const lastToMove       = normalCallFinallyBlock->bbNext;
24512                 BasicBlock* const placeToMoveAfter = firstCallFinallyBlock->bbPrev;
24513
24514                 fgUnlinkRange(firstToMove, lastToMove);
24515                 fgMoveBlocksAfter(firstToMove, lastToMove, placeToMoveAfter);
24516
24517 #ifdef DEBUG
24518                 // Sanity checks
24519                 fgDebugCheckBBlist(false, false);
24520                 fgVerifyHandlerTab();
24521 #endif // DEBUG
24522
24523                 assert(nextBlock == lastBlock->bbNext);
24524
24525                 // Update where the callfinally range begins, since we might
24526                 // have altered this with callfinally rearrangement, and/or
24527                 // the range begin might have been pretty loose to begin with.
24528                 firstCallFinallyRangeBlock = normalCallFinallyBlock;
24529             }
24530         }
24531
24532         // Clone the finally and retarget the normal return path and
24533         // any other path that happens to share that same return
24534         // point. For instance a construct like:
24535         //
24536         //  try { } catch { } finally { }
24537         //
24538         // will have two call finally blocks, one for the normal exit
24539         // from the try, and the the other for the exit from the
24540         // catch. They'll both pass the same return point which is the
24541         // statement after the finally, so they can share the clone.
24542         //
24543         // Clone the finally body, and splice it into the flow graph
24544         // within in the parent region of the try.
24545         const unsigned  finallyTryIndex = firstBlock->bbTryIndex;
24546         BasicBlock*     insertAfter     = nullptr;
24547         BlockToBlockMap blockMap(getAllocator());
24548         bool            clonedOk     = true;
24549         unsigned        cloneBBCount = 0;
24550
24551         for (BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
24552         {
24553             BasicBlock* newBlock;
24554
24555             if (block == firstBlock)
24556             {
24557                 // Put first cloned finally block into the approprate
24558                 // region, somewhere within or after the range of
24559                 // callfinallys, depending on the EH implementation.
24560                 const unsigned    hndIndex = 0;
24561                 BasicBlock* const nearBlk  = cloneInsertAfter;
24562                 newBlock                   = fgNewBBinRegion(block->bbJumpKind, finallyTryIndex, hndIndex, nearBlk);
24563
24564                 // If the clone ends up just after the finally, adjust
24565                 // the stopping point for finally traversal.
24566                 if (newBlock->bbNext == nextBlock)
24567                 {
24568                     assert(newBlock->bbPrev == lastBlock);
24569                     nextBlock = newBlock;
24570                 }
24571             }
24572             else
24573             {
24574                 // Put subsequent blocks in the same region...
24575                 const bool extendRegion = true;
24576                 newBlock                = fgNewBBafter(block->bbJumpKind, insertAfter, extendRegion);
24577             }
24578
24579             cloneBBCount++;
24580             assert(cloneBBCount <= regionBBCount);
24581
24582             insertAfter = newBlock;
24583             blockMap.Set(block, newBlock);
24584
24585             clonedOk = BasicBlock::CloneBlockState(this, newBlock, block);
24586
24587             if (!clonedOk)
24588             {
24589                 break;
24590             }
24591
24592             // Update block flags. Note a block can be both first and last.
24593             if (block == firstBlock)
24594             {
24595                 // Mark the block as the start of the cloned finally.
24596                 newBlock->bbFlags |= BBF_CLONED_FINALLY_BEGIN;
24597             }
24598
24599             if (block == lastBlock)
24600             {
24601                 // Mark the block as the end of the cloned finally.
24602                 newBlock->bbFlags |= BBF_CLONED_FINALLY_END;
24603             }
24604
24605             // Make sure clone block state hasn't munged the try region.
24606             assert(newBlock->bbTryIndex == finallyTryIndex);
24607
24608             // Cloned handler block is no longer within the handler.
24609             newBlock->clearHndIndex();
24610
24611             // Jump dests are set in a post-pass; make sure CloneBlockState hasn't tried to set them.
24612             assert(newBlock->bbJumpDest == nullptr);
24613         }
24614
24615         if (!clonedOk)
24616         {
24617             // TODO: cleanup the partial clone?
24618             JITDUMP("Unable to clone the finally; skipping.\n");
24619             continue;
24620         }
24621
24622         // We should have cloned all the finally region blocks.
24623         assert(cloneBBCount == regionBBCount);
24624
24625         JITDUMP("Cloned finally blocks are: BB%2u ... BB%2u\n", blockMap[firstBlock]->bbNum,
24626                 blockMap[lastBlock]->bbNum);
24627
24628         // Redirect redirect any branches within the newly-cloned
24629         // finally, and any finally returns to jump to the return
24630         // point.
24631         for (BasicBlock* block = firstBlock; block != nextBlock; block = block->bbNext)
24632         {
24633             BasicBlock* newBlock = blockMap[block];
24634
24635             if (block->bbJumpKind == BBJ_EHFINALLYRET)
24636             {
24637                 GenTreeStmt* finallyRet     = newBlock->lastStmt();
24638                 GenTree*     finallyRetExpr = finallyRet->gtStmtExpr;
24639                 assert(finallyRetExpr->gtOper == GT_RETFILT);
24640                 fgRemoveStmt(newBlock, finallyRet);
24641                 newBlock->bbJumpKind = BBJ_ALWAYS;
24642                 newBlock->bbJumpDest = normalCallFinallyReturn;
24643
24644                 fgAddRefPred(normalCallFinallyReturn, newBlock);
24645             }
24646             else
24647             {
24648                 optCopyBlkDest(block, newBlock);
24649                 optRedirectBlock(newBlock, &blockMap);
24650             }
24651         }
24652
24653         // Modify the targeting call finallys to branch to the cloned
24654         // finally. Make a note if we see some calls that can't be
24655         // retargeted (since they want to return to other places).
24656         BasicBlock* const firstCloneBlock    = blockMap[firstBlock];
24657         bool              retargetedAllCalls = true;
24658         BasicBlock*       currentBlock       = firstCallFinallyRangeBlock;
24659
24660         while (currentBlock != endCallFinallyRangeBlock)
24661         {
24662             BasicBlock* nextBlockToScan = currentBlock->bbNext;
24663
24664             if (currentBlock->isBBCallAlwaysPair())
24665             {
24666                 if (currentBlock->bbJumpDest == firstBlock)
24667                 {
24668                     BasicBlock* const leaveBlock          = currentBlock->bbNext;
24669                     BasicBlock* const postTryFinallyBlock = leaveBlock->bbJumpDest;
24670
24671                     // Note we must retarget all callfinallies that have this
24672                     // continuation, or we can't clean up the continuation
24673                     // block properly below, since it will be reachable both
24674                     // by the cloned finally and by the called finally.
24675                     if (postTryFinallyBlock == normalCallFinallyReturn)
24676                     {
24677                         // This call returns to the expected spot, so
24678                         // retarget it to branch to the clone.
24679                         currentBlock->bbJumpDest = firstCloneBlock;
24680                         currentBlock->bbJumpKind = BBJ_ALWAYS;
24681
24682                         // Ref count updates.
24683                         fgAddRefPred(firstCloneBlock, currentBlock);
24684                         // fgRemoveRefPred(firstBlock, currentBlock);
24685
24686                         // Delete the leave block, which should be marked as
24687                         // keep always.
24688                         assert((leaveBlock->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0);
24689                         nextBlock = leaveBlock->bbNext;
24690
24691                         leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
24692                         fgRemoveBlock(leaveBlock, true);
24693
24694                         // Make sure iteration isn't going off the deep end.
24695                         assert(leaveBlock != endCallFinallyRangeBlock);
24696                     }
24697                     else
24698                     {
24699                         // We can't retarget this call since it
24700                         // returns somewhere else.
24701                         retargetedAllCalls = false;
24702                     }
24703                 }
24704             }
24705
24706             currentBlock = nextBlockToScan;
24707         }
24708
24709         // If we retargeted all calls, modify EH descriptor to be
24710         // try-fault instead of try-finally, and then non-cloned
24711         // finally catch type to be fault.
24712         if (retargetedAllCalls)
24713         {
24714             JITDUMP("All callfinallys retargeted; changing finally to fault.\n");
24715             HBtab->ebdHandlerType  = EH_HANDLER_FAULT_WAS_FINALLY;
24716             firstBlock->bbCatchTyp = BBCT_FAULT;
24717         }
24718         else
24719         {
24720             JITDUMP("Some callfinallys *not* retargeted, so region must remain as a finally.\n");
24721         }
24722
24723         // Modify first block of cloned finally to be a "normal" block.
24724         BasicBlock* firstClonedBlock = blockMap[firstBlock];
24725         firstClonedBlock->bbCatchTyp = BBCT_NONE;
24726
24727         // Cleanup the continuation
24728         fgCleanupContinuation(normalCallFinallyReturn);
24729
24730         // Todo -- mark cloned blocks as a cloned finally....
24731
24732         // Done!
24733         JITDUMP("\nDone with EH#%u\n\n", XTnum);
24734         cloneCount++;
24735     }
24736
24737     if (cloneCount > 0)
24738     {
24739         JITDUMP("fgCloneFinally() cloned %u finally handlers\n", cloneCount);
24740         fgOptimizedFinally = true;
24741
24742 #ifdef DEBUG
24743         if (verbose)
24744         {
24745             printf("\n*************** After fgCloneFinally()\n");
24746             fgDispBasicBlocks();
24747             fgDispHandlerTab();
24748             printf("\n");
24749         }
24750
24751         fgVerifyHandlerTab();
24752         fgDebugCheckBBlist(false, false);
24753         fgDebugCheckTryFinallyExits();
24754
24755 #endif // DEBUG
24756     }
24757 }
24758
24759 #ifdef DEBUG
24760
24761 //------------------------------------------------------------------------
24762 // fgDebugCheckTryFinallyExits: validate normal flow from try-finally
24763 // or try-fault-was-finally.
24764 //
24765 // Notes:
24766 //
24767 // Normal control flow exiting the try block of a try-finally must
24768 // pass through the finally. This checker attempts to verify that by
24769 // looking at the control flow graph.
24770 //
24771 // Each path that exits the try of a try-finally (including try-faults
24772 // that were optimized into try-finallys by fgCloneFinally) should
24773 // thus either execute a callfinally to the associated finally or else
24774 // jump to a block with the BBF_CLONED_FINALLY_BEGIN flag set.
24775 //
24776 // Depending on when this check is done, there may also be an empty
24777 // block along the path.
24778 //
24779 // Depending on the model for invoking finallys, the callfinallies may
24780 // lie within the try region (callfinally thunks) or in the enclosing
24781 // region.
24782
24783 void Compiler::fgDebugCheckTryFinallyExits()
24784 {
24785     unsigned  XTnum            = 0;
24786     EHblkDsc* HBtab            = compHndBBtab;
24787     unsigned  cloneCount       = 0;
24788     bool      allTryExitsValid = true;
24789     for (; XTnum < compHndBBtabCount; XTnum++, HBtab++)
24790     {
24791         const EHHandlerType handlerType = HBtab->ebdHandlerType;
24792         const bool          isFinally   = (handlerType == EH_HANDLER_FINALLY);
24793         const bool          wasFinally  = (handlerType == EH_HANDLER_FAULT_WAS_FINALLY);
24794
24795         // Screen out regions that are or were not finallys.
24796         if (!isFinally && !wasFinally)
24797         {
24798             continue;
24799         }
24800
24801         // Walk blocks of the try, looking for normal control flow to
24802         // an ancestor region.
24803
24804         BasicBlock* const firstTryBlock = HBtab->ebdTryBeg;
24805         BasicBlock* const lastTryBlock  = HBtab->ebdTryLast;
24806         assert(firstTryBlock->getTryIndex() <= XTnum);
24807         assert(lastTryBlock->getTryIndex() <= XTnum);
24808         BasicBlock* const afterTryBlock = lastTryBlock->bbNext;
24809         BasicBlock* const finallyBlock  = isFinally ? HBtab->ebdHndBeg : nullptr;
24810
24811         for (BasicBlock* block = firstTryBlock; block != afterTryBlock; block = block->bbNext)
24812         {
24813             // Only check the directly contained blocks.
24814             assert(block->hasTryIndex());
24815
24816             if (block->getTryIndex() != XTnum)
24817             {
24818                 continue;
24819             }
24820
24821             // Look at each of the normal control flow possibilities.
24822             const unsigned numSuccs = block->NumSucc();
24823
24824             for (unsigned i = 0; i < numSuccs; i++)
24825             {
24826                 BasicBlock* const succBlock = block->GetSucc(i);
24827
24828                 if (succBlock->hasTryIndex() && succBlock->getTryIndex() <= XTnum)
24829                 {
24830                     // Successor does not exit this try region.
24831                     continue;
24832                 }
24833
24834 #if FEATURE_EH_CALLFINALLY_THUNKS
24835
24836                 // When there are callfinally thunks, callfinallies
24837                 // logically "belong" to a child region and the exit
24838                 // path validity will be checked when looking at the
24839                 // try blocks in that region.
24840                 if (block->bbJumpKind == BBJ_CALLFINALLY)
24841                 {
24842                     continue;
24843                 }
24844
24845 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24846
24847                 // Now we know block lies directly within the try of a
24848                 // try-finally, and succBlock is in an enclosing
24849                 // region (possibly the method region). So this path
24850                 // represents flow out of the try and should be
24851                 // checked.
24852                 //
24853                 // There are various ways control can properly leave a
24854                 // try-finally (or try-fault-was-finally):
24855                 //
24856                 // (a1) via a jump to a callfinally (only for finallys, only for call finally thunks)
24857                 // (a2) via a callfinally (only for finallys, only for !call finally thunks)
24858                 // (b) via a jump to a begin finally clone block
24859                 // (c) via a jump to an empty block to (b)
24860                 // (d) via a fallthrough to an empty block to (b)
24861                 // (e) via the always half of a callfinally pair
24862                 // (f) via an always jump clonefinally exit
24863                 bool isCallToFinally = false;
24864
24865 #if FEATURE_EH_CALLFINALLY_THUNKS
24866                 if (succBlock->bbJumpKind == BBJ_CALLFINALLY)
24867                 {
24868                     // case (a1)
24869                     isCallToFinally = isFinally && (succBlock->bbJumpDest == finallyBlock);
24870                 }
24871 #else
24872                 if (block->bbJumpKind == BBJ_CALLFINALLY)
24873                 {
24874                     // case (a2)
24875                     isCallToFinally = isFinally && (block->bbJumpDest == finallyBlock);
24876                 }
24877 #endif // FEATURE_EH_CALLFINALLY_THUNKS
24878
24879                 bool isJumpToClonedFinally = false;
24880
24881                 if (succBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24882                 {
24883                     // case (b)
24884                     isJumpToClonedFinally = true;
24885                 }
24886                 else if (succBlock->bbJumpKind == BBJ_ALWAYS)
24887                 {
24888                     if (succBlock->isEmpty())
24889                     {
24890                         // case (c)
24891                         BasicBlock* const succSuccBlock = succBlock->bbJumpDest;
24892
24893                         if (succSuccBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24894                         {
24895                             isJumpToClonedFinally = true;
24896                         }
24897                     }
24898                 }
24899                 else if (succBlock->bbJumpKind == BBJ_NONE)
24900                 {
24901                     if (succBlock->isEmpty())
24902                     {
24903                         BasicBlock* const succSuccBlock = succBlock->bbNext;
24904
24905                         // case (d)
24906                         if (succSuccBlock->bbFlags & BBF_CLONED_FINALLY_BEGIN)
24907                         {
24908                             isJumpToClonedFinally = true;
24909                         }
24910                     }
24911                 }
24912
24913                 bool isReturnFromFinally = false;
24914
24915                 // Case (e). Ideally we'd have something stronger to
24916                 // check here -- eg that we are returning from a call
24917                 // to the right finally -- but there are odd cases
24918                 // like orphaned second halves of callfinally pairs
24919                 // that we need to tolerate.
24920                 if (block->bbFlags & BBF_KEEP_BBJ_ALWAYS)
24921                 {
24922                     isReturnFromFinally = true;
24923                 }
24924
24925                 // Case (f)
24926                 if (block->bbFlags & BBF_CLONED_FINALLY_END)
24927                 {
24928                     isReturnFromFinally = true;
24929                 }
24930
24931                 const bool thisExitValid = isCallToFinally || isJumpToClonedFinally || isReturnFromFinally;
24932
24933                 if (!thisExitValid)
24934                 {
24935                     JITDUMP("fgCheckTryFinallyExitS: EH#%u exit via BB%02u -> BB%02u is invalid\n", XTnum, block->bbNum,
24936                             succBlock->bbNum);
24937                 }
24938
24939                 allTryExitsValid = allTryExitsValid & thisExitValid;
24940             }
24941         }
24942     }
24943
24944     if (!allTryExitsValid)
24945     {
24946         JITDUMP("fgCheckTryFinallyExits: method contains invalid try exit paths\n");
24947         assert(allTryExitsValid);
24948     }
24949 }
24950
24951 #endif // DEBUG
24952
24953 //------------------------------------------------------------------------
24954 // fgCleanupContinuation: cleanup a finally continuation after a
24955 // finally is removed or converted to normal control flow.
24956 //
24957 // Notes:
24958 //    The continuation is the block targeted by the second half of
24959 //    a callfinally/always pair.
24960 //
24961 //    Used by finally cloning, empty try removal, and empty
24962 //    finally removal.
24963 //
24964 //    BBF_FINALLY_TARGET bbFlag is left unchanged by this method
24965 //    since it cannot be incrementally updated. Proper updates happen
24966 //    when fgUpdateFinallyTargetFlags runs after all finally optimizations.
24967
24968 void Compiler::fgCleanupContinuation(BasicBlock* continuation)
24969 {
24970     // The continuation may be a finalStep block.
24971     // It is now a normal block, so clear the special keep
24972     // always flag.
24973     continuation->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
24974
24975 #if !FEATURE_EH_FUNCLETS
24976     // Remove the GT_END_LFIN from the continuation,
24977     // Note we only expect to see one such statement.
24978     bool foundEndLFin = false;
24979     for (GenTreeStmt* stmt = continuation->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
24980     {
24981         GenTree* expr = stmt->gtStmtExpr;
24982         if (expr->gtOper == GT_END_LFIN)
24983         {
24984             assert(!foundEndLFin);
24985             fgRemoveStmt(continuation, stmt);
24986             foundEndLFin = true;
24987         }
24988     }
24989     assert(foundEndLFin);
24990 #endif // !FEATURE_EH_FUNCLETS
24991 }
24992
24993 //------------------------------------------------------------------------
24994 // fgUpdateFinallyTargetFlags: recompute BBF_FINALLY_TARGET bits for all blocks
24995 // after finally optimizations have run.
24996
24997 void Compiler::fgUpdateFinallyTargetFlags()
24998 {
24999 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25000
25001     // Any fixup required?
25002     if (!fgOptimizedFinally)
25003     {
25004         JITDUMP("In fgUpdateFinallyTargetFlags - no finally opts, no fixup required\n");
25005         return;
25006     }
25007
25008     JITDUMP("In fgUpdateFinallyTargetFlags, updating finally target flag bits\n");
25009
25010     fgClearAllFinallyTargetBits();
25011     fgAddFinallyTargetFlags();
25012
25013 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25014 }
25015
25016 //------------------------------------------------------------------------
25017 // fgClearAllFinallyTargetBits: Clear all BBF_FINALLY_TARGET bits; these will need to be
25018 // recomputed later.
25019 //
25020 void Compiler::fgClearAllFinallyTargetBits()
25021 {
25022 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25023
25024     JITDUMP("*************** In fgClearAllFinallyTargetBits()\n");
25025
25026     // Note that we clear the flags even if there are no EH clauses (compHndBBtabCount == 0)
25027     // in case bits are left over from EH clauses being deleted.
25028
25029     // Walk all blocks, and reset the target bits.
25030     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25031     {
25032         block->bbFlags &= ~BBF_FINALLY_TARGET;
25033     }
25034
25035 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25036 }
25037
25038 //------------------------------------------------------------------------
25039 // fgAddFinallyTargetFlags: Add BBF_FINALLY_TARGET bits to all finally targets.
25040 //
25041 void Compiler::fgAddFinallyTargetFlags()
25042 {
25043 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25044
25045     JITDUMP("*************** In fgAddFinallyTargetFlags()\n");
25046
25047     if (compHndBBtabCount == 0)
25048     {
25049         JITDUMP("No EH in this method, no flags to set.\n");
25050         return;
25051     }
25052
25053     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25054     {
25055         if (block->isBBCallAlwaysPair())
25056         {
25057             BasicBlock* const leave        = block->bbNext;
25058             BasicBlock* const continuation = leave->bbJumpDest;
25059
25060             if ((continuation->bbFlags & BBF_FINALLY_TARGET) == 0)
25061             {
25062                 JITDUMP("Found callfinally BB%02u; setting finally target bit on BB%02u\n", block->bbNum,
25063                         continuation->bbNum);
25064
25065                 continuation->bbFlags |= BBF_FINALLY_TARGET;
25066             }
25067         }
25068     }
25069 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
25070 }
25071
25072 //------------------------------------------------------------------------
25073 // fgMergeFinallyChains: tail merge finally invocations
25074 //
25075 // Notes:
25076 //
25077 //    Looks for common suffixes in chains of finally invocations
25078 //    (callfinallys) and merges them. These typically arise from
25079 //    try-finallys where there are multiple exit points in the try
25080 //    that have the same target.
25081
25082 void Compiler::fgMergeFinallyChains()
25083 {
25084     JITDUMP("\n*************** In fgMergeFinallyChains()\n");
25085
25086 #if FEATURE_EH_FUNCLETS
25087     // We need to do this transformation before funclets are created.
25088     assert(!fgFuncletsCreated);
25089 #endif // FEATURE_EH_FUNCLETS
25090
25091     // Assume we don't need to update the bbPreds lists.
25092     assert(!fgComputePredsDone);
25093
25094     if (compHndBBtabCount == 0)
25095     {
25096         JITDUMP("No EH in this method, nothing to merge.\n");
25097         return;
25098     }
25099
25100     if (opts.MinOpts())
25101     {
25102         JITDUMP("Method compiled with minOpts, no merging.\n");
25103         return;
25104     }
25105
25106     if (opts.compDbgCode)
25107     {
25108         JITDUMP("Method compiled with debug codegen, no merging.\n");
25109         return;
25110     }
25111
25112     bool enableMergeFinallyChains = true;
25113
25114 #if !FEATURE_EH_FUNCLETS
25115     // For non-funclet models (x86) the callfinallys may contain
25116     // statements and the continuations contain GT_END_LFINs.  So no
25117     // merging is possible until the GT_END_LFIN blocks can be merged
25118     // and merging is not safe unless the callfinally blocks are split.
25119     JITDUMP("EH using non-funclet model; merging not yet implemented.\n");
25120     enableMergeFinallyChains = false;
25121 #endif // !FEATURE_EH_FUNCLETS
25122
25123 #if !FEATURE_EH_CALLFINALLY_THUNKS
25124     // For non-thunk EH models (arm32) the callfinallys may contain
25125     // statements, and merging is not safe unless the callfinally
25126     // blocks are split.
25127     JITDUMP("EH using non-callfinally thunk model; merging not yet implemented.\n");
25128     enableMergeFinallyChains = false;
25129 #endif
25130
25131     if (!enableMergeFinallyChains)
25132     {
25133         JITDUMP("fgMergeFinallyChains disabled\n");
25134         return;
25135     }
25136
25137 #ifdef DEBUG
25138     if (verbose)
25139     {
25140         printf("\n*************** Before fgMergeFinallyChains()\n");
25141         fgDispBasicBlocks();
25142         fgDispHandlerTab();
25143         printf("\n");
25144     }
25145 #endif // DEBUG
25146
25147     // Look for finallys.
25148     bool hasFinally = false;
25149     for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
25150     {
25151         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
25152
25153         // Check if this is a try/finally.
25154         if (HBtab->HasFinallyHandler())
25155         {
25156             hasFinally = true;
25157             break;
25158         }
25159     }
25160
25161     if (!hasFinally)
25162     {
25163         JITDUMP("Method does not have any try-finallys; no merging.\n");
25164         return;
25165     }
25166
25167     // Process finallys from outside in, merging as we go. This gives
25168     // us the desired bottom-up tail merge order for callfinally
25169     // chains: outer merges may enable inner merges.
25170     bool            canMerge = false;
25171     bool            didMerge = false;
25172     BlockToBlockMap continuationMap(getAllocator());
25173
25174     // Note XTnum is signed here so we can count down.
25175     for (int XTnum = compHndBBtabCount - 1; XTnum >= 0; XTnum--)
25176     {
25177         EHblkDsc* const HBtab = &compHndBBtab[XTnum];
25178
25179         // Screen out non-finallys
25180         if (!HBtab->HasFinallyHandler())
25181         {
25182             continue;
25183         }
25184
25185         JITDUMP("Examining callfinallys for EH#%d.\n", XTnum);
25186
25187         // Find all the callfinallys that invoke this finally.
25188         BasicBlock* firstCallFinallyRangeBlock = nullptr;
25189         BasicBlock* endCallFinallyRangeBlock   = nullptr;
25190         ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
25191
25192         // Clear out any stale entries in the continuation map
25193         continuationMap.RemoveAll();
25194
25195         // Build a map from each continuation to the "canonical"
25196         // callfinally for that continuation.
25197         unsigned          callFinallyCount  = 0;
25198         BasicBlock* const beginHandlerBlock = HBtab->ebdHndBeg;
25199
25200         for (BasicBlock* currentBlock = firstCallFinallyRangeBlock; currentBlock != endCallFinallyRangeBlock;
25201              currentBlock             = currentBlock->bbNext)
25202         {
25203             // Ignore "retless" callfinallys (where the finally doesn't return).
25204             if (currentBlock->isBBCallAlwaysPair() && (currentBlock->bbJumpDest == beginHandlerBlock))
25205             {
25206                 // The callfinally must be empty, so that we can
25207                 // safely retarget anything that branches here to
25208                 // another callfinally with the same contiuation.
25209                 assert(currentBlock->isEmpty());
25210
25211                 // This callfinally invokes the finally for this try.
25212                 callFinallyCount++;
25213
25214                 // Locate the continuation
25215                 BasicBlock* const leaveBlock        = currentBlock->bbNext;
25216                 BasicBlock* const continuationBlock = leaveBlock->bbJumpDest;
25217
25218                 // If this is the first time we've seen this
25219                 // continuation, register this callfinally as the
25220                 // canonical one.
25221                 if (!continuationMap.Lookup(continuationBlock))
25222                 {
25223                     continuationMap.Set(continuationBlock, currentBlock);
25224                 }
25225             }
25226         }
25227
25228         // Now we've seen all the callfinallys and their continuations.
25229         JITDUMP("EH#%i has %u callfinallys, %u continuations\n", XTnum, callFinallyCount, continuationMap.GetCount());
25230
25231         // If there are more callfinallys than continuations, some of the
25232         // callfinallys must share a continuation, and we can merge them.
25233         const bool tryMerge = callFinallyCount > continuationMap.GetCount();
25234
25235         if (!tryMerge)
25236         {
25237             JITDUMP("EH#%i does not have any mergeable callfinallys\n", XTnum);
25238             continue;
25239         }
25240
25241         canMerge = true;
25242
25243         // Walk the callfinally region, looking for blocks that jump
25244         // to a callfinally that invokes this try's finally, and make
25245         // sure they all jump to the appropriate canonical
25246         // callfinally.
25247         for (BasicBlock* currentBlock = firstCallFinallyRangeBlock; currentBlock != endCallFinallyRangeBlock;
25248              currentBlock             = currentBlock->bbNext)
25249         {
25250             bool merged = fgRetargetBranchesToCanonicalCallFinally(currentBlock, beginHandlerBlock, continuationMap);
25251             didMerge    = didMerge || merged;
25252         }
25253     }
25254
25255     if (!canMerge)
25256     {
25257         JITDUMP("Method had try-finallys, but did not have any mergeable finally chains.\n");
25258     }
25259     else
25260     {
25261         if (didMerge)
25262         {
25263             JITDUMP("Method had mergeable try-finallys and some callfinally merges were performed.\n");
25264
25265 #if DEBUG
25266             if (verbose)
25267             {
25268                 printf("\n*************** After fgMergeFinallyChains()\n");
25269                 fgDispBasicBlocks();
25270                 fgDispHandlerTab();
25271                 printf("\n");
25272             }
25273
25274 #endif // DEBUG
25275         }
25276         else
25277         {
25278             // We may not end up doing any merges, because we are only
25279             // merging continuations for callfinallys that can
25280             // actually be invoked, and the importer may leave
25281             // unreachable callfinallys around (for instance, if it
25282             // is forced to re-import a leave).
25283             JITDUMP("Method had mergeable try-finallys but no callfinally merges were performed,\n"
25284                     "likely the non-canonical callfinallys were unreachable\n");
25285         }
25286     }
25287 }
25288
25289 //------------------------------------------------------------------------
25290 // fgRetargetBranchesToCanonicalCallFinally: find non-canonical callfinally
25291 // invocations and make them canonical.
25292 //
25293 // Arguments:
25294 //     block -- block to examine for call finally invocation
25295 //     handler -- start of the finally region for the try
25296 //     continuationMap -- map giving the canonical callfinally for
25297 //        each continuation
25298 //
25299 // Returns:
25300 //     true iff the block's branch was retargeted.
25301
25302 bool Compiler::fgRetargetBranchesToCanonicalCallFinally(BasicBlock*      block,
25303                                                         BasicBlock*      handler,
25304                                                         BlockToBlockMap& continuationMap)
25305 {
25306     // We expect callfinallys to be invoked by a BBJ_ALWAYS at this
25307     // stage in compilation.
25308     if (block->bbJumpKind != BBJ_ALWAYS)
25309     {
25310         // Possible paranoia assert here -- no flow successor of
25311         // this block should be a callfinally for this try.
25312         return false;
25313     }
25314
25315     // Screen out cases that are not callfinallys to the right
25316     // handler.
25317     BasicBlock* const callFinally = block->bbJumpDest;
25318
25319     if (!callFinally->isBBCallAlwaysPair())
25320     {
25321         return false;
25322     }
25323
25324     if (callFinally->bbJumpDest != handler)
25325     {
25326         return false;
25327     }
25328
25329     // Ok, this is a callfinally that invokes the right handler.
25330     // Get its continuation.
25331     BasicBlock* const leaveBlock        = callFinally->bbNext;
25332     BasicBlock* const continuationBlock = leaveBlock->bbJumpDest;
25333
25334     // Find the canonical callfinally for that continuation.
25335     BasicBlock* const canonicalCallFinally = continuationMap[continuationBlock];
25336     assert(canonicalCallFinally != nullptr);
25337
25338     // If the block already jumps to the canoncial call finally, no work needed.
25339     if (block->bbJumpDest == canonicalCallFinally)
25340     {
25341         JITDUMP("BB%02u already canonical\n", block->bbNum);
25342         return false;
25343     }
25344
25345     // Else, retarget it so that it does...
25346     JITDUMP("Redirecting branch in BB%02u from BB%02u to BB%02u.\n", block->bbNum, callFinally->bbNum,
25347             canonicalCallFinally->bbNum);
25348
25349     block->bbJumpDest = canonicalCallFinally;
25350     fgAddRefPred(canonicalCallFinally, block);
25351     assert(callFinally->bbRefs > 0);
25352     fgRemoveRefPred(callFinally, block);
25353
25354     return true;
25355 }
25356
25357 // FatCalliTransformer transforms calli that can use fat function pointer.
25358 // Fat function pointer is pointer with the second least significant bit set,
25359 // if the bit is set, the pointer (after clearing the bit) actually points to
25360 // a tuple <method pointer, instantiation argument pointer> where
25361 // instantiationArgument is a hidden first argument required by method pointer.
25362 //
25363 // Fat pointers are used in CoreRT as a replacement for instantiating stubs,
25364 // because CoreRT can't generate stubs in runtime.
25365 //
25366 // Jit is responsible for the checking the bit, do the regular call if it is not set
25367 // or load hidden argument, fix the pointer and make a call with the fixed pointer and
25368 // the instantiation argument.
25369 //
25370 // before:
25371 //   current block
25372 //   {
25373 //     previous statements
25374 //     transforming statement
25375 //     {
25376 //       call with GTF_CALL_M_FAT_POINTER_CHECK flag set in function ptr
25377 //     }
25378 //     subsequent statements
25379 //   }
25380 //
25381 // after:
25382 //   current block
25383 //   {
25384 //     previous statements
25385 //   } BBJ_NONE check block
25386 //   check block
25387 //   {
25388 //     jump to else if function ptr has GTF_CALL_M_FAT_POINTER_CHECK set.
25389 //   } BBJ_COND then block, else block
25390 //   then block
25391 //   {
25392 //     original statement
25393 //   } BBJ_ALWAYS remainder block
25394 //   else block
25395 //   {
25396 //     unset GTF_CALL_M_FAT_POINTER_CHECK
25397 //     load actual function pointer
25398 //     load instantiation argument
25399 //     create newArgList = (instantiation argument, original argList)
25400 //     call (actual function pointer, newArgList)
25401 //   } BBJ_NONE remainder block
25402 //   remainder block
25403 //   {
25404 //     subsequent statements
25405 //   }
25406 //
25407 class FatCalliTransformer
25408 {
25409 public:
25410     FatCalliTransformer(Compiler* compiler) : compiler(compiler)
25411     {
25412     }
25413
25414     //------------------------------------------------------------------------
25415     // Run: run transformation for each block.
25416     //
25417     void Run()
25418     {
25419         for (BasicBlock* block = compiler->fgFirstBB; block != nullptr; block = block->bbNext)
25420         {
25421             TransformBlock(block);
25422         }
25423     }
25424
25425 private:
25426     //------------------------------------------------------------------------
25427     // TransformBlock: look through statements and transform statements with fat pointer calls.
25428     //
25429     void TransformBlock(BasicBlock* block)
25430     {
25431         for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
25432         {
25433             if (ContainsFatCalli(stmt))
25434             {
25435                 StatementTransformer stmtTransformer(compiler, block, stmt);
25436                 stmtTransformer.Run();
25437             }
25438         }
25439     }
25440
25441     //------------------------------------------------------------------------
25442     // ContainsFatCalli: check does this statement contain fat pointer call.
25443     //
25444     // Checks fatPointerCandidate in form of call() or lclVar = call().
25445     //
25446     // Return Value:
25447     //    true if contains, false otherwise.
25448     //
25449     bool ContainsFatCalli(GenTreeStmt* stmt)
25450     {
25451         GenTree* fatPointerCandidate = stmt->gtStmtExpr;
25452         if (fatPointerCandidate->OperIsAssignment())
25453         {
25454             fatPointerCandidate = fatPointerCandidate->gtGetOp2();
25455         }
25456         return fatPointerCandidate->IsCall() && fatPointerCandidate->AsCall()->IsFatPointerCandidate();
25457     }
25458
25459     class StatementTransformer
25460     {
25461     public:
25462         StatementTransformer(Compiler* compiler, BasicBlock* block, GenTreeStmt* stmt)
25463             : compiler(compiler), currBlock(block), stmt(stmt)
25464         {
25465             remainderBlock  = nullptr;
25466             checkBlock      = nullptr;
25467             thenBlock       = nullptr;
25468             elseBlock       = nullptr;
25469             doesReturnValue = stmt->gtStmtExpr->OperIsAssignment();
25470             origCall        = GetCall(stmt);
25471             fptrAddress     = origCall->gtCallAddr;
25472             pointerType     = fptrAddress->TypeGet();
25473         }
25474
25475         //------------------------------------------------------------------------
25476         // Run: transform the statement as described above.
25477         //
25478         void Run()
25479         {
25480             ClearFatFlag();
25481             CreateRemainder();
25482             CreateCheck();
25483             CreateThen();
25484             CreateElse();
25485
25486             RemoveOldStatement();
25487             SetWeights();
25488             ChainFlow();
25489         }
25490
25491     private:
25492         //------------------------------------------------------------------------
25493         // GetCall: find a call in a statement.
25494         //
25495         // Arguments:
25496         //    callStmt - the statement with the call inside.
25497         //
25498         // Return Value:
25499         //    call tree node pointer.
25500         GenTreeCall* GetCall(GenTreeStmt* callStmt)
25501         {
25502             GenTree*     tree = callStmt->gtStmtExpr;
25503             GenTreeCall* call = nullptr;
25504             if (doesReturnValue)
25505             {
25506                 assert(tree->OperIsAssignment());
25507                 call = tree->gtGetOp2()->AsCall();
25508             }
25509             else
25510             {
25511                 call = tree->AsCall(); // call with void return type.
25512             }
25513             return call;
25514         }
25515
25516         //------------------------------------------------------------------------
25517         // ClearFatFlag: clear fat pointer candidate flag from the original call.
25518         //
25519         void ClearFatFlag()
25520         {
25521             origCall->ClearFatPointerCandidate();
25522         }
25523
25524         //------------------------------------------------------------------------
25525         // CreateRemainder: split current block at the fat call stmt and
25526         // insert statements after the call into remainderBlock.
25527         //
25528         void CreateRemainder()
25529         {
25530             remainderBlock          = compiler->fgSplitBlockAfterStatement(currBlock, stmt);
25531             unsigned propagateFlags = currBlock->bbFlags & BBF_GC_SAFE_POINT;
25532             remainderBlock->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL | propagateFlags;
25533         }
25534
25535         //------------------------------------------------------------------------
25536         // CreateCheck: create check block, that checks fat pointer bit set.
25537         //
25538         void CreateCheck()
25539         {
25540             checkBlock               = CreateAndInsertBasicBlock(BBJ_COND, currBlock);
25541             GenTree* fatPointerMask  = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, FAT_POINTER_MASK);
25542             GenTree* fptrAddressCopy = compiler->gtCloneExpr(fptrAddress);
25543             GenTree* fatPointerAnd   = compiler->gtNewOperNode(GT_AND, TYP_I_IMPL, fptrAddressCopy, fatPointerMask);
25544             GenTree* zero            = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, 0);
25545             GenTree* fatPointerCmp   = compiler->gtNewOperNode(GT_NE, TYP_INT, fatPointerAnd, zero);
25546             GenTree* jmpTree         = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, fatPointerCmp);
25547             GenTree* jmpStmt         = compiler->fgNewStmtFromTree(jmpTree, stmt->gtStmt.gtStmtILoffsx);
25548             compiler->fgInsertStmtAtEnd(checkBlock, jmpStmt);
25549         }
25550
25551         //------------------------------------------------------------------------
25552         // CreateCheck: create then block, that is executed if call address is not fat pointer.
25553         //
25554         void CreateThen()
25555         {
25556             thenBlock               = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock);
25557             GenTree* nonFatCallStmt = compiler->gtCloneExpr(stmt)->AsStmt();
25558             compiler->fgInsertStmtAtEnd(thenBlock, nonFatCallStmt);
25559         }
25560
25561         //------------------------------------------------------------------------
25562         // CreateCheck: create else block, that is executed if call address is fat pointer.
25563         //
25564         void CreateElse()
25565         {
25566             elseBlock = CreateAndInsertBasicBlock(BBJ_NONE, thenBlock);
25567
25568             GenTree* fixedFptrAddress  = GetFixedFptrAddress();
25569             GenTree* actualCallAddress = compiler->gtNewOperNode(GT_IND, pointerType, fixedFptrAddress);
25570             GenTree* hiddenArgument    = GetHiddenArgument(fixedFptrAddress);
25571
25572             GenTreeStmt* fatStmt = CreateFatCallStmt(actualCallAddress, hiddenArgument);
25573             compiler->fgInsertStmtAtEnd(elseBlock, fatStmt);
25574         }
25575
25576         //------------------------------------------------------------------------
25577         // CreateAndInsertBasicBlock: ask compiler to create new basic block.
25578         // and insert in into the basic block list.
25579         //
25580         // Arguments:
25581         //    jumpKind - jump kind for the new basic block
25582         //    insertAfter - basic block, after which compiler has to insert the new one.
25583         //
25584         // Return Value:
25585         //    new basic block.
25586         BasicBlock* CreateAndInsertBasicBlock(BBjumpKinds jumpKind, BasicBlock* insertAfter)
25587         {
25588             BasicBlock* block = compiler->fgNewBBafter(jumpKind, insertAfter, true);
25589             if ((insertAfter->bbFlags & BBF_INTERNAL) == 0)
25590             {
25591                 block->bbFlags &= ~BBF_INTERNAL;
25592                 block->bbFlags |= BBF_IMPORTED;
25593             }
25594             return block;
25595         }
25596
25597         //------------------------------------------------------------------------
25598         // GetFixedFptrAddress: clear fat pointer bit from fat pointer address.
25599         //
25600         // Return Value:
25601         //    address without fat pointer bit set.
25602         GenTree* GetFixedFptrAddress()
25603         {
25604             GenTree* fptrAddressCopy = compiler->gtCloneExpr(fptrAddress);
25605             GenTree* fatPointerMask  = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, FAT_POINTER_MASK);
25606             return compiler->gtNewOperNode(GT_SUB, pointerType, fptrAddressCopy, fatPointerMask);
25607         }
25608
25609         //------------------------------------------------------------------------
25610         // GetHiddenArgument: load hidden argument.
25611         //
25612         // Arguments:
25613         //    fixedFptrAddress - pointer to the tuple <methodPointer, instantiationArgumentPointer>
25614         //
25615         // Return Value:
25616         //    generic context hidden argument.
25617         GenTree* GetHiddenArgument(GenTree* fixedFptrAddress)
25618         {
25619             GenTree* fixedFptrAddressCopy = compiler->gtCloneExpr(fixedFptrAddress);
25620             GenTree* wordSize = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, genTypeSize(TYP_I_IMPL));
25621             GenTree* hiddenArgumentPtrPtr =
25622                 compiler->gtNewOperNode(GT_ADD, pointerType, fixedFptrAddressCopy, wordSize);
25623             GenTree* hiddenArgumentPtr = compiler->gtNewOperNode(GT_IND, pointerType, hiddenArgumentPtrPtr);
25624             return compiler->gtNewOperNode(GT_IND, fixedFptrAddressCopy->TypeGet(), hiddenArgumentPtr);
25625         }
25626
25627         //------------------------------------------------------------------------
25628         // CreateFatCallStmt: create call with fixed call address and hidden argument in the args list.
25629         //
25630         // Arguments:
25631         //    actualCallAddress - fixed call address
25632         //    hiddenArgument - generic context hidden argument
25633         //
25634         // Return Value:
25635         //    created call node.
25636         GenTreeStmt* CreateFatCallStmt(GenTree* actualCallAddress, GenTree* hiddenArgument)
25637         {
25638             GenTreeStmt* fatStmt = compiler->gtCloneExpr(stmt)->AsStmt();
25639             GenTree*     fatTree = fatStmt->gtStmtExpr;
25640             GenTreeCall* fatCall = GetCall(fatStmt);
25641             fatCall->gtCallAddr  = actualCallAddress;
25642             AddHiddenArgument(fatCall, hiddenArgument);
25643             return fatStmt;
25644         }
25645
25646         //------------------------------------------------------------------------
25647         // AddHiddenArgument: add hidden argument to the call argument list.
25648         //
25649         // Arguments:
25650         //    fatCall - fat call node
25651         //    hiddenArgument - generic context hidden argument
25652         //
25653         void AddHiddenArgument(GenTreeCall* fatCall, GenTree* hiddenArgument)
25654         {
25655             GenTreeArgList* oldArgs = fatCall->gtCallArgs;
25656             GenTreeArgList* newArgs;
25657 #if USER_ARGS_COME_LAST
25658             if (fatCall->HasRetBufArg())
25659             {
25660                 GenTree*        retBuffer = oldArgs->Current();
25661                 GenTreeArgList* rest      = oldArgs->Rest();
25662                 newArgs                   = compiler->gtNewListNode(hiddenArgument, rest);
25663                 newArgs                   = compiler->gtNewListNode(retBuffer, newArgs);
25664             }
25665             else
25666             {
25667                 newArgs = compiler->gtNewListNode(hiddenArgument, oldArgs);
25668             }
25669 #else
25670             newArgs = oldArgs;
25671             AddArgumentToTail(newArgs, hiddenArgument);
25672 #endif
25673             fatCall->gtCallArgs = newArgs;
25674         }
25675
25676         //------------------------------------------------------------------------
25677         // AddArgumentToTail: add hidden argument to the tail of the call argument list.
25678         //
25679         // Arguments:
25680         //    argList - fat call node
25681         //    hiddenArgument - generic context hidden argument
25682         //
25683         void AddArgumentToTail(GenTreeArgList* argList, GenTree* hiddenArgument)
25684         {
25685             GenTreeArgList* iterator = argList;
25686             while (iterator->Rest() != nullptr)
25687             {
25688                 iterator = iterator->Rest();
25689             }
25690             iterator->Rest() = compiler->gtNewArgList(hiddenArgument);
25691         }
25692
25693         //------------------------------------------------------------------------
25694         // RemoveOldStatement: remove original stmt from current block.
25695         //
25696         void RemoveOldStatement()
25697         {
25698             compiler->fgRemoveStmt(currBlock, stmt);
25699         }
25700
25701         //------------------------------------------------------------------------
25702         // SetWeights: set weights for new blocks.
25703         //
25704         void SetWeights()
25705         {
25706             remainderBlock->inheritWeight(currBlock);
25707             checkBlock->inheritWeight(currBlock);
25708             thenBlock->inheritWeightPercentage(currBlock, HIGH_PROBABILITY);
25709             elseBlock->inheritWeightPercentage(currBlock, 100 - HIGH_PROBABILITY);
25710         }
25711
25712         //------------------------------------------------------------------------
25713         // ChainFlow: link new blocks into correct cfg.
25714         //
25715         void ChainFlow()
25716         {
25717             assert(!compiler->fgComputePredsDone);
25718             checkBlock->bbJumpDest = elseBlock;
25719             thenBlock->bbJumpDest  = remainderBlock;
25720         }
25721
25722         Compiler*    compiler;
25723         BasicBlock*  currBlock;
25724         BasicBlock*  remainderBlock;
25725         BasicBlock*  checkBlock;
25726         BasicBlock*  thenBlock;
25727         BasicBlock*  elseBlock;
25728         GenTreeStmt* stmt;
25729         GenTreeCall* origCall;
25730         GenTree*     fptrAddress;
25731         var_types    pointerType;
25732         bool         doesReturnValue;
25733
25734         const int FAT_POINTER_MASK = 0x2;
25735         const int HIGH_PROBABILITY = 80;
25736     };
25737
25738     Compiler* compiler;
25739 };
25740
25741 #ifdef DEBUG
25742
25743 //------------------------------------------------------------------------
25744 // fgDebugCheckFatPointerCandidates: callback to make sure there are no more GTF_CALL_M_FAT_POINTER_CHECK calls.
25745 //
25746 Compiler::fgWalkResult Compiler::fgDebugCheckFatPointerCandidates(GenTree** pTree, fgWalkData* data)
25747 {
25748     GenTree* tree = *pTree;
25749     if (tree->IsCall())
25750     {
25751         assert(!tree->AsCall()->IsFatPointerCandidate());
25752     }
25753     return WALK_CONTINUE;
25754 }
25755
25756 //------------------------------------------------------------------------
25757 // CheckNoFatPointerCandidatesLeft: walk through blocks and check that there are no fat pointer candidates left.
25758 //
25759 void Compiler::CheckNoFatPointerCandidatesLeft()
25760 {
25761     assert(!doesMethodHaveFatPointer());
25762     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25763     {
25764         for (GenTreeStmt* stmt = fgFirstBB->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
25765         {
25766             fgWalkTreePre(&stmt->gtStmtExpr, fgDebugCheckFatPointerCandidates);
25767         }
25768     }
25769 }
25770 #endif
25771
25772 //------------------------------------------------------------------------
25773 // fgTransformFatCalli: find and transform fat calls.
25774 //
25775 void Compiler::fgTransformFatCalli()
25776 {
25777     assert(IsTargetAbi(CORINFO_CORERT_ABI));
25778     FatCalliTransformer fatCalliTransformer(this);
25779     fatCalliTransformer.Run();
25780     clearMethodHasFatPointer();
25781 #ifdef DEBUG
25782     CheckNoFatPointerCandidatesLeft();
25783 #endif
25784 }
25785
25786 //------------------------------------------------------------------------
25787 // fgMeasureIR: count and return the number of IR nodes in the function.
25788 //
25789 unsigned Compiler::fgMeasureIR()
25790 {
25791     unsigned nodeCount = 0;
25792
25793     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
25794     {
25795         if (!block->IsLIR())
25796         {
25797             for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt())
25798             {
25799                 fgWalkTreePre(&stmt->gtStmtExpr,
25800                               [](GenTree** slot, fgWalkData* data) -> Compiler::fgWalkResult {
25801                                   (*reinterpret_cast<unsigned*>(data->pCallbackData))++;
25802                                   return Compiler::WALK_CONTINUE;
25803                               },
25804                               &nodeCount);
25805             }
25806         }
25807         else
25808         {
25809             for (GenTree* node : LIR::AsRange(block))
25810             {
25811                 nodeCount++;
25812             }
25813         }
25814     }
25815
25816     return nodeCount;
25817 }
25818
25819 //------------------------------------------------------------------------
25820 // fgCompDominatedByExceptionalEntryBlocks: compute blocks that are
25821 // dominated by not normal entry.
25822 //
25823 void Compiler::fgCompDominatedByExceptionalEntryBlocks()
25824 {
25825     assert(fgEnterBlksSetValid);
25826     if (BlockSetOps::Count(this, fgEnterBlks) != 1) // There are exception entries.
25827     {
25828         for (unsigned i = 1; i <= fgBBNumMax; ++i)
25829         {
25830             BasicBlock* block = fgBBInvPostOrder[i];
25831             if (BlockSetOps::IsMember(this, fgEnterBlks, block->bbNum))
25832             {
25833                 if (fgFirstBB != block) // skip the normal entry.
25834                 {
25835                     block->SetDominatedByExceptionalEntryFlag();
25836                 }
25837             }
25838             else if (block->bbIDom->IsDominatedByExceptionalEntryFlag())
25839             {
25840                 block->SetDominatedByExceptionalEntryFlag();
25841             }
25842         }
25843     }
25844 }
25845
25846 //------------------------------------------------------------------------
25847 // fgNeedReturnSpillTemp: Answers does the inlinee need to spill all returns
25848 //  as a temp.
25849 //
25850 // Return Value:
25851 //    true if the inlinee has to spill return exprs.
25852 bool Compiler::fgNeedReturnSpillTemp()
25853 {
25854     assert(compIsForInlining());
25855     return (lvaInlineeReturnSpillTemp != BAD_VAR_NUM);
25856 }
25857
25858 //------------------------------------------------------------------------
25859 // fgUseThrowHelperBlocks: Determinate does compiler use throw helper blocks.
25860 //
25861 // Note:
25862 //   For debuggable code, codegen will generate the 'throw' code inline.
25863 // Return Value:
25864 //    true if 'throw' helper block should be created.
25865 bool Compiler::fgUseThrowHelperBlocks()
25866 {
25867     return !opts.compDbgCode;
25868 }