Sync may31 release/8.0-tizen (#510)
[platform/upstream/dotnet/runtime.git] / src / coreclr / jit / compiler.h
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
4 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XX                                                                           XX
7 XX                           Compiler                                        XX
8 XX                                                                           XX
9 XX  Represents the method data we are currently JIT-compiling.               XX
10 XX  An instance of this class is created for every method we JIT.            XX
11 XX  This contains all the info needed for the method. So allocating a        XX
12 XX  a new instance per method makes it thread-safe.                          XX
13 XX  It should be used to do all the memory management for the compiler run.  XX
14 XX                                                                           XX
15 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
17 */
18
19 /*****************************************************************************/
20 #ifndef _COMPILER_H_
21 #define _COMPILER_H_
22 /*****************************************************************************/
23
24 #include "jit.h"
25 #include "opcode.h"
26 #include "varset.h"
27 #include "jitstd.h"
28 #include "jithashtable.h"
29 #include "gentree.h"
30 #include "debuginfo.h"
31 #include "lir.h"
32 #include "block.h"
33 #include "inline.h"
34 #include "jiteh.h"
35 #include "instr.h"
36 #include "regalloc.h"
37 #include "sm.h"
38 #include "cycletimer.h"
39 #include "blockset.h"
40 #include "arraystack.h"
41 #include "hashbv.h"
42 #include "jitexpandarray.h"
43 #include "tinyarray.h"
44 #include "valuenum.h"
45 #include "jittelemetry.h"
46 #include "namedintrinsiclist.h"
47 #ifdef LATE_DISASM
48 #include "disasm.h"
49 #endif
50
51 #include "codegeninterface.h"
52 #include "regset.h"
53 #include "jitgcinfo.h"
54
55 #if DUMP_GC_TABLES && defined(JIT32_GCENCODER)
56 #include "gcdump.h"
57 #endif
58
59 #include "emit.h"
60
61 // Forward declaration
62 template <class T>
63 inline var_types genActualType(T value);
64
65 #include "hwintrinsic.h"
66 #include "simd.h"
67 #include "simdashwintrinsic.h"
68
69 /*****************************************************************************
70  *                  Forward declarations
71  */
72
73 struct InfoHdr;              // defined in GCInfo.h
74 struct escapeMapping_t;      // defined in fgdiagnostic.cpp
75 class emitter;               // defined in emit.h
76 struct ShadowParamVarInfo;   // defined in GSChecks.cpp
77 struct InitVarDscInfo;       // defined in registerargconvention.h
78 class FgStack;               // defined in fgbasic.cpp
79 class Instrumentor;          // defined in fgprofile.cpp
80 class SpanningTreeVisitor;   // defined in fgprofile.cpp
81 class CSE_DataFlow;          // defined in OptCSE.cpp
82 class OptBoolsDsc;           // defined in optimizer.cpp
83 struct RelopImplicationInfo; // defined in redundantbranchopts.cpp
84 struct JumpThreadInfo;       // defined in redundantbranchopts.cpp
85 class ProfileSynthesis;      // defined in profilesynthesis.h
86 #ifdef DEBUG
87 struct IndentStack;
88 #endif
89
90 class Lowering; // defined in lower.h
91
92 // The following are defined in this file, Compiler.h
93
94 class Compiler;
95
96 /*****************************************************************************
97  *                  Unwind info
98  */
99
100 #include "unwind.h"
101
102 /*****************************************************************************/
103
104 //
105 // Declare global operator new overloads that use the compiler's arena allocator
106 //
107
108 void* operator new(size_t n, Compiler* context, CompMemKind cmk);
109 void* operator new[](size_t n, Compiler* context, CompMemKind cmk);
110
111 // Requires the definitions of "operator new" so including "LoopCloning.h" after the definitions.
112 #include "loopcloning.h"
113
114 /*****************************************************************************/
115
116 /* This is included here and not earlier as it needs the definition of "CSE"
117  * which is defined in the section above */
118
119 /*****************************************************************************/
120
121 unsigned genLog2(unsigned value);
122 unsigned genLog2(unsigned __int64 value);
123
124 unsigned ReinterpretHexAsDecimal(unsigned in);
125
126 /*****************************************************************************/
127
128 const unsigned FLG_CCTOR = (CORINFO_FLG_CONSTRUCTOR | CORINFO_FLG_STATIC);
129
130 #ifdef DEBUG
131 const int BAD_STK_OFFS = 0xBAADF00D; // for LclVarDsc::lvStkOffs
132 #endif
133
134 //------------------------------------------------------------------------
135 // HFA info shared by LclVarDsc and CallArgABIInformation
136 //------------------------------------------------------------------------
137 inline bool IsHfa(CorInfoHFAElemType kind)
138 {
139     return kind != CORINFO_HFA_ELEM_NONE;
140 }
141 inline var_types HfaTypeFromElemKind(CorInfoHFAElemType kind)
142 {
143     switch (kind)
144     {
145         case CORINFO_HFA_ELEM_FLOAT:
146             return TYP_FLOAT;
147         case CORINFO_HFA_ELEM_DOUBLE:
148             return TYP_DOUBLE;
149 #ifdef FEATURE_SIMD
150         case CORINFO_HFA_ELEM_VECTOR64:
151             return TYP_SIMD8;
152         case CORINFO_HFA_ELEM_VECTOR128:
153             return TYP_SIMD16;
154 #endif
155         case CORINFO_HFA_ELEM_NONE:
156             return TYP_UNDEF;
157         default:
158             assert(!"Invalid HfaElemKind");
159             return TYP_UNDEF;
160     }
161 }
162 inline CorInfoHFAElemType HfaElemKindFromType(var_types type)
163 {
164     switch (type)
165     {
166         case TYP_FLOAT:
167             return CORINFO_HFA_ELEM_FLOAT;
168         case TYP_DOUBLE:
169             return CORINFO_HFA_ELEM_DOUBLE;
170 #ifdef FEATURE_SIMD
171         case TYP_SIMD8:
172             return CORINFO_HFA_ELEM_VECTOR64;
173         case TYP_SIMD16:
174             return CORINFO_HFA_ELEM_VECTOR128;
175 #endif
176         case TYP_UNDEF:
177             return CORINFO_HFA_ELEM_NONE;
178         default:
179             assert(!"Invalid HFA Type");
180             return CORINFO_HFA_ELEM_NONE;
181     }
182 }
183
184 // The following holds the Local var info (scope information)
185 typedef const char* VarName; // Actual ASCII string
186 struct VarScopeDsc
187 {
188     unsigned vsdVarNum; // (remapped) LclVarDsc number
189     unsigned vsdLVnum;  // 'which' in eeGetLVinfo().
190                         // Also, it is the index of this entry in the info.compVarScopes array,
191                         // which is useful since the array is also accessed via the
192                         // compEnterScopeList and compExitScopeList sorted arrays.
193
194     IL_OFFSET vsdLifeBeg; // instr offset of beg of life
195     IL_OFFSET vsdLifeEnd; // instr offset of end of life
196
197 #ifdef DEBUG
198     VarName vsdName; // name of the var
199 #endif
200 };
201
202 // This class stores information associated with a LclVar SSA definition.
203 class LclSsaVarDsc
204 {
205     // The basic block where the definition occurs. Definitions of uninitialized variables
206     // are considered to occur at the start of the first basic block (fgFirstBB).
207     //
208     // TODO-Cleanup: In the case of uninitialized variables the block is set to nullptr by
209     // SsaBuilder and changed to fgFirstBB during value numbering. It would be useful to
210     // investigate and perhaps eliminate this rather unexpected behavior.
211     BasicBlock* m_block = nullptr;
212     // The store node that generates the definition, or nullptr for definitions
213     // of uninitialized variables.
214     GenTreeLclVarCommon* m_defNode = nullptr;
215     // The SSA number associated with the previous definition for partial (GTF_USEASG) defs.
216     unsigned m_useDefSsaNum = SsaConfig::RESERVED_SSA_NUM;
217     // Number of uses of this SSA def (may be an over-estimate).
218     // May not be accurate for for promoted fields.
219     unsigned short m_numUses = 0;
220     // True if there may be phi args uses of this def
221     // May not be accurate for for promoted fields.
222     // (false implies all uses are non-phi).
223     bool m_hasPhiUse = false;
224     // True if there may be uses of the def in a different block.
225     // May not be accurate for for promoted fields.
226     bool m_hasGlobalUse = false;
227
228 public:
229     LclSsaVarDsc()
230     {
231     }
232
233     LclSsaVarDsc(BasicBlock* block) : m_block(block)
234     {
235     }
236
237     LclSsaVarDsc(BasicBlock* block, GenTreeLclVarCommon* defNode) : m_block(block)
238     {
239         SetDefNode(defNode);
240     }
241
242     BasicBlock* GetBlock() const
243     {
244         return m_block;
245     }
246
247     void SetBlock(BasicBlock* block)
248     {
249         m_block = block;
250     }
251
252     GenTreeLclVarCommon* GetDefNode() const
253     {
254         return m_defNode;
255     }
256
257     void SetDefNode(GenTreeLclVarCommon* defNode)
258     {
259         assert((defNode == nullptr) || defNode->OperIsLocalStore());
260         m_defNode = defNode;
261     }
262
263     unsigned GetUseDefSsaNum() const
264     {
265         return m_useDefSsaNum;
266     }
267
268     void SetUseDefSsaNum(unsigned ssaNum)
269     {
270         m_useDefSsaNum = ssaNum;
271     }
272
273     unsigned GetNumUses() const
274     {
275         return m_numUses;
276     }
277
278     void AddUse(BasicBlock* block)
279     {
280         if (block != m_block)
281         {
282             m_hasGlobalUse = true;
283         }
284
285         if (m_numUses < USHRT_MAX)
286         {
287             m_numUses++;
288         }
289     }
290
291     void AddPhiUse(BasicBlock* block)
292     {
293         m_hasPhiUse = true;
294         AddUse(block);
295     }
296
297     bool HasPhiUse() const
298     {
299         return m_hasPhiUse;
300     }
301
302     bool HasGlobalUse() const
303     {
304         return m_hasGlobalUse;
305     }
306
307     ValueNumPair m_vnPair;
308 };
309
310 // This class stores information associated with a memory SSA definition.
311 class SsaMemDef
312 {
313 public:
314     ValueNumPair m_vnPair;
315 };
316
317 //------------------------------------------------------------------------
318 // SsaDefArray: A resizable array of SSA definitions.
319 //
320 // Unlike an ordinary resizable array implementation, this allows only element
321 // addition (by calling AllocSsaNum) and has special handling for RESERVED_SSA_NUM
322 // (basically it's a 1-based array). The array doesn't impose any particular
323 // requirements on the elements it stores and AllocSsaNum forwards its arguments
324 // to the array element constructor, this way the array supports both LclSsaVarDsc
325 // and SsaMemDef elements.
326 //
327 template <typename T>
328 class SsaDefArray
329 {
330     T*       m_array;
331     unsigned m_arraySize;
332     unsigned m_count;
333
334     static_assert_no_msg(SsaConfig::RESERVED_SSA_NUM == 0);
335     static_assert_no_msg(SsaConfig::FIRST_SSA_NUM == 1);
336
337     // Get the minimum valid SSA number.
338     unsigned GetMinSsaNum() const
339     {
340         return SsaConfig::FIRST_SSA_NUM;
341     }
342
343     // Increase (double) the size of the array.
344     void GrowArray(CompAllocator alloc)
345     {
346         unsigned oldSize = m_arraySize;
347         unsigned newSize = max(2, oldSize * 2);
348
349         T* newArray = alloc.allocate<T>(newSize);
350
351         for (unsigned i = 0; i < oldSize; i++)
352         {
353             newArray[i] = m_array[i];
354         }
355
356         m_array     = newArray;
357         m_arraySize = newSize;
358     }
359
360 public:
361     // Construct an empty SsaDefArray.
362     SsaDefArray() : m_array(nullptr), m_arraySize(0), m_count(0)
363     {
364     }
365
366     // Reset the array (used only if the SSA form is reconstructed).
367     void Reset()
368     {
369         m_count = 0;
370     }
371
372     // Allocate a new SSA number (starting with SsaConfig::FIRST_SSA_NUM).
373     template <class... Args>
374     unsigned AllocSsaNum(CompAllocator alloc, Args&&... args)
375     {
376         if (m_count == m_arraySize)
377         {
378             GrowArray(alloc);
379         }
380
381         unsigned ssaNum    = GetMinSsaNum() + m_count;
382         m_array[m_count++] = T(std::forward<Args>(args)...);
383
384         // Ensure that the first SSA number we allocate is SsaConfig::FIRST_SSA_NUM
385         assert((ssaNum == SsaConfig::FIRST_SSA_NUM) || (m_count > 1));
386
387         return ssaNum;
388     }
389
390     // Get the number of SSA definitions in the array.
391     unsigned GetCount() const
392     {
393         return m_count;
394     }
395
396     // Get a pointer to the SSA definition at the specified index.
397     T* GetSsaDefByIndex(unsigned index) const
398     {
399         assert(index < m_count);
400         return &m_array[index];
401     }
402
403     // Check if the specified SSA number is valid.
404     bool IsValidSsaNum(unsigned ssaNum) const
405     {
406         return (GetMinSsaNum() <= ssaNum) && (ssaNum < (GetMinSsaNum() + m_count));
407     }
408
409     // Get a pointer to the SSA definition associated with the specified SSA number.
410     T* GetSsaDef(unsigned ssaNum) const
411     {
412         assert(ssaNum != SsaConfig::RESERVED_SSA_NUM);
413         return GetSsaDefByIndex(ssaNum - GetMinSsaNum());
414     }
415
416     // Get an SSA number associated with the specified SSA def (that must be in this array).
417     unsigned GetSsaNum(T* ssaDef) const
418     {
419         assert((m_array <= ssaDef) && (ssaDef < &m_array[m_count]));
420         return GetMinSsaNum() + static_cast<unsigned>(ssaDef - &m_array[0]);
421     }
422 };
423
424 enum RefCountState
425 {
426     RCS_INVALID, // not valid to get/set ref counts
427     RCS_EARLY,   // early counts for struct promotion and struct passing
428     RCS_NORMAL,  // normal ref counts (from lvaMarkRefs onward)
429 };
430
431 #ifdef DEBUG
432 // Reasons why we can't enregister a local.
433 enum class DoNotEnregisterReason
434 {
435     None,
436     AddrExposed,      // the address of this local is exposed.
437     DontEnregStructs, // struct enregistration is disabled.
438     NotRegSizeStruct, // the struct size does not much any register size, usually the struct size is too big.
439     LocalField,       // the local is accessed with LCL_FLD, note we can do it not only for struct locals.
440     VMNeedsStackAddr,
441     LiveInOutOfHandler, // the local is alive in and out of exception handler and not single def.
442     BlockOp,            // Is read or written via a block operation.
443     IsStructArg,        // Is a struct passed as an argument in a way that requires a stack location.
444     DepField,           // It is a field of a dependently promoted struct
445     NoRegVars,          // opts.compFlags & CLFLG_REGVAR is not set
446     MinOptsGC,          // It is a GC Ref and we are compiling MinOpts
447 #if !defined(TARGET_64BIT)
448     LongParamField, // It is a decomposed field of a long parameter.
449 #endif
450 #ifdef JIT32_GCENCODER
451     PinningRef,
452 #endif
453     LclAddrNode, // the local is accessed with LCL_ADDR_VAR/FLD.
454     CastTakesAddr,
455     StoreBlkSrc,          // the local is used as STORE_BLK source.
456     SwizzleArg,           // the local is passed using LCL_FLD as another type.
457     BlockOpRet,           // the struct is returned and it promoted or there is a cast.
458     ReturnSpCheck,        // the local is used to do SP check on return from function
459     CallSpCheck,          // the local is used to do SP check on every call
460     SimdUserForcesDep,    // a promoted struct was used by a SIMD/HWI node; it must be dependently promoted
461     HiddenBufferStructArg // the argument is a hidden return buffer passed to a method.
462 };
463
464 enum class AddressExposedReason
465 {
466     NONE,
467     PARENT_EXPOSED,                // This is a promoted field but the parent is exposed.
468     TOO_CONSERVATIVE,              // Were marked as exposed to be conservative, fix these places.
469     ESCAPE_ADDRESS,                // The address is escaping, for example, passed as call argument.
470     WIDE_INDIR,                    // We access via indirection with wider type.
471     OSR_EXPOSED,                   // It was exposed in the original method, osr has to repeat it.
472     STRESS_LCL_FLD,                // Stress mode replaces localVar with localFld and makes them addrExposed.
473     DISPATCH_RET_BUF,              // Caller return buffer dispatch.
474     STRESS_POISON_IMPLICIT_BYREFS, // This is an implicit byref we want to poison.
475     EXTERNALLY_VISIBLE_IMPLICITLY, // Local is visible externally without explicit escape in JIT IR.
476                                    // For example because it is used by GC or is the outgoing arg area
477                                    // that belongs to callees.
478 };
479
480 #endif // DEBUG
481
482 class LclVarDsc
483 {
484 public:
485     // The constructor. Most things can just be zero'ed.
486     //
487     // Initialize the ArgRegs to REG_STK.
488     // Morph will update if this local is passed in a register.
489     LclVarDsc()
490         : _lvArgReg(REG_STK)
491 #if FEATURE_MULTIREG_ARGS
492         , _lvOtherArgReg(REG_STK)
493 #endif // FEATURE_MULTIREG_ARGS
494         , lvClassHnd(NO_CLASS_HANDLE)
495         , lvPerSsaData()
496     {
497     }
498
499     // note this only packs because var_types is a typedef of unsigned char
500     var_types lvType : 5; // TYP_INT/LONG/FLOAT/DOUBLE/REF
501
502     unsigned char lvIsParam : 1;           // is this a parameter?
503     unsigned char lvIsRegArg : 1;          // is this an argument that was passed by register?
504     unsigned char lvFramePointerBased : 1; // 0 = off of REG_SPBASE (e.g., ESP), 1 = off of REG_FPBASE (e.g., EBP)
505
506     unsigned char lvOnFrame : 1;  // (part of) the variable lives on the frame
507     unsigned char lvRegister : 1; // assigned to live in a register? For RyuJIT backend, this is only set if the
508                                   // variable is in the same register for the entire function.
509     unsigned char lvTracked : 1;  // is this a tracked variable?
510     bool          lvTrackedNonStruct()
511     {
512         return lvTracked && lvType != TYP_STRUCT;
513     }
514 #ifdef DEBUG
515     unsigned char lvTrackedWithoutIndex : 1; // Tracked but has no lvVarIndex (i.e. only valid GTF_VAR_DEATH flags, used
516                                              // by physical promotion)
517 #endif
518     unsigned char lvPinned : 1; // is this a pinned variable?
519
520     unsigned char lvMustInit : 1; // must be initialized
521
522 private:
523     bool m_addrExposed : 1; // The address of this variable is "exposed" -- passed as an argument, stored in a
524                             // global location, etc.
525                             // We cannot reason reliably about the value of the variable.
526 public:
527     unsigned char lvDoNotEnregister : 1; // Do not enregister this variable.
528     unsigned char lvFieldAccessed : 1;   // The var is a struct local, and a field of the variable is accessed.  Affects
529                                          // struct promotion.
530     unsigned char lvLiveInOutOfHndlr : 1; // The variable is live in or out of an exception handler, and therefore must
531                                           // be on the stack (at least at those boundaries.)
532
533     unsigned char lvInSsa : 1;       // The variable is in SSA form (set by SsaBuilder)
534     unsigned char lvIsCSE : 1;       // Indicates if this LclVar is a CSE variable.
535     unsigned char lvHasLdAddrOp : 1; // has ldloca or ldarga opcode on this local.
536
537     unsigned char lvHasILStoreOp : 1;         // there is at least one STLOC or STARG on this local
538     unsigned char lvHasMultipleILStoreOp : 1; // there is more than one STLOC on this local
539
540     unsigned char lvIsTemp : 1; // Short-lifetime compiler temp
541
542 #if FEATURE_IMPLICIT_BYREFS
543     // Set if the argument is an implicit byref.
544     unsigned char lvIsImplicitByRef : 1;
545     // Set if the local appears as a last use that will be passed as an implicit byref.
546     unsigned char lvIsLastUseCopyOmissionCandidate : 1;
547 #endif // FEATURE_IMPLICIT_BYREFS
548
549 #if defined(TARGET_LOONGARCH64)
550     unsigned char lvIs4Field1 : 1; // Set if the 1st field is int or float within struct for LA-ABI64.
551     unsigned char lvIs4Field2 : 1; // Set if the 2nd field is int or float within struct for LA-ABI64.
552     unsigned char lvIsSplit : 1;   // Set if the argument is splited.
553 #endif                             // defined(TARGET_LOONGARCH64)
554
555 #if defined(TARGET_RISCV64)
556     unsigned char lvIs4Field1 : 1; // Set if the 1st field is int or float within struct for RISCV64.
557     unsigned char lvIs4Field2 : 1; // Set if the 2nd field is int or float within struct for RISCV64.
558     unsigned char lvIsSplit : 1;   // Set if the argument is splited.
559 #endif                             // defined(TARGET_RISCV64)
560
561     unsigned char lvIsBoolean : 1; // set if variable is boolean
562     unsigned char lvSingleDef : 1; // variable has a single def. Used to identify ref type locals that can get type
563                                    // updates
564
565     unsigned char lvSingleDefRegCandidate : 1; // variable has a single def and hence is a register candidate
566                                                // Currently, this is only used to decide if an EH variable can be
567                                                // a register candidate or not.
568
569     unsigned char lvDisqualifySingleDefRegCandidate : 1; // tracks variable that are disqualified from register
570                                                          // candidancy
571
572     unsigned char lvSpillAtSingleDef : 1; // variable has a single def (as determined by LSRA interval scan)
573                                           // and is spilled making it candidate to spill right after the
574                                           // first (and only) definition.
575                                           // Note: We cannot reuse lvSingleDefRegCandidate because it is set
576                                           // in earlier phase and the information might not be appropriate
577                                           // in LSRA.
578
579     unsigned char lvVolatileHint : 1; // hint for AssertionProp
580
581 #ifndef TARGET_64BIT
582     unsigned char lvStructDoubleAlign : 1; // Must we double align this struct?
583 #endif                                     // !TARGET_64BIT
584 #ifdef TARGET_64BIT
585     unsigned char lvQuirkToLong : 1; // Quirk to allocate this LclVar as a 64-bit long
586 #endif
587 #ifdef DEBUG
588     unsigned char lvKeepType : 1;       // Don't change the type of this variable
589     unsigned char lvNoLclFldStress : 1; // Can't apply local field stress on this one
590 #endif
591     unsigned char lvIsPtr : 1; // Might this be used in an address computation? (used by buffer overflow security
592                                // checks)
593     unsigned char lvIsUnsafeBuffer : 1; // Does this contain an unsafe buffer requiring buffer overflow security checks?
594     unsigned char lvPromoted : 1; // True when this local is a promoted struct, a normed struct, or a "split" long on a
595                                   // 32-bit target.  For implicit byref parameters, this gets hijacked between
596                                   // fgRetypeImplicitByRefArgs and fgMarkDemotedImplicitByRefArgs to indicate whether
597                                   // references to the arg are being rewritten as references to a promoted shadow local.
598     unsigned char lvIsStructField : 1; // Is this local var a field of a promoted struct local?
599     unsigned char lvContainsHoles : 1; // Is this a promoted struct whose fields do not cover the struct local?
600
601     // True for a promoted struct that has significant padding in it.
602     // Significant padding is any data in the struct that is not covered by a
603     // promoted field and that the EE told us we need to preserve on block
604     // copies/inits.
605     unsigned char lvAnySignificantPadding : 1;
606
607     unsigned char lvIsMultiRegArg : 1; // true if this is a multireg LclVar struct used in an argument context
608     unsigned char lvIsMultiRegRet : 1; // true if this is a multireg LclVar struct assigned from a multireg call
609
610 #ifdef DEBUG
611     unsigned char lvHiddenBufferStructArg : 1; // True when this struct (or its field) are passed as hidden buffer
612                                                // pointer.
613 #endif
614
615 #ifdef FEATURE_HFA_FIELDS_PRESENT
616     CorInfoHFAElemType _lvHfaElemKind : 3; // What kind of an HFA this is (CORINFO_HFA_ELEM_NONE if it is not an HFA).
617 #endif                                     // FEATURE_HFA_FIELDS_PRESENT
618
619 #ifdef DEBUG
620     // TODO-Cleanup: See the note on lvSize() - this flag is only in use by asserts that are checking for struct
621     // types, and is needed because of cases where TYP_STRUCT is bashed to an integral type.
622     // Consider cleaning this up so this workaround is not required.
623     unsigned char lvUnusedStruct : 1; // All references to this promoted struct are through its field locals.
624                                       // I.e. there is no longer any reference to the struct directly.
625                                       // In this case we can simply remove this struct local.
626
627     unsigned char lvUndoneStructPromotion : 1; // The struct promotion was undone and hence there should be no
628                                                // reference to the fields of this struct.
629 #endif
630
631     unsigned char lvLRACandidate : 1; // Tracked for linear scan register allocation purposes
632
633 #ifdef FEATURE_SIMD
634     unsigned char lvUsedInSIMDIntrinsic : 1; // This tells lclvar is used for simd intrinsic
635 #endif                                       // FEATURE_SIMD
636
637     unsigned char lvRegStruct : 1; // This is a reg-sized non-field-addressed struct.
638
639     unsigned char lvClassIsExact : 1; // lvClassHandle is the exact type
640
641 #ifdef DEBUG
642     unsigned char lvClassInfoUpdated : 1; // true if this var has updated class handle or exactness
643 #endif
644
645     unsigned char lvImplicitlyReferenced : 1; // true if there are non-IR references to this local (prolog, epilog, gc,
646                                               // eh)
647
648     unsigned char lvSuppressedZeroInit : 1; // local needs zero init if we transform tail call to loop
649
650     unsigned char lvHasExplicitInit : 1; // The local is explicitly initialized and doesn't need zero initialization in
651                                          // the prolog. If the local has gc pointers, there are no gc-safe points
652                                          // between the prolog and the explicit initialization.
653
654     unsigned char lvIsOSRLocal : 1; // Root method local in an OSR method. Any stack home will be on the Tier0 frame.
655                                     // Initial value will be defined by Tier0. Requires special handing in prolog.
656
657     unsigned char lvIsOSRExposedLocal : 1; // OSR local that was address exposed in Tier0
658
659     unsigned char lvRedefinedInEmbeddedStatement : 1; // Local has redefinitions inside embedded statements that
660                                                       // disqualify it from local copy prop.
661 private:
662     unsigned char lvIsNeverNegative : 1; // The local is known to be never negative
663
664 public:
665     union {
666         unsigned lvFieldLclStart; // The index of the local var representing the first field in the promoted struct
667                                   // local.  For implicit byref parameters, this gets hijacked between
668                                   // fgRetypeImplicitByRefArgs and fgMarkDemotedImplicitByRefArgs to point to the
669                                   // struct local created to model the parameter's struct promotion, if any.
670         unsigned lvParentLcl; // The index of the local var representing the parent (i.e. the promoted struct local).
671                               // Valid on promoted struct local fields.
672     };
673
674     unsigned char lvFieldCnt; //  Number of fields in the promoted VarDsc.
675     unsigned char lvFldOffset;
676     unsigned char lvFldOrdinal;
677
678 #ifdef DEBUG
679     unsigned char lvSingleDefDisqualifyReason = 'H';
680 #endif
681
682     unsigned char lvAllDefsAreNoGc : 1; // For pinned locals: true if all defs of this local are no-gc
683
684 #if FEATURE_MULTIREG_ARGS
685     regNumber lvRegNumForSlot(unsigned slotNum)
686     {
687         if (slotNum == 0)
688         {
689             return (regNumber)_lvArgReg;
690         }
691         else if (slotNum == 1)
692         {
693             return GetOtherArgReg();
694         }
695         else
696         {
697             assert(false && "Invalid slotNum!");
698         }
699
700         unreached();
701     }
702 #endif // FEATURE_MULTIREG_ARGS
703
704     CorInfoHFAElemType GetLvHfaElemKind() const
705     {
706 #ifdef FEATURE_HFA_FIELDS_PRESENT
707         return _lvHfaElemKind;
708 #else
709         NOWAY_MSG("GetLvHfaElemKind");
710         return CORINFO_HFA_ELEM_NONE;
711 #endif // FEATURE_HFA_FIELDS_PRESENT
712     }
713
714     void SetLvHfaElemKind(CorInfoHFAElemType elemKind)
715     {
716 #ifdef FEATURE_HFA_FIELDS_PRESENT
717         _lvHfaElemKind = elemKind;
718 #else
719         NOWAY_MSG("SetLvHfaElemKind");
720 #endif // FEATURE_HFA_FIELDS_PRESENT
721     }
722
723     bool lvIsHfa() const
724     {
725         if (GlobalJitOptions::compFeatureHfa)
726         {
727             return IsHfa(GetLvHfaElemKind());
728         }
729         else
730         {
731             return false;
732         }
733     }
734
735     bool lvIsHfaRegArg() const
736     {
737         if (GlobalJitOptions::compFeatureHfa)
738         {
739             return lvIsRegArg && lvIsHfa();
740         }
741         else
742         {
743             return false;
744         }
745     }
746
747     //------------------------------------------------------------------------------
748     // lvHfaSlots: Get the number of slots used by an HFA local
749     //
750     // Return Value:
751     //    On Arm64 - Returns 1-4 indicating the number of register slots used by the HFA
752     //    On Arm32 - Returns the total number of single FP register slots used by the HFA, max is 8
753     //
754     unsigned lvHfaSlots() const
755     {
756         assert(lvIsHfa());
757         assert(varTypeIsStruct(lvType));
758         unsigned slots = 0;
759 #ifdef TARGET_ARM
760         slots = lvExactSize() / sizeof(float);
761         assert(slots <= 8);
762 #elif defined(TARGET_ARM64)
763         switch (GetLvHfaElemKind())
764         {
765             case CORINFO_HFA_ELEM_NONE:
766                 assert(!"lvHfaSlots called for non-HFA");
767                 break;
768             case CORINFO_HFA_ELEM_FLOAT:
769                 assert((lvExactSize() % 4) == 0);
770                 slots = lvExactSize() >> 2;
771                 break;
772             case CORINFO_HFA_ELEM_DOUBLE:
773             case CORINFO_HFA_ELEM_VECTOR64:
774                 assert((lvExactSize() % 8) == 0);
775                 slots = lvExactSize() >> 3;
776                 break;
777             case CORINFO_HFA_ELEM_VECTOR128:
778                 assert((lvExactSize() % 16) == 0);
779                 slots = lvExactSize() >> 4;
780                 break;
781             default:
782                 unreached();
783         }
784         assert(slots <= 4);
785 #endif //  TARGET_ARM64
786         return slots;
787     }
788
789     // lvIsMultiRegArgOrRet()
790     //     returns true if this is a multireg LclVar struct used in an argument context
791     //               or if this is a multireg LclVar struct assigned from a multireg call
792     bool lvIsMultiRegArgOrRet()
793     {
794         return lvIsMultiRegArg || lvIsMultiRegRet;
795     }
796
797 #if defined(DEBUG)
798 private:
799     DoNotEnregisterReason m_doNotEnregReason;
800
801     AddressExposedReason m_addrExposedReason;
802
803 public:
804     void SetDoNotEnregReason(DoNotEnregisterReason reason)
805     {
806         m_doNotEnregReason = reason;
807     }
808
809     DoNotEnregisterReason GetDoNotEnregReason() const
810     {
811         return m_doNotEnregReason;
812     }
813
814     AddressExposedReason GetAddrExposedReason() const
815     {
816         return m_addrExposedReason;
817     }
818 #endif // DEBUG
819
820 public:
821     void SetAddressExposed(bool value DEBUGARG(AddressExposedReason reason))
822     {
823         m_addrExposed = value;
824         INDEBUG(m_addrExposedReason = reason);
825     }
826
827     void CleanAddressExposed()
828     {
829         m_addrExposed = false;
830     }
831
832     bool IsAddressExposed() const
833     {
834         return m_addrExposed;
835     }
836
837 #ifdef DEBUG
838     void SetHiddenBufferStructArg(char value)
839     {
840         lvHiddenBufferStructArg = value;
841     }
842
843     bool IsHiddenBufferStructArg() const
844     {
845         return lvHiddenBufferStructArg;
846     }
847 #endif
848
849 private:
850     regNumberSmall _lvRegNum; // Used to store the register this variable is in (or, the low register of a
851                               // register pair). It is set during codegen any time the
852                               // variable is enregistered (lvRegister is only set
853                               // to non-zero if the variable gets the same register assignment for its entire
854                               // lifetime).
855 #if !defined(TARGET_64BIT)
856     regNumberSmall _lvOtherReg; // Used for "upper half" of long var.
857 #endif                          // !defined(TARGET_64BIT)
858
859     regNumberSmall _lvArgReg; // The (first) register in which this argument is passed.
860
861 #if FEATURE_MULTIREG_ARGS
862     regNumberSmall _lvOtherArgReg; // Used for the second part of the struct passed in a register.
863                                    // Note this is defined but not used by ARM32
864 #endif                             // FEATURE_MULTIREG_ARGS
865
866     regNumberSmall _lvArgInitReg; // the register into which the argument is moved at entry
867
868 public:
869     // The register number is stored in a small format (8 bits), but the getters return and the setters take
870     // a full-size (unsigned) format, to localize the casts here.
871
872     /////////////////////
873
874     regNumber GetRegNum() const
875     {
876         return (regNumber)_lvRegNum;
877     }
878
879     void SetRegNum(regNumber reg)
880     {
881         _lvRegNum = (regNumberSmall)reg;
882         assert(_lvRegNum == reg);
883     }
884
885 /////////////////////
886
887 #if defined(TARGET_64BIT)
888
889     regNumber GetOtherReg() const
890     {
891         assert(!"shouldn't get here"); // can't use "unreached();" because it's NORETURN, which causes C4072
892                                        // "unreachable code" warnings
893         return REG_NA;
894     }
895
896     void SetOtherReg(regNumber reg)
897     {
898         assert(!"shouldn't get here"); // can't use "unreached();" because it's NORETURN, which causes C4072
899                                        // "unreachable code" warnings
900     }
901 #else  // !TARGET_64BIT
902
903     regNumber GetOtherReg() const
904     {
905         return (regNumber)_lvOtherReg;
906     }
907
908     void SetOtherReg(regNumber reg)
909     {
910         _lvOtherReg = (regNumberSmall)reg;
911         assert(_lvOtherReg == reg);
912     }
913 #endif // !TARGET_64BIT
914
915     /////////////////////
916
917     regNumber GetArgReg() const
918     {
919         return (regNumber)_lvArgReg;
920     }
921
922     void SetArgReg(regNumber reg)
923     {
924         _lvArgReg = (regNumberSmall)reg;
925         assert(_lvArgReg == reg);
926     }
927
928 #if FEATURE_MULTIREG_ARGS
929
930     regNumber GetOtherArgReg() const
931     {
932         return (regNumber)_lvOtherArgReg;
933     }
934
935     void SetOtherArgReg(regNumber reg)
936     {
937         _lvOtherArgReg = (regNumberSmall)reg;
938         assert(_lvOtherArgReg == reg);
939     }
940 #endif // FEATURE_MULTIREG_ARGS
941
942 #ifdef FEATURE_SIMD
943     // Is this is a SIMD struct which is used for SIMD intrinsic?
944     bool lvIsUsedInSIMDIntrinsic() const
945     {
946         return lvUsedInSIMDIntrinsic;
947     }
948 #else
949     bool lvIsUsedInSIMDIntrinsic() const
950     {
951         return false;
952     }
953 #endif
954
955     // Is this is local never negative?
956     bool IsNeverNegative() const
957     {
958         return lvIsNeverNegative;
959     }
960
961     // Is this is local never negative?
962     void SetIsNeverNegative(bool value)
963     {
964         lvIsNeverNegative = value;
965     }
966
967     /////////////////////
968
969     regNumber GetArgInitReg() const
970     {
971         return (regNumber)_lvArgInitReg;
972     }
973
974     void SetArgInitReg(regNumber reg)
975     {
976         _lvArgInitReg = (regNumberSmall)reg;
977         assert(_lvArgInitReg == reg);
978     }
979
980     /////////////////////
981
982     bool lvIsRegCandidate() const
983     {
984         return lvLRACandidate != 0;
985     }
986
987     bool lvIsInReg() const
988     {
989         return lvIsRegCandidate() && (GetRegNum() != REG_STK);
990     }
991
992     regMaskTP lvRegMask() const
993     {
994         regMaskTP regMask = RBM_NONE;
995         if (GetRegNum() != REG_STK)
996         {
997             if (varTypeUsesIntReg(this))
998             {
999                 regMask = genRegMask(GetRegNum());
1000             }
1001             else
1002             {
1003                 assert(varTypeUsesFloatReg(this));
1004                 regMask = genRegMaskFloat(GetRegNum() ARM_ARG(TypeGet()));
1005             }
1006         }
1007         return regMask;
1008     }
1009
1010     //-----------------------------------------------------------------------------
1011     // AllFieldDeathFlags: Get a bitset of flags that represents all fields dying.
1012     //
1013     // Returns:
1014     //    A bit mask that has GTF_VAR_FIELD_DEATH0 to GTF_VAR_FIELD_DEATH3 set,
1015     //    depending on how many fields this promoted local has.
1016     //
1017     // Remarks:
1018     //    Only usable for promoted locals.
1019     //
1020     GenTreeFlags AllFieldDeathFlags() const
1021     {
1022         assert(lvPromoted && (lvFieldCnt > 0) && (lvFieldCnt <= 4));
1023         GenTreeFlags flags = static_cast<GenTreeFlags>(((1 << lvFieldCnt) - 1) << FIELD_LAST_USE_SHIFT);
1024         assert((flags & ~GTF_VAR_DEATH_MASK) == 0);
1025         return flags;
1026     }
1027
1028     //-----------------------------------------------------------------------------
1029     // FullDeathFlags: Get a bitset of flags that represents this local fully dying.
1030     //
1031     // Returns:
1032     //    For promoted locals, this returns AllFieldDeathFlags(). Otherwise
1033     //    returns GTF_VAR_DEATH.
1034     //
1035     GenTreeFlags FullDeathFlags() const
1036     {
1037         return lvPromoted ? AllFieldDeathFlags() : GTF_VAR_DEATH;
1038     }
1039
1040     unsigned short lvVarIndex; // variable tracking index
1041
1042 private:
1043     unsigned short m_lvRefCnt; // unweighted (real) reference count.  For implicit by reference
1044                                // parameters, this gets hijacked from fgResetImplicitByRefRefCount
1045                                // through fgMarkDemotedImplicitByRefArgs, to provide a static
1046                                // appearance count (computed during address-exposed analysis)
1047                                // that fgMakeOutgoingStructArgCopy consults during global morph
1048                                // to determine if eliding its copy is legal.
1049
1050     weight_t m_lvRefCntWtd; // weighted reference count
1051
1052 public:
1053     unsigned short lvRefCnt(RefCountState state = RCS_NORMAL) const;
1054     void incLvRefCnt(unsigned short delta, RefCountState state = RCS_NORMAL);
1055     void setLvRefCnt(unsigned short newValue, RefCountState state = RCS_NORMAL);
1056     void incLvRefCntSaturating(unsigned short delta, RefCountState state = RCS_NORMAL);
1057
1058     weight_t lvRefCntWtd(RefCountState state = RCS_NORMAL) const;
1059     void incLvRefCntWtd(weight_t delta, RefCountState state = RCS_NORMAL);
1060     void setLvRefCntWtd(weight_t newValue, RefCountState state = RCS_NORMAL);
1061
1062 private:
1063     int lvStkOffs; // stack offset of home in bytes.
1064
1065 public:
1066     int GetStackOffset() const
1067     {
1068         return lvStkOffs;
1069     }
1070
1071     void SetStackOffset(int offset)
1072     {
1073         lvStkOffs = offset;
1074     }
1075
1076     unsigned lvExactSize() const;
1077     unsigned lvSize() const;
1078
1079     size_t lvArgStackSize() const;
1080
1081     unsigned lvSlotNum; // original slot # (if remapped)
1082
1083     // class handle for the local or null if not known or not a class
1084     CORINFO_CLASS_HANDLE lvClassHnd;
1085
1086 private:
1087     ClassLayout* m_layout; // layout info for structs
1088
1089 public:
1090     var_types TypeGet() const
1091     {
1092         return (var_types)lvType;
1093     }
1094     bool lvStackAligned() const
1095     {
1096         assert(lvIsStructField);
1097         return ((lvFldOffset % TARGET_POINTER_SIZE) == 0);
1098     }
1099
1100     // NormalizeOnLoad Rules:
1101     //     1. All small locals are actually TYP_INT locals.
1102     //     2. NOL locals are such that not all definitions can be controlled by the compiler and so the upper bits can
1103     //        be undefined.For parameters this is the case because of ABI.For struct fields - because of padding.For
1104     //        address - exposed locals - because not all stores are direct.
1105     //     3. Hence, all NOL uses(unless proven otherwise) are assumed in morph to have undefined upper bits and
1106     //        explicit casts have be inserted to "normalize" them back to conform to IL semantics.
1107     bool lvNormalizeOnLoad() const
1108     {
1109         return varTypeIsSmall(TypeGet()) &&
1110                // OSR exposed locals were normalize on load in the Tier0 frame so must be so for OSR too.
1111                (lvIsParam || m_addrExposed || lvIsStructField || lvIsOSRExposedLocal);
1112     }
1113
1114     bool lvNormalizeOnStore() const
1115     {
1116         return varTypeIsSmall(TypeGet()) &&
1117                // OSR exposed locals were normalize on load in the Tier0 frame so must be so for OSR too.
1118                !(lvIsParam || m_addrExposed || lvIsStructField || lvIsOSRExposedLocal);
1119     }
1120
1121     void incRefCnts(weight_t weight, Compiler* pComp, RefCountState state = RCS_NORMAL, bool propagate = true);
1122
1123     var_types GetHfaType() const
1124     {
1125         if (GlobalJitOptions::compFeatureHfa)
1126         {
1127             assert(lvIsHfa());
1128             return HfaTypeFromElemKind(GetLvHfaElemKind());
1129         }
1130         else
1131         {
1132             return TYP_UNDEF;
1133         }
1134     }
1135
1136     void SetHfaType(var_types type)
1137     {
1138         if (GlobalJitOptions::compFeatureHfa)
1139         {
1140             CorInfoHFAElemType elemKind = HfaElemKindFromType(type);
1141             SetLvHfaElemKind(elemKind);
1142             // Ensure we've allocated enough bits.
1143             assert(GetLvHfaElemKind() == elemKind);
1144         }
1145     }
1146
1147     // Returns true if this variable contains GC pointers (including being a GC pointer itself).
1148     bool HasGCPtr() const
1149     {
1150         return varTypeIsGC(lvType) || ((lvType == TYP_STRUCT) && m_layout->HasGCPtr());
1151     }
1152
1153     // Returns the layout of a struct variable or implicit byref.
1154     ClassLayout* GetLayout() const
1155     {
1156 #if FEATURE_IMPLICIT_BYREFS
1157         assert(varTypeIsStruct(TypeGet()) || (lvIsImplicitByRef && (TypeGet() == TYP_BYREF)));
1158 #else
1159         assert(varTypeIsStruct(TypeGet()));
1160 #endif
1161         return m_layout;
1162     }
1163
1164     // Sets the layout of a struct variable.
1165     void SetLayout(ClassLayout* layout)
1166     {
1167         assert(varTypeIsStruct(lvType));
1168         assert((m_layout == nullptr) || ClassLayout::AreCompatible(m_layout, layout));
1169         m_layout = layout;
1170     }
1171
1172     // Grow the size of a block layout local.
1173     void GrowBlockLayout(ClassLayout* layout)
1174     {
1175         assert(varTypeIsStruct(lvType));
1176         assert((m_layout == nullptr) || (m_layout->IsBlockLayout() && (m_layout->GetSize() <= layout->GetSize())));
1177         assert(layout->IsBlockLayout());
1178         m_layout = layout;
1179     }
1180
1181     SsaDefArray<LclSsaVarDsc> lvPerSsaData;
1182
1183     // True if ssaNum is a viable ssaNum for this local.
1184     bool IsValidSsaNum(unsigned ssaNum) const
1185     {
1186         return lvPerSsaData.IsValidSsaNum(ssaNum);
1187     }
1188
1189     // Returns the address of the per-Ssa data for the given ssaNum (which is required
1190     // not to be the SsaConfig::RESERVED_SSA_NUM, which indicates that the variable is
1191     // not an SSA variable).
1192     LclSsaVarDsc* GetPerSsaData(unsigned ssaNum) const
1193     {
1194         return lvPerSsaData.GetSsaDef(ssaNum);
1195     }
1196
1197     // Returns the SSA number for "ssaDef". Requires "ssaDef" to be a valid definition
1198     // of this variable.
1199     unsigned GetSsaNumForSsaDef(LclSsaVarDsc* ssaDef)
1200     {
1201         return lvPerSsaData.GetSsaNum(ssaDef);
1202     }
1203
1204     var_types GetRegisterType(const GenTreeLclVarCommon* tree) const;
1205
1206     var_types GetRegisterType() const;
1207
1208     var_types GetStackSlotHomeType() const;
1209
1210     bool IsEnregisterableType() const
1211     {
1212         return GetRegisterType() != TYP_UNDEF;
1213     }
1214
1215     bool IsEnregisterableLcl() const
1216     {
1217         if (lvDoNotEnregister)
1218         {
1219             return false;
1220         }
1221         return IsEnregisterableType();
1222     }
1223
1224     //-----------------------------------------------------------------------------
1225     //  IsAlwaysAliveInMemory: Determines if this variable's value is always
1226     //     up-to-date on stack. This is possible if this is an EH-var or
1227     //     we decided to spill after single-def.
1228     //
1229     bool IsAlwaysAliveInMemory() const
1230     {
1231         return lvLiveInOutOfHndlr || lvSpillAtSingleDef;
1232     }
1233
1234     bool CanBeReplacedWithItsField(Compiler* comp) const;
1235
1236 #ifdef DEBUG
1237 public:
1238     const char* lvReason;
1239
1240     void PrintVarReg() const
1241     {
1242         printf("%s", getRegName(GetRegNum()));
1243     }
1244 #endif // DEBUG
1245
1246 }; // class LclVarDsc
1247
1248 enum class SymbolicIntegerValue : int32_t
1249 {
1250     LongMin,
1251     IntMin,
1252     ShortMin,
1253     ByteMin,
1254     Zero,
1255     One,
1256     ByteMax,
1257     UByteMax,
1258     ShortMax,
1259     UShortMax,
1260     ArrayLenMax,
1261     IntMax,
1262     UIntMax,
1263     LongMax,
1264 };
1265
1266 inline constexpr bool operator>(SymbolicIntegerValue left, SymbolicIntegerValue right)
1267 {
1268     return static_cast<int32_t>(left) > static_cast<int32_t>(right);
1269 }
1270
1271 inline constexpr bool operator>=(SymbolicIntegerValue left, SymbolicIntegerValue right)
1272 {
1273     return static_cast<int32_t>(left) >= static_cast<int32_t>(right);
1274 }
1275
1276 inline constexpr bool operator<(SymbolicIntegerValue left, SymbolicIntegerValue right)
1277 {
1278     return static_cast<int32_t>(left) < static_cast<int32_t>(right);
1279 }
1280
1281 inline constexpr bool operator<=(SymbolicIntegerValue left, SymbolicIntegerValue right)
1282 {
1283     return static_cast<int32_t>(left) <= static_cast<int32_t>(right);
1284 }
1285
1286 // Represents an integral range useful for reasoning about integral casts.
1287 // It uses a symbolic representation for lower and upper bounds so
1288 // that it can efficiently handle integers of all sizes on all hosts.
1289 //
1290 // Note that the ranges represented by this class are **always** in the
1291 // "signed" domain. This is so that if we know the range a node produces, it
1292 // can be trivially used to determine if a cast above the node does or does not
1293 // overflow, which requires that the interpretation of integers be the same both
1294 // for the "input" and "output". We choose signed interpretation here because it
1295 // produces nice continuous ranges and because IR uses sign-extension for constants.
1296 //
1297 // Some examples of how ranges are computed for casts:
1298 // 1. CAST_OVF(ubyte <- uint): does not overflow for [0..UBYTE_MAX], produces the
1299 //    same range - all casts that do not change the representation, i. e. have the same
1300 //    "actual" input and output type, have the same "input" and "output" range.
1301 // 2. CAST_OVF(ulong <- uint): never overflows => the "input" range is [INT_MIN..INT_MAX]
1302 //    (aka all possible 32 bit integers). Produces [0..UINT_MAX] (aka all possible 32
1303 //    bit integers zero-extended to 64 bits).
1304 // 3. CAST_OVF(int <- uint): overflows for inputs larger than INT_MAX <=> less than 0
1305 //    when interpreting as signed => the "input" range is [0..INT_MAX], the same range
1306 //    being the produced one as the node does not change the width of the integer.
1307 //
1308 class IntegralRange
1309 {
1310 private:
1311     SymbolicIntegerValue m_lowerBound;
1312     SymbolicIntegerValue m_upperBound;
1313
1314 public:
1315     IntegralRange() = default;
1316
1317     IntegralRange(SymbolicIntegerValue lowerBound, SymbolicIntegerValue upperBound)
1318         : m_lowerBound(lowerBound), m_upperBound(upperBound)
1319     {
1320         assert(lowerBound <= upperBound);
1321     }
1322
1323     SymbolicIntegerValue GetLowerBound() const
1324     {
1325         return m_lowerBound;
1326     }
1327
1328     SymbolicIntegerValue GetUpperBound() const
1329     {
1330         return m_upperBound;
1331     }
1332
1333     bool Contains(int64_t value) const;
1334
1335     bool Contains(IntegralRange other) const
1336     {
1337         return (m_lowerBound <= other.m_lowerBound) && (other.m_upperBound <= m_upperBound);
1338     }
1339
1340     bool IsNonNegative() const
1341     {
1342         return m_lowerBound >= SymbolicIntegerValue::Zero;
1343     }
1344
1345     bool Equals(IntegralRange other) const
1346     {
1347         return (m_lowerBound == other.m_lowerBound) && (m_upperBound == other.m_upperBound);
1348     }
1349
1350     static int64_t SymbolicToRealValue(SymbolicIntegerValue value);
1351     static SymbolicIntegerValue LowerBoundForType(var_types type);
1352     static SymbolicIntegerValue UpperBoundForType(var_types type);
1353
1354     static IntegralRange ForType(var_types type)
1355     {
1356         return {LowerBoundForType(type), UpperBoundForType(type)};
1357     }
1358
1359     static IntegralRange ForNode(GenTree* node, Compiler* compiler);
1360     static IntegralRange ForCastInput(GenTreeCast* cast);
1361     static IntegralRange ForCastOutput(GenTreeCast* cast, Compiler* compiler);
1362     static IntegralRange Union(IntegralRange range1, IntegralRange range2);
1363
1364 #ifdef DEBUG
1365     static void Print(IntegralRange range);
1366 #endif // DEBUG
1367 };
1368
1369 /*
1370 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1371 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1372 XX                                                                           XX
1373 XX                           TempsInfo                                       XX
1374 XX                                                                           XX
1375 XX  The temporary lclVars allocated by the compiler for code generation      XX
1376 XX                                                                           XX
1377 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1378 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1379 */
1380
1381 /*****************************************************************************
1382  *
1383  *  The following keeps track of temporaries allocated in the stack frame
1384  *  during code-generation (after register allocation). These spill-temps are
1385  *  only used if we run out of registers while evaluating a tree.
1386  *
1387  *  These are different from the more common temps allocated by lvaGrabTemp().
1388  */
1389
1390 class TempDsc
1391 {
1392 public:
1393     TempDsc* tdNext;
1394
1395 private:
1396     int tdOffs;
1397 #ifdef DEBUG
1398     static const int BAD_TEMP_OFFSET = 0xDDDDDDDD; // used as a sentinel "bad value" for tdOffs in DEBUG
1399 #endif                                             // DEBUG
1400
1401     int       tdNum;
1402     BYTE      tdSize;
1403     var_types tdType;
1404
1405 public:
1406     TempDsc(int _tdNum, unsigned _tdSize, var_types _tdType) : tdNum(_tdNum), tdSize((BYTE)_tdSize), tdType(_tdType)
1407     {
1408 #ifdef DEBUG
1409         // temps must have a negative number (so they have a different number from all local variables)
1410         assert(tdNum < 0);
1411         tdOffs = BAD_TEMP_OFFSET;
1412 #endif // DEBUG
1413         if (tdNum != _tdNum)
1414         {
1415             IMPL_LIMITATION("too many spill temps");
1416         }
1417     }
1418
1419 #ifdef DEBUG
1420     bool tdLegalOffset() const
1421     {
1422         return tdOffs != BAD_TEMP_OFFSET;
1423     }
1424 #endif // DEBUG
1425
1426     int tdTempOffs() const
1427     {
1428         assert(tdLegalOffset());
1429         return tdOffs;
1430     }
1431     void tdSetTempOffs(int offs)
1432     {
1433         tdOffs = offs;
1434         assert(tdLegalOffset());
1435     }
1436     void tdAdjustTempOffs(int offs)
1437     {
1438         tdOffs += offs;
1439         assert(tdLegalOffset());
1440     }
1441
1442     int tdTempNum() const
1443     {
1444         assert(tdNum < 0);
1445         return tdNum;
1446     }
1447     unsigned tdTempSize() const
1448     {
1449         return tdSize;
1450     }
1451     var_types tdTempType() const
1452     {
1453         return tdType;
1454     }
1455 };
1456
1457 // Specify compiler data that a phase might modify
1458 enum class PhaseStatus : unsigned
1459 {
1460     MODIFIED_NOTHING,    // Phase did not make any changes that warrant running post-phase checks or dumping
1461                          // the main jit data strutures.
1462     MODIFIED_EVERYTHING, // Phase made changes that warrant running post-phase checks or dumping
1463                          // the main jit data strutures.
1464 };
1465
1466 // interface to hide linearscan implementation from rest of compiler
1467 class LinearScanInterface
1468 {
1469 public:
1470     virtual PhaseStatus doLinearScan()                         = 0;
1471     virtual void recordVarLocationsAtStartOfBB(BasicBlock* bb) = 0;
1472     virtual bool willEnregisterLocalVars() const               = 0;
1473 #if TRACK_LSRA_STATS
1474     virtual void dumpLsraStatsCsv(FILE* file)     = 0;
1475     virtual void dumpLsraStatsSummary(FILE* file) = 0;
1476 #endif // TRACK_LSRA_STATS
1477 };
1478
1479 LinearScanInterface* getLinearScanAllocator(Compiler* comp);
1480
1481 // This enumeration names the phases into which we divide compilation.  The phases should completely
1482 // partition a compilation.
1483 enum Phases
1484 {
1485 #define CompPhaseNameMacro(enum_nm, string_nm, hasChildren, parent, measureIR) enum_nm,
1486 #include "compphases.h"
1487     PHASE_NUMBER_OF
1488 };
1489
1490 extern const char* PhaseNames[];
1491 extern const char* PhaseEnums[];
1492
1493 // Specify which checks should be run after each phase
1494 //
1495 // clang-format off
1496 enum class PhaseChecks : unsigned int
1497 {
1498     CHECK_NONE          = 0,
1499     CHECK_IR            = 1 << 0, // ir flags, etc
1500     CHECK_UNIQUE        = 1 << 1, // tree node uniqueness
1501     CHECK_FG            = 1 << 2, // flow graph integrity
1502     CHECK_EH            = 1 << 3, // eh table integrity
1503     CHECK_LOOPS         = 1 << 4, // loop table integrity
1504     CHECK_PROFILE       = 1 << 5, // profile data integrity
1505     CHECK_LINKED_LOCALS = 1 << 6, // check linked list of locals
1506 };
1507
1508 inline constexpr PhaseChecks operator ~(PhaseChecks a)
1509 {
1510     return (PhaseChecks)(~(unsigned int)a);
1511 }
1512
1513 inline constexpr PhaseChecks operator |(PhaseChecks a, PhaseChecks b)
1514 {
1515     return (PhaseChecks)((unsigned int)a | (unsigned int)b);
1516 }
1517
1518 inline constexpr PhaseChecks operator &(PhaseChecks a, PhaseChecks b)
1519 {
1520     return (PhaseChecks)((unsigned int)a & (unsigned int)b);
1521 }
1522
1523 inline PhaseChecks& operator |=(PhaseChecks& a, PhaseChecks b)
1524 {
1525     return a = (PhaseChecks)((unsigned int)a | (unsigned int)b);
1526 }
1527
1528 inline PhaseChecks& operator &=(PhaseChecks& a, PhaseChecks b)
1529 {
1530     return a = (PhaseChecks)((unsigned int)a & (unsigned int)b);
1531 }
1532
1533 inline PhaseChecks& operator ^=(PhaseChecks& a, PhaseChecks b)
1534 {
1535     return a = (PhaseChecks)((unsigned int)a ^ (unsigned int)b);
1536 }
1537 // clang-format on
1538
1539 // Specify which dumps should be run after each phase
1540 //
1541 enum class PhaseDumps
1542 {
1543     DUMP_NONE,
1544     DUMP_ALL
1545 };
1546
1547 // The following enum provides a simple 1:1 mapping to CLR API's
1548 enum API_ICorJitInfo_Names
1549 {
1550 #define DEF_CLR_API(name) API_##name,
1551 #include "ICorJitInfo_names_generated.h"
1552     API_COUNT
1553 };
1554
1555 enum class FlowGraphUpdates
1556 {
1557     COMPUTE_BASICS  = 0,      // renumber blocks, reachability, etc
1558     COMPUTE_DOMS    = 1 << 0, // recompute dominators
1559     COMPUTE_RETURNS = 1 << 1, // recompute return blocks
1560     COMPUTE_LOOPS   = 1 << 2, // recompute loop table
1561 };
1562
1563 inline constexpr FlowGraphUpdates operator|(FlowGraphUpdates a, FlowGraphUpdates b)
1564 {
1565     return (FlowGraphUpdates)((unsigned int)a | (unsigned int)b);
1566 }
1567
1568 inline constexpr FlowGraphUpdates operator&(FlowGraphUpdates a, FlowGraphUpdates b)
1569 {
1570     return (FlowGraphUpdates)((unsigned int)a & (unsigned int)b);
1571 }
1572
1573 // Profile checking options
1574 //
1575 // clang-format off
1576 enum class ProfileChecks : unsigned int
1577 {
1578     CHECK_NONE          = 0,
1579     CHECK_CLASSIC       = 1 << 0, // check "classic" jit weights
1580     CHECK_LIKELY        = 1 << 1, // check likelihood based weights
1581     RAISE_ASSERT        = 1 << 2, // assert on check failure
1582     CHECK_ALL_BLOCKS    = 1 << 3, // check blocks even if bbHasProfileWeight is false
1583 };
1584
1585 inline constexpr ProfileChecks operator ~(ProfileChecks a)
1586 {
1587     return (ProfileChecks)(~(unsigned int)a);
1588 }
1589
1590 inline constexpr ProfileChecks operator |(ProfileChecks a, ProfileChecks b)
1591 {
1592     return (ProfileChecks)((unsigned int)a | (unsigned int)b);
1593 }
1594
1595 inline constexpr ProfileChecks operator &(ProfileChecks a, ProfileChecks b)
1596 {
1597     return (ProfileChecks)((unsigned int)a & (unsigned int)b);
1598 }
1599
1600 inline ProfileChecks& operator |=(ProfileChecks& a, ProfileChecks b)
1601 {
1602     return a = (ProfileChecks)((unsigned int)a | (unsigned int)b);
1603 }
1604
1605 inline ProfileChecks& operator &=(ProfileChecks& a, ProfileChecks b)
1606 {
1607     return a = (ProfileChecks)((unsigned int)a & (unsigned int)b);
1608 }
1609
1610 inline ProfileChecks& operator ^=(ProfileChecks& a, ProfileChecks b)
1611 {
1612     return a = (ProfileChecks)((unsigned int)a ^ (unsigned int)b);
1613 }
1614
1615 inline bool hasFlag(const ProfileChecks& flagSet, const ProfileChecks& flag)
1616 {
1617     return ((flagSet & flag) == flag);
1618 }
1619
1620 //---------------------------------------------------------------
1621 // Compilation time.
1622 //
1623
1624 // A "CompTimeInfo" is a structure for tracking the compilation time of one or more methods.
1625 // We divide a compilation into a sequence of contiguous phases, and track the total (per-thread) cycles
1626 // of the compilation, as well as the cycles for each phase.  We also track the number of bytecodes.
1627 // If there is a failure in reading a timer at any point, the "CompTimeInfo" becomes invalid, as indicated
1628 // by "m_timerFailure" being true.
1629 // If FEATURE_JIT_METHOD_PERF is not set, we define a minimal form of this, enough to let other code compile.
1630 struct CompTimeInfo
1631 {
1632 #ifdef FEATURE_JIT_METHOD_PERF
1633     // The string names of the phases.
1634     static const char* PhaseNames[];
1635
1636     static bool PhaseHasChildren[];
1637     static int  PhaseParent[];
1638     static bool PhaseReportsIRSize[];
1639
1640     unsigned         m_byteCodeBytes;
1641     unsigned __int64 m_totalCycles;
1642     unsigned __int64 m_invokesByPhase[PHASE_NUMBER_OF];
1643     unsigned __int64 m_cyclesByPhase[PHASE_NUMBER_OF];
1644 #if MEASURE_CLRAPI_CALLS
1645     unsigned __int64 m_CLRinvokesByPhase[PHASE_NUMBER_OF];
1646     unsigned __int64 m_CLRcyclesByPhase[PHASE_NUMBER_OF];
1647 #endif
1648
1649     unsigned m_nodeCountAfterPhase[PHASE_NUMBER_OF];
1650
1651     // For better documentation, we call EndPhase on
1652     // non-leaf phases.  We should also call EndPhase on the
1653     // last leaf subphase; obviously, the elapsed cycles between the EndPhase
1654     // for the last leaf subphase and the EndPhase for an ancestor should be very small.
1655     // We add all such "redundant end phase" intervals to this variable below; we print
1656     // it out in a report, so we can verify that it is, indeed, very small.  If it ever
1657     // isn't, this means that we're doing something significant between the end of the last
1658     // declared subphase and the end of its parent.
1659     unsigned __int64 m_parentPhaseEndSlop;
1660     bool             m_timerFailure;
1661
1662 #if MEASURE_CLRAPI_CALLS
1663     // The following measures the time spent inside each individual CLR API call.
1664     unsigned         m_allClrAPIcalls;
1665     unsigned         m_perClrAPIcalls[API_ICorJitInfo_Names::API_COUNT];
1666     unsigned __int64 m_allClrAPIcycles;
1667     unsigned __int64 m_perClrAPIcycles[API_ICorJitInfo_Names::API_COUNT];
1668     unsigned __int32 m_maxClrAPIcycles[API_ICorJitInfo_Names::API_COUNT];
1669 #endif // MEASURE_CLRAPI_CALLS
1670
1671     CompTimeInfo(unsigned byteCodeBytes);
1672 #endif
1673 };
1674
1675 #ifdef FEATURE_JIT_METHOD_PERF
1676
1677 #if MEASURE_CLRAPI_CALLS
1678 struct WrapICorJitInfo;
1679 #endif
1680
1681 // This class summarizes the JIT time information over the course of a run: the number of methods compiled,
1682 // and the total and maximum timings.  (These are instances of the "CompTimeInfo" type described above).
1683 // The operation of adding a single method's timing to the summary may be performed concurrently by several
1684 // threads, so it is protected by a lock.
1685 // This class is intended to be used as a singleton type, with only a single instance.
1686 class CompTimeSummaryInfo
1687 {
1688     // This lock protects the fields of all CompTimeSummaryInfo(s) (of which we expect there to be one).
1689     static CritSecObject s_compTimeSummaryLock;
1690
1691     int          m_numMethods;
1692     int          m_totMethods;
1693     CompTimeInfo m_total;
1694     CompTimeInfo m_maximum;
1695
1696     int          m_numFilteredMethods;
1697     CompTimeInfo m_filtered;
1698
1699     // This can use what ever data you want to determine if the value to be added
1700     // belongs in the filtered section (it's always included in the unfiltered section)
1701     bool IncludedInFilteredData(CompTimeInfo& info);
1702
1703 public:
1704     // This is the unique CompTimeSummaryInfo object for this instance of the runtime.
1705     static CompTimeSummaryInfo s_compTimeSummary;
1706
1707     CompTimeSummaryInfo()
1708         : m_numMethods(0), m_totMethods(0), m_total(0), m_maximum(0), m_numFilteredMethods(0), m_filtered(0)
1709     {
1710     }
1711
1712     // Assumes that "info" is a completed CompTimeInfo for a compilation; adds it to the summary.
1713     // This is thread safe.
1714     void AddInfo(CompTimeInfo& info, bool includePhases);
1715
1716     // Print the summary information to "f".
1717     // This is not thread-safe; assumed to be called by only one thread.
1718     void Print(FILE* f);
1719 };
1720
1721 // A JitTimer encapsulates a CompTimeInfo for a single compilation. It also tracks the start of compilation,
1722 // and when the current phase started.  This is intended to be part of a Compilation object.
1723 //
1724 class JitTimer
1725 {
1726     unsigned __int64 m_start;         // Start of the compilation.
1727     unsigned __int64 m_curPhaseStart; // Start of the current phase.
1728 #if MEASURE_CLRAPI_CALLS
1729     unsigned __int64 m_CLRcallStart;   // Start of the current CLR API call (if any).
1730     unsigned __int64 m_CLRcallInvokes; // CLR API invokes under current outer so far
1731     unsigned __int64 m_CLRcallCycles;  // CLR API  cycles under current outer so far.
1732     int              m_CLRcallAPInum;  // The enum/index of the current CLR API call (or -1).
1733     static double    s_cyclesPerSec;   // Cached for speedier measurements
1734 #endif
1735 #ifdef DEBUG
1736     Phases m_lastPhase; // The last phase that was completed (or (Phases)-1 to start).
1737 #endif
1738     CompTimeInfo m_info; // The CompTimeInfo for this compilation.
1739
1740     static CritSecObject s_csvLock; // Lock to protect the time log file.
1741     static FILE*         s_csvFile; // The time log file handle.
1742     void PrintCsvMethodStats(Compiler* comp);
1743
1744 private:
1745     void* operator new(size_t);
1746     void* operator new[](size_t);
1747     void operator delete(void*);
1748     void operator delete[](void*);
1749
1750 public:
1751     // Initialized the timer instance
1752     JitTimer(unsigned byteCodeSize);
1753
1754     static JitTimer* Create(Compiler* comp, unsigned byteCodeSize)
1755     {
1756         return ::new (comp, CMK_Unknown) JitTimer(byteCodeSize);
1757     }
1758
1759     static void PrintCsvHeader();
1760
1761     // Ends the current phase (argument is for a redundant check).
1762     void EndPhase(Compiler* compiler, Phases phase);
1763
1764 #if MEASURE_CLRAPI_CALLS
1765     // Start and end a timed CLR API call.
1766     void CLRApiCallEnter(unsigned apix);
1767     void CLRApiCallLeave(unsigned apix);
1768 #endif // MEASURE_CLRAPI_CALLS
1769
1770     // Completes the timing of the current method, which is assumed to have "byteCodeBytes" bytes of bytecode,
1771     // and adds it to "sum".
1772     void Terminate(Compiler* comp, CompTimeSummaryInfo& sum, bool includePhases);
1773
1774     // Attempts to query the cycle counter of the current thread.  If successful, returns "true" and sets
1775     // *cycles to the cycle counter value.  Otherwise, returns false and sets the "m_timerFailure" flag of
1776     // "m_info" to true.
1777     bool GetThreadCycles(unsigned __int64* cycles)
1778     {
1779         bool res = CycleTimer::GetThreadCyclesS(cycles);
1780         if (!res)
1781         {
1782             m_info.m_timerFailure = true;
1783         }
1784         return res;
1785     }
1786
1787     static void Shutdown();
1788 };
1789 #endif // FEATURE_JIT_METHOD_PERF
1790
1791 //------------------- Function/Funclet info -------------------------------
1792 enum FuncKind : BYTE
1793 {
1794     FUNC_ROOT,    // The main/root function (always id==0)
1795     FUNC_HANDLER, // a funclet associated with an EH handler (finally, fault, catch, filter handler)
1796     FUNC_FILTER,  // a funclet associated with an EH filter
1797     FUNC_COUNT
1798 };
1799
1800 class emitLocation;
1801
1802 struct FuncInfoDsc
1803 {
1804     FuncKind       funKind;
1805     BYTE           funFlags;   // Currently unused, just here for padding
1806     unsigned short funEHIndex; // index, into the ebd table, of innermost EH clause corresponding to this
1807                                // funclet. It is only valid if funKind field indicates this is a
1808                                // EH-related funclet: FUNC_HANDLER or FUNC_FILTER
1809
1810 #if defined(TARGET_AMD64)
1811
1812     // TODO-AMD64-Throughput: make the AMD64 info more like the ARM info to avoid having this large static array.
1813     emitLocation* startLoc;
1814     emitLocation* endLoc;
1815     emitLocation* coldStartLoc; // locations for the cold section, if there is one.
1816     emitLocation* coldEndLoc;
1817     UNWIND_INFO   unwindHeader;
1818     // Maximum of 255 UNWIND_CODE 'nodes' and then the unwind header. If there are an odd
1819     // number of codes, the VM or Zapper will 4-byte align the whole thing.
1820     BYTE     unwindCodes[offsetof(UNWIND_INFO, UnwindCode) + (0xFF * sizeof(UNWIND_CODE))];
1821     unsigned unwindCodeSlot;
1822
1823 #elif defined(TARGET_X86)
1824
1825     emitLocation* startLoc;
1826     emitLocation* endLoc;
1827     emitLocation* coldStartLoc; // locations for the cold section, if there is one.
1828     emitLocation* coldEndLoc;
1829
1830 #elif defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
1831
1832     UnwindInfo  uwi;     // Unwind information for this function/funclet's hot  section
1833     UnwindInfo* uwiCold; // Unwind information for this function/funclet's cold section
1834                          //   Note: we only have a pointer here instead of the actual object,
1835                          //   to save memory in the JIT case (compared to the NGEN case),
1836                          //   where we don't have any cold section.
1837                          //   Note 2: we currently don't support hot/cold splitting in functions
1838                          //   with EH, so uwiCold will be NULL for all funclets.
1839
1840     emitLocation* startLoc;
1841     emitLocation* endLoc;
1842     emitLocation* coldStartLoc; // locations for the cold section, if there is one.
1843     emitLocation* coldEndLoc;
1844
1845 #endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64
1846
1847 #if defined(FEATURE_CFI_SUPPORT)
1848     jitstd::vector<CFI_CODE>* cfiCodes;
1849 #endif // FEATURE_CFI_SUPPORT
1850
1851     // Eventually we may want to move rsModifiedRegsMask, lvaOutgoingArgSize, and anything else
1852     // that isn't shared between the main function body and funclets.
1853 };
1854
1855 struct TempInfo
1856 {
1857     GenTree* store;
1858     GenTree* load;
1859 };
1860
1861 #ifdef DEBUG
1862 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1863 // We have the ability to mark source expressions with "Test Labels."
1864 // These drive assertions within the JIT, or internal JIT testing.  For example, we could label expressions
1865 // that should be CSE defs, and other expressions that should uses of those defs, with a shared label.
1866
1867 enum TestLabel // This must be kept identical to System.Runtime.CompilerServices.JitTestLabel.TestLabel.
1868 {
1869     TL_SsaName,
1870     TL_VN,        // Defines a "VN equivalence class".  (For full VN, including exceptions thrown).
1871     TL_VNNorm,    // Like above, but uses the non-exceptional value of the expression.
1872     TL_CSE_Def,   //  This must be identified in the JIT as a CSE def
1873     TL_CSE_Use,   //  This must be identified in the JIT as a CSE use
1874     TL_LoopHoist, // Expression must (or must not) be hoisted out of the loop.
1875 };
1876
1877 struct TestLabelAndNum
1878 {
1879     TestLabel m_tl;
1880     ssize_t   m_num;
1881
1882     TestLabelAndNum() : m_tl(TestLabel(0)), m_num(0)
1883     {
1884     }
1885 };
1886
1887 typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, TestLabelAndNum> NodeToTestDataMap;
1888
1889 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1890 #endif // DEBUG
1891
1892 //-------------------------------------------------------------------------
1893 // LoopFlags: flags for the loop table.
1894 //
1895 enum LoopFlags : unsigned short
1896 {
1897     LPFLG_EMPTY = 0,
1898
1899     // LPFLG_UNUSED  = 0x0001,
1900     // LPFLG_UNUSED  = 0x0002,
1901     LPFLG_ITER = 0x0004, // loop of form: for (i = icon or expression; test_condition(); i++)
1902     // LPFLG_UNUSED    = 0x0008,
1903
1904     LPFLG_CONTAINS_CALL = 0x0010, // If executing the loop body *may* execute a call
1905     // LPFLG_UNUSED     = 0x0020,
1906     LPFLG_CONST_INIT = 0x0040, // iterator is initialized with a constant (found in lpConstInit)
1907     LPFLG_SIMD_LIMIT = 0x0080, // iterator is compared with vector element count (found in lpConstLimit)
1908
1909     LPFLG_VAR_LIMIT    = 0x0100, // iterator is compared with a local var (var # found in lpVarLimit)
1910     LPFLG_CONST_LIMIT  = 0x0200, // iterator is compared with a constant (found in lpConstLimit)
1911     LPFLG_ARRLEN_LIMIT = 0x0400, // iterator is compared with a.len or a[i].len (found in lpArrLenLimit)
1912     LPFLG_HAS_PREHEAD  = 0x0800, // lpHead is known to be a preHead for this loop
1913
1914     LPFLG_REMOVED     = 0x1000, // has been removed from the loop table (unrolled or optimized away)
1915     LPFLG_DONT_UNROLL = 0x2000, // do not unroll this loop
1916     LPFLG_ASGVARS_YES = 0x4000, // "lpAsgVars" has been computed
1917     LPFLG_ASGVARS_INC = 0x8000, // "lpAsgVars" is incomplete -- vars beyond those representable in an AllVarSet
1918                                 // type are assigned to.
1919 };
1920
1921 inline constexpr LoopFlags operator~(LoopFlags a)
1922 {
1923     return (LoopFlags)(~(unsigned short)a);
1924 }
1925
1926 inline constexpr LoopFlags operator|(LoopFlags a, LoopFlags b)
1927 {
1928     return (LoopFlags)((unsigned short)a | (unsigned short)b);
1929 }
1930
1931 inline constexpr LoopFlags operator&(LoopFlags a, LoopFlags b)
1932 {
1933     return (LoopFlags)((unsigned short)a & (unsigned short)b);
1934 }
1935
1936 inline LoopFlags& operator|=(LoopFlags& a, LoopFlags b)
1937 {
1938     return a = (LoopFlags)((unsigned short)a | (unsigned short)b);
1939 }
1940
1941 inline LoopFlags& operator&=(LoopFlags& a, LoopFlags b)
1942 {
1943     return a = (LoopFlags)((unsigned short)a & (unsigned short)b);
1944 }
1945
1946 //  The following holds information about instr offsets in terms of generated code.
1947
1948 enum class IPmappingDscKind
1949 {
1950     Prolog,    // The mapping represents the start of a prolog.
1951     Epilog,    // The mapping represents the start of an epilog.
1952     NoMapping, // This does not map to any IL offset.
1953     Normal,    // The mapping maps to an IL offset.
1954 };
1955
1956 struct IPmappingDsc
1957 {
1958     emitLocation     ipmdNativeLoc; // the emitter location of the native code corresponding to the IL offset
1959     IPmappingDscKind ipmdKind;      // The kind of mapping
1960     ILLocation       ipmdLoc;       // The location for normal mappings
1961     bool             ipmdIsLabel;   // Can this code be a branch label?
1962 };
1963
1964 struct RichIPMapping
1965 {
1966     emitLocation nativeLoc;
1967     DebugInfo    debugInfo;
1968 };
1969
1970 // Current kind of node threading stored in GenTree::gtPrev and GenTree::gtNext.
1971 // See fgNodeThreading for more information.
1972 enum class NodeThreading
1973 {
1974     None,
1975     AllLocals, // Locals are threaded (after local morph when optimizing)
1976     AllTrees,  // All nodes are threaded (after gtSetBlockOrder)
1977     LIR,       // Nodes are in LIR form (after rationalization)
1978 };
1979
1980 /*
1981 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1982 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1983 XX                                                                           XX
1984 XX   The big guy. The sections are currently organized as :                  XX
1985 XX                                                                           XX
1986 XX    o  GenTree and BasicBlock                                              XX
1987 XX    o  LclVarsInfo                                                         XX
1988 XX    o  Importer                                                            XX
1989 XX    o  FlowGraph                                                           XX
1990 XX    o  Optimizer                                                           XX
1991 XX    o  RegAlloc                                                            XX
1992 XX    o  EEInterface                                                         XX
1993 XX    o  TempsInfo                                                           XX
1994 XX    o  RegSet                                                              XX
1995 XX    o  GCInfo                                                              XX
1996 XX    o  Instruction                                                         XX
1997 XX    o  ScopeInfo                                                           XX
1998 XX    o  PrologScopeInfo                                                     XX
1999 XX    o  CodeGenerator                                                       XX
2000 XX    o  UnwindInfo                                                          XX
2001 XX    o  Compiler                                                            XX
2002 XX    o  typeInfo                                                            XX
2003 XX                                                                           XX
2004 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2005 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2006 */
2007
2008 struct HWIntrinsicInfo;
2009
2010 class Compiler
2011 {
2012     friend class emitter;
2013     friend class UnwindInfo;
2014     friend class UnwindFragmentInfo;
2015     friend class UnwindEpilogInfo;
2016     friend class JitTimer;
2017     friend class LinearScan;
2018     friend class Rationalizer;
2019     friend class Phase;
2020     friend class Lowering;
2021     friend class CSE_DataFlow;
2022     friend class CSE_Heuristic;
2023     friend class CodeGenInterface;
2024     friend class CodeGen;
2025     friend class LclVarDsc;
2026     friend class TempDsc;
2027     friend class LIR;
2028     friend class ObjectAllocator;
2029     friend class LocalAddressVisitor;
2030     friend struct Statement;
2031     friend struct GenTree;
2032     friend class MorphInitBlockHelper;
2033     friend class MorphCopyBlockHelper;
2034     friend class SharedTempsScope;
2035     friend class CallArgs;
2036     friend class IndirectCallTransformer;
2037     friend class ProfileSynthesis;
2038     friend class LocalsUseVisitor;
2039     friend class Promotion;
2040     friend class ReplaceVisitor;
2041
2042 #ifdef FEATURE_HW_INTRINSICS
2043     friend struct HWIntrinsicInfo;
2044     friend struct SimdAsHWIntrinsicInfo;
2045 #endif // FEATURE_HW_INTRINSICS
2046
2047 #ifndef TARGET_64BIT
2048     friend class DecomposeLongs;
2049 #endif // !TARGET_64BIT
2050
2051     /*
2052     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2053     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2054     XX                                                                           XX
2055     XX  Misc structs definitions                                                 XX
2056     XX                                                                           XX
2057     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2058     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2059     */
2060
2061 public:
2062     hashBvGlobalData hbvGlobalData; // Used by the hashBv bitvector package.
2063
2064 #ifdef DEBUG
2065     bool verbose;
2066     bool verboseTrees;
2067     bool shouldUseVerboseTrees();
2068     bool asciiTrees; // If true, dump trees using only ASCII characters
2069     bool shouldDumpASCIITrees();
2070     bool verboseSsa; // If true, produce especially verbose dump output in SSA construction.
2071     bool shouldUseVerboseSsa();
2072     bool treesBeforeAfterMorph; // If true, print trees before/after morphing (paired by an intra-compilation id:
2073     int  morphNum;              // This counts the trees that have been morphed, allowing us to label each uniquely.
2074     void makeExtraStructQueries(CORINFO_CLASS_HANDLE structHandle, int level); // Make queries recursively 'level' deep.
2075
2076     const char* VarNameToStr(VarName name)
2077     {
2078         return name;
2079     }
2080
2081     DWORD expensiveDebugCheckLevel;
2082 #endif
2083
2084     GenTree* impStoreMultiRegValueToVar(GenTree*             op,
2085                                         CORINFO_CLASS_HANDLE hClass DEBUGARG(CorInfoCallConvExtension callConv));
2086
2087 #ifdef TARGET_X86
2088     bool isTrivialPointerSizedStruct(CORINFO_CLASS_HANDLE clsHnd) const;
2089 #endif // TARGET_X86
2090
2091     //-------------------------------------------------------------------------
2092     // Functions to handle homogeneous floating-point aggregates (HFAs) in ARM/ARM64.
2093     // HFAs are one to four element structs where each element is the same
2094     // type, either all float or all double. We handle HVAs (one to four elements of
2095     // vector types) uniformly with HFAs. HFAs are treated specially
2096     // in the ARM/ARM64 Procedure Call Standards, specifically, they are passed in
2097     // floating-point registers instead of the general purpose registers.
2098     //
2099
2100     bool IsHfa(CORINFO_CLASS_HANDLE hClass);
2101     var_types GetHfaType(CORINFO_CLASS_HANDLE hClass);
2102     unsigned GetHfaCount(CORINFO_CLASS_HANDLE hClass);
2103
2104     bool IsMultiRegReturnedType(CORINFO_CLASS_HANDLE hClass, CorInfoCallConvExtension callConv);
2105
2106     //-------------------------------------------------------------------------
2107     // The following is used for validating format of EH table
2108     //
2109
2110     struct EHNodeDsc;
2111     typedef struct EHNodeDsc* pEHNodeDsc;
2112
2113     EHNodeDsc* ehnTree; // root of the tree comprising the EHnodes.
2114     EHNodeDsc* ehnNext; // root of the tree comprising the EHnodes.
2115
2116     struct EHNodeDsc
2117     {
2118         enum EHBlockType
2119         {
2120             TryNode,
2121             FilterNode,
2122             HandlerNode,
2123             FinallyNode,
2124             FaultNode
2125         };
2126
2127         EHBlockType ehnBlockType;   // kind of EH block
2128         IL_OFFSET   ehnStartOffset; // IL offset of start of the EH block
2129         IL_OFFSET ehnEndOffset; // IL offset past end of the EH block. (TODO: looks like verInsertEhNode() sets this to
2130                                 // the last IL offset, not "one past the last one", i.e., the range Start to End is
2131                                 // inclusive).
2132         pEHNodeDsc ehnNext;     // next (non-nested) block in sequential order
2133         pEHNodeDsc ehnChild;    // leftmost nested block
2134         union {
2135             pEHNodeDsc ehnTryNode;     // for filters and handlers, the corresponding try node
2136             pEHNodeDsc ehnHandlerNode; // for a try node, the corresponding handler node
2137         };
2138         pEHNodeDsc ehnFilterNode; // if this is a try node and has a filter, otherwise 0
2139         pEHNodeDsc ehnEquivalent; // if blockType=tryNode, start offset and end offset is same,
2140
2141         void ehnSetTryNodeType()
2142         {
2143             ehnBlockType = TryNode;
2144         }
2145         void ehnSetFilterNodeType()
2146         {
2147             ehnBlockType = FilterNode;
2148         }
2149         void ehnSetHandlerNodeType()
2150         {
2151             ehnBlockType = HandlerNode;
2152         }
2153         void ehnSetFinallyNodeType()
2154         {
2155             ehnBlockType = FinallyNode;
2156         }
2157         void ehnSetFaultNodeType()
2158         {
2159             ehnBlockType = FaultNode;
2160         }
2161
2162         bool ehnIsTryBlock()
2163         {
2164             return ehnBlockType == TryNode;
2165         }
2166         bool ehnIsFilterBlock()
2167         {
2168             return ehnBlockType == FilterNode;
2169         }
2170         bool ehnIsHandlerBlock()
2171         {
2172             return ehnBlockType == HandlerNode;
2173         }
2174         bool ehnIsFinallyBlock()
2175         {
2176             return ehnBlockType == FinallyNode;
2177         }
2178         bool ehnIsFaultBlock()
2179         {
2180             return ehnBlockType == FaultNode;
2181         }
2182
2183         // returns true if there is any overlap between the two nodes
2184         static bool ehnIsOverlap(pEHNodeDsc node1, pEHNodeDsc node2)
2185         {
2186             if (node1->ehnStartOffset < node2->ehnStartOffset)
2187             {
2188                 return (node1->ehnEndOffset >= node2->ehnStartOffset);
2189             }
2190             else
2191             {
2192                 return (node1->ehnStartOffset <= node2->ehnEndOffset);
2193             }
2194         }
2195
2196         // fails with BADCODE if inner is not completely nested inside outer
2197         static bool ehnIsNested(pEHNodeDsc inner, pEHNodeDsc outer)
2198         {
2199             return ((inner->ehnStartOffset >= outer->ehnStartOffset) && (inner->ehnEndOffset <= outer->ehnEndOffset));
2200         }
2201     };
2202
2203 //-------------------------------------------------------------------------
2204 // Exception handling functions
2205 //
2206
2207 #if !defined(FEATURE_EH_FUNCLETS)
2208
2209     bool ehNeedsShadowSPslots()
2210     {
2211         return (info.compXcptnsCount || opts.compDbgEnC);
2212     }
2213
2214     // 0 for methods with no EH
2215     // 1 for methods with non-nested EH, or where only the try blocks are nested
2216     // 2 for a method with a catch within a catch
2217     // etc.
2218     unsigned ehMaxHndNestingCount;
2219
2220 #endif // !FEATURE_EH_FUNCLETS
2221
2222     static bool jitIsBetween(unsigned value, unsigned start, unsigned end);
2223     static bool jitIsBetweenInclusive(unsigned value, unsigned start, unsigned end);
2224
2225     bool bbInCatchHandlerILRange(BasicBlock* blk);
2226     bool bbInFilterILRange(BasicBlock* blk);
2227     bool bbInFilterBBRange(BasicBlock* blk);
2228     bool bbInTryRegions(unsigned regionIndex, BasicBlock* blk);
2229     bool bbInExnFlowRegions(unsigned regionIndex, BasicBlock* blk);
2230     bool bbInHandlerRegions(unsigned regionIndex, BasicBlock* blk);
2231     bool bbInCatchHandlerRegions(BasicBlock* tryBlk, BasicBlock* hndBlk);
2232     unsigned short bbFindInnermostCommonTryRegion(BasicBlock* bbOne, BasicBlock* bbTwo);
2233
2234     unsigned short bbFindInnermostTryRegionContainingHandlerRegion(unsigned handlerIndex);
2235     unsigned short bbFindInnermostHandlerRegionContainingTryRegion(unsigned tryIndex);
2236
2237     // Returns true if "block" is the start of a try region.
2238     bool bbIsTryBeg(BasicBlock* block);
2239
2240     // Returns true if "block" is the start of a handler or filter region.
2241     bool bbIsHandlerBeg(BasicBlock* block);
2242
2243     // Returns true iff "block" is where control flows if an exception is raised in the
2244     // try region, and sets "*regionIndex" to the index of the try for the handler.
2245     // Differs from "IsHandlerBeg" in the case of filters, where this is true for the first
2246     // block of the filter, but not for the filter's handler.
2247     bool bbIsExFlowBlock(BasicBlock* block, unsigned* regionIndex);
2248
2249     bool ehHasCallableHandlers();
2250
2251     // Return the EH descriptor for the given region index.
2252     EHblkDsc* ehGetDsc(unsigned regionIndex);
2253
2254     // Return the EH index given a region descriptor.
2255     unsigned ehGetIndex(EHblkDsc* ehDsc);
2256
2257     // Return the EH descriptor index of the enclosing try, for the given region index.
2258     unsigned ehGetEnclosingTryIndex(unsigned regionIndex);
2259
2260     // Return the EH descriptor index of the enclosing handler, for the given region index.
2261     unsigned ehGetEnclosingHndIndex(unsigned regionIndex);
2262
2263     // Return the EH descriptor for the most nested 'try' region this BasicBlock is a member of (or nullptr if this
2264     // block is not in a 'try' region).
2265     EHblkDsc* ehGetBlockTryDsc(BasicBlock* block);
2266
2267     // Return the EH descriptor for the most nested filter or handler region this BasicBlock is a member of (or nullptr
2268     // if this block is not in a filter or handler region).
2269     EHblkDsc* ehGetBlockHndDsc(BasicBlock* block);
2270
2271     // Return the EH descriptor for the most nested region that may handle exceptions raised in this BasicBlock (or
2272     // nullptr if this block's exceptions propagate to caller).
2273     EHblkDsc* ehGetBlockExnFlowDsc(BasicBlock* block);
2274
2275     EHblkDsc* ehIsBlockTryLast(BasicBlock* block);
2276     EHblkDsc* ehIsBlockHndLast(BasicBlock* block);
2277     bool ehIsBlockEHLast(BasicBlock* block);
2278
2279     bool ehBlockHasExnFlowDsc(BasicBlock* block);
2280
2281     // Return the region index of the most nested EH region this block is in.
2282     unsigned ehGetMostNestedRegionIndex(BasicBlock* block, bool* inTryRegion);
2283
2284     // Find the true enclosing try index, ignoring 'mutual protect' try. Uses IL ranges to check.
2285     unsigned ehTrueEnclosingTryIndexIL(unsigned regionIndex);
2286
2287     // Return the index of the most nested enclosing region for a particular EH region. Returns NO_ENCLOSING_INDEX
2288     // if there is no enclosing region. If the returned index is not NO_ENCLOSING_INDEX, then '*inTryRegion'
2289     // is set to 'true' if the enclosing region is a 'try', or 'false' if the enclosing region is a handler.
2290     // (It can never be a filter.)
2291     unsigned ehGetEnclosingRegionIndex(unsigned regionIndex, bool* inTryRegion);
2292
2293     // A block has been deleted. Update the EH table appropriately.
2294     void ehUpdateForDeletedBlock(BasicBlock* block);
2295
2296     // Determine whether a block can be deleted while preserving the EH normalization rules.
2297     bool ehCanDeleteEmptyBlock(BasicBlock* block);
2298
2299     // Update the 'last' pointers in the EH table to reflect new or deleted blocks in an EH region.
2300     void ehUpdateLastBlocks(BasicBlock* oldLast, BasicBlock* newLast);
2301
2302     // For a finally handler, find the region index that the BBJ_CALLFINALLY lives in that calls the handler,
2303     // or NO_ENCLOSING_INDEX if the BBJ_CALLFINALLY lives in the main function body. Normally, the index
2304     // is the same index as the handler (and the BBJ_CALLFINALLY lives in the 'try' region), but for AMD64 the
2305     // BBJ_CALLFINALLY lives in the enclosing try or handler region, whichever is more nested, or the main function
2306     // body. If the returned index is not NO_ENCLOSING_INDEX, then '*inTryRegion' is set to 'true' if the
2307     // BBJ_CALLFINALLY lives in the returned index's 'try' region, or 'false' if lives in the handler region. (It never
2308     // lives in a filter.)
2309     unsigned ehGetCallFinallyRegionIndex(unsigned finallyIndex, bool* inTryRegion);
2310
2311     // Find the range of basic blocks in which all BBJ_CALLFINALLY will be found that target the 'finallyIndex' region's
2312     // handler. Set begBlk to the first block, and endBlk to the block after the last block of the range
2313     // (nullptr if the last block is the last block in the program).
2314     // Precondition: 'finallyIndex' is the EH region of a try/finally clause.
2315     void ehGetCallFinallyBlockRange(unsigned finallyIndex, BasicBlock** begBlk, BasicBlock** endBlk);
2316
2317 #ifdef DEBUG
2318     // Given a BBJ_CALLFINALLY block and the EH region index of the finally it is calling, return
2319     // 'true' if the BBJ_CALLFINALLY is in the correct EH region.
2320     bool ehCallFinallyInCorrectRegion(BasicBlock* blockCallFinally, unsigned finallyIndex);
2321 #endif // DEBUG
2322
2323 #if defined(FEATURE_EH_FUNCLETS)
2324     // Do we need a PSPSym in the main function? For codegen purposes, we only need one
2325     // if there is a filter that protects a region with a nested EH clause (such as a
2326     // try/catch nested in the 'try' body of a try/filter/filter-handler). See
2327     // genFuncletProlog() for more details. However, the VM seems to use it for more
2328     // purposes, maybe including debugging. Until we are sure otherwise, always create
2329     // a PSPSym for functions with any EH.
2330     bool ehNeedsPSPSym() const
2331     {
2332 #ifdef TARGET_X86
2333         return false;
2334 #else  // TARGET_X86
2335         return compHndBBtabCount > 0;
2336 #endif // TARGET_X86
2337     }
2338
2339     bool     ehAnyFunclets();  // Are there any funclets in this function?
2340     unsigned ehFuncletCount(); // Return the count of funclets in the function
2341
2342     unsigned bbThrowIndex(BasicBlock* blk); // Get the index to use as the cache key for sharing throw blocks
2343
2344 #else  // !FEATURE_EH_FUNCLETS
2345
2346     bool ehAnyFunclets()
2347     {
2348         return false;
2349     }
2350     unsigned ehFuncletCount()
2351     {
2352         return 0;
2353     }
2354
2355     unsigned bbThrowIndex(BasicBlock* blk)
2356     {
2357         return blk->bbTryIndex;
2358     } // Get the index to use as the cache key for sharing throw blocks
2359 #endif // !FEATURE_EH_FUNCLETS
2360
2361     // Returns a FlowEdge representing the "EH predecessors" of "blk".  These are the normal predecessors of
2362     // "blk", plus one special case: if "blk" is the first block of a handler, considers the predecessor(s) of the
2363     // first block of the corresponding try region to be "EH predecessors".  (If there is a single such predecessor,
2364     // for example, we want to consider that the immediate dominator of the catch clause start block, so it's
2365     // convenient to also consider it a predecessor.)
2366     FlowEdge* BlockPredsWithEH(BasicBlock* blk);
2367
2368     // This table is useful for memoization of the method above.
2369     typedef JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, FlowEdge*> BlockToFlowEdgeMap;
2370     BlockToFlowEdgeMap* m_blockToEHPreds;
2371     BlockToFlowEdgeMap* GetBlockToEHPreds()
2372     {
2373         if (m_blockToEHPreds == nullptr)
2374         {
2375             m_blockToEHPreds = new (getAllocator()) BlockToFlowEdgeMap(getAllocator());
2376         }
2377         return m_blockToEHPreds;
2378     }
2379
2380     void* ehEmitCookie(BasicBlock* block);
2381     UNATIVE_OFFSET ehCodeOffset(BasicBlock* block);
2382
2383     EHblkDsc* ehInitHndRange(BasicBlock* src, IL_OFFSET* hndBeg, IL_OFFSET* hndEnd, bool* inFilter);
2384
2385     EHblkDsc* ehInitTryRange(BasicBlock* src, IL_OFFSET* tryBeg, IL_OFFSET* tryEnd);
2386
2387     EHblkDsc* ehInitHndBlockRange(BasicBlock* blk, BasicBlock** hndBeg, BasicBlock** hndLast, bool* inFilter);
2388
2389     EHblkDsc* ehInitTryBlockRange(BasicBlock* blk, BasicBlock** tryBeg, BasicBlock** tryLast);
2390
2391     void fgSetTryBeg(EHblkDsc* handlerTab, BasicBlock* newTryBeg);
2392
2393     void fgSetTryEnd(EHblkDsc* handlerTab, BasicBlock* newTryLast);
2394
2395     void fgSetHndEnd(EHblkDsc* handlerTab, BasicBlock* newHndLast);
2396
2397     void fgSkipRmvdBlocks(EHblkDsc* handlerTab);
2398
2399     void fgAllocEHTable();
2400
2401     void fgRemoveEHTableEntry(unsigned XTnum);
2402
2403 #if defined(FEATURE_EH_FUNCLETS)
2404
2405     EHblkDsc* fgAddEHTableEntry(unsigned XTnum);
2406
2407 #endif // FEATURE_EH_FUNCLETS
2408
2409     void fgSortEHTable();
2410
2411     // Causes the EH table to obey some well-formedness conditions, by inserting
2412     // empty BB's when necessary:
2413     //   * No block is both the first block of a handler and the first block of a try.
2414     //   * No block is the first block of multiple 'try' regions.
2415     //   * No block is the last block of multiple EH regions.
2416     void fgNormalizeEH();
2417     bool fgNormalizeEHCase1();
2418     bool fgNormalizeEHCase2();
2419     bool fgNormalizeEHCase3();
2420
2421     bool fgCreateFiltersForGenericExceptions();
2422
2423     void fgCheckForLoopsInHandlers();
2424
2425 #ifdef DEBUG
2426     void dispIncomingEHClause(unsigned num, const CORINFO_EH_CLAUSE& clause);
2427     void dispOutgoingEHClause(unsigned num, const CORINFO_EH_CLAUSE& clause);
2428     void fgVerifyHandlerTab();
2429     void fgDispHandlerTab();
2430 #endif // DEBUG
2431
2432     bool fgNeedToSortEHTable;
2433
2434     void verInitEHTree(unsigned numEHClauses);
2435     void verInsertEhNode(CORINFO_EH_CLAUSE* clause, EHblkDsc* handlerTab);
2436     void verInsertEhNodeInTree(EHNodeDsc** ppRoot, EHNodeDsc* node);
2437     void verInsertEhNodeParent(EHNodeDsc** ppRoot, EHNodeDsc* node);
2438     void verCheckNestingLevel(EHNodeDsc* initRoot);
2439
2440     /*
2441     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2442     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2443     XX                                                                           XX
2444     XX                        GenTree and BasicBlock                             XX
2445     XX                                                                           XX
2446     XX  Functions to allocate and display the GenTrees and BasicBlocks           XX
2447     XX                                                                           XX
2448     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2449     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2450     */
2451
2452     // Functions to create nodes
2453     Statement* gtNewStmt(GenTree* expr = nullptr);
2454     Statement* gtNewStmt(GenTree* expr, const DebugInfo& di);
2455
2456     // For unary opers.
2457     GenTree* gtNewOperNode(genTreeOps oper, var_types type, GenTree* op1);
2458
2459     // For binary opers.
2460     GenTreeOp* gtNewOperNode(genTreeOps oper, var_types type, GenTree* op1, GenTree* op2);
2461
2462     GenTreeCC* gtNewCC(genTreeOps oper, var_types type, GenCondition cond);
2463     GenTreeOpCC* gtNewOperCC(genTreeOps oper, var_types type, GenCondition cond, GenTree* op1, GenTree* op2);
2464
2465     GenTreeColon* gtNewColonNode(var_types type, GenTree* thenNode, GenTree* elseNode);
2466     GenTreeQmark* gtNewQmarkNode(var_types type, GenTree* cond, GenTreeColon* colon);
2467
2468     GenTree* gtNewLargeOperNode(genTreeOps oper,
2469                                 var_types  type = TYP_I_IMPL,
2470                                 GenTree*   op1  = nullptr,
2471                                 GenTree*   op2  = nullptr);
2472
2473     GenTreeIntCon* gtNewIconNode(ssize_t value, var_types type = TYP_INT);
2474     GenTreeIntCon* gtNewIconNode(unsigned fieldOffset, FieldSeq* fieldSeq);
2475     GenTreeIntCon* gtNewNull();
2476     GenTreeIntCon* gtNewTrue();
2477     GenTreeIntCon* gtNewFalse();
2478
2479     GenTree* gtNewPhysRegNode(regNumber reg, var_types type);
2480
2481     GenTree* gtNewJmpTableNode();
2482
2483     GenTree* gtNewIndOfIconHandleNode(var_types indType, size_t value, GenTreeFlags iconFlags, bool isInvariant);
2484
2485     GenTreeIntCon* gtNewIconHandleNode(size_t value, GenTreeFlags flags, FieldSeq* fields = nullptr);
2486
2487     GenTreeFlags gtTokenToIconFlags(unsigned token);
2488
2489     GenTree* gtNewIconEmbHndNode(void* value, void* pValue, GenTreeFlags flags, void* compileTimeHandle);
2490
2491     GenTree* gtNewIconEmbScpHndNode(CORINFO_MODULE_HANDLE scpHnd);
2492     GenTree* gtNewIconEmbClsHndNode(CORINFO_CLASS_HANDLE clsHnd);
2493     GenTree* gtNewIconEmbMethHndNode(CORINFO_METHOD_HANDLE methHnd);
2494     GenTree* gtNewIconEmbFldHndNode(CORINFO_FIELD_HANDLE fldHnd);
2495
2496     GenTree* gtNewStringLiteralNode(InfoAccessType iat, void* pValue);
2497     GenTreeIntCon* gtNewStringLiteralLength(GenTreeStrCon* node);
2498
2499     GenTree* gtNewLconNode(__int64 value);
2500
2501     GenTree* gtNewDconNodeF(float value);
2502     GenTree* gtNewDconNodeD(double value);
2503     GenTree* gtNewDconNode(float value, var_types type) = delete; // use gtNewDconNodeF instead
2504     GenTree* gtNewDconNode(double value, var_types type);
2505
2506     GenTree* gtNewSconNode(int CPX, CORINFO_MODULE_HANDLE scpHandle);
2507
2508     GenTreeVecCon* gtNewVconNode(var_types type);
2509
2510     GenTreeVecCon* gtNewVconNode(var_types type, void* data);
2511
2512     GenTree* gtNewAllBitsSetConNode(var_types type);
2513
2514     GenTree* gtNewZeroConNode(var_types type);
2515
2516     GenTree* gtNewOneConNode(var_types type, var_types simdBaseType = TYP_UNDEF);
2517
2518     GenTree* gtNewGenericCon(var_types type, uint8_t* cnsVal);
2519
2520     GenTree* gtNewConWithPattern(var_types type, uint8_t pattern);
2521
2522     GenTreeLclVar* gtNewStoreLclVarNode(unsigned lclNum, GenTree* data);
2523
2524     GenTreeLclFld* gtNewStoreLclFldNode(
2525         unsigned lclNum, var_types type, ClassLayout* layout, unsigned offset, GenTree* data);
2526
2527     GenTreeLclFld* gtNewStoreLclFldNode(unsigned lclNum, var_types type, unsigned offset, GenTree* data)
2528     {
2529         return gtNewStoreLclFldNode(lclNum, type, (type == TYP_STRUCT) ? data->GetLayout(this) : nullptr, offset, data);
2530     }
2531
2532     GenTree* gtNewPutArgReg(var_types type, GenTree* arg, regNumber argReg);
2533
2534     GenTree* gtNewBitCastNode(var_types type, GenTree* arg);
2535
2536 public:
2537     GenTreeCall* gtNewCallNode(gtCallTypes           callType,
2538                                CORINFO_METHOD_HANDLE handle,
2539                                var_types             type,
2540                                const DebugInfo&      di = DebugInfo());
2541
2542     GenTreeCall* gtNewIndCallNode(GenTree* addr, var_types type, const DebugInfo& di = DebugInfo());
2543
2544     GenTreeCall* gtNewHelperCallNode(
2545         unsigned helper, var_types type, GenTree* arg1 = nullptr, GenTree* arg2 = nullptr, GenTree* arg3 = nullptr);
2546
2547     GenTreeCall* gtNewRuntimeLookupHelperCallNode(CORINFO_RUNTIME_LOOKUP* pRuntimeLookup,
2548                                                   GenTree*                ctxTree,
2549                                                   void*                   compileTimeHandle);
2550
2551     GenTreeLclVar* gtNewLclvNode(unsigned lnum, var_types type DEBUGARG(IL_OFFSET offs = BAD_IL_OFFSET));
2552     GenTreeLclVar* gtNewLclVarNode(unsigned lclNum, var_types type = TYP_UNDEF);
2553     GenTreeLclVar* gtNewLclLNode(unsigned lnum, var_types type DEBUGARG(IL_OFFSET offs = BAD_IL_OFFSET));
2554
2555     GenTreeLclFld* gtNewLclVarAddrNode(unsigned lclNum, var_types type = TYP_I_IMPL);
2556     GenTreeLclFld* gtNewLclAddrNode(unsigned lclNum, unsigned lclOffs, var_types type = TYP_I_IMPL);
2557
2558     GenTreeConditional* gtNewConditionalNode(
2559         genTreeOps oper, GenTree* cond, GenTree* op1, GenTree* op2, var_types type);
2560
2561 #ifdef FEATURE_SIMD
2562     void SetOpLclRelatedToSIMDIntrinsic(GenTree* op);
2563 #endif
2564
2565 #ifdef FEATURE_HW_INTRINSICS
2566     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2567                                                  NamedIntrinsic hwIntrinsicID,
2568                                                  CorInfoType    simdBaseJitType,
2569                                                  unsigned       simdSize);
2570     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2571                                                  GenTree*       op1,
2572                                                  NamedIntrinsic hwIntrinsicID,
2573                                                  CorInfoType    simdBaseJitType,
2574                                                  unsigned       simdSize);
2575     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2576                                                  GenTree*       op1,
2577                                                  GenTree*       op2,
2578                                                  NamedIntrinsic hwIntrinsicID,
2579                                                  CorInfoType    simdBaseJitType,
2580                                                  unsigned       simdSize);
2581     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2582                                                  GenTree*       op1,
2583                                                  GenTree*       op2,
2584                                                  GenTree*       op3,
2585                                                  NamedIntrinsic hwIntrinsicID,
2586                                                  CorInfoType    simdBaseJitType,
2587                                                  unsigned       simdSize);
2588     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2589                                                  GenTree*       op1,
2590                                                  GenTree*       op2,
2591                                                  GenTree*       op3,
2592                                                  GenTree*       op4,
2593                                                  NamedIntrinsic hwIntrinsicID,
2594                                                  CorInfoType    simdBaseJitType,
2595                                                  unsigned       simdSize);
2596     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2597                                                  GenTree**      operands,
2598                                                  size_t         operandCount,
2599                                                  NamedIntrinsic hwIntrinsicID,
2600                                                  CorInfoType    simdBaseJitType,
2601                                                  unsigned       simdSize);
2602     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types              type,
2603                                                  IntrinsicNodeBuilder&& nodeBuilder,
2604                                                  NamedIntrinsic         hwIntrinsicID,
2605                                                  CorInfoType            simdBaseJitType,
2606                                                  unsigned               simdSize);
2607
2608     GenTreeHWIntrinsic* gtNewSimdAsHWIntrinsicNode(var_types      type,
2609                                                    NamedIntrinsic hwIntrinsicID,
2610                                                    CorInfoType    simdBaseJitType,
2611                                                    unsigned       simdSize)
2612     {
2613         return gtNewSimdHWIntrinsicNode(type, hwIntrinsicID, simdBaseJitType, simdSize);
2614     }
2615
2616     GenTreeHWIntrinsic* gtNewSimdAsHWIntrinsicNode(
2617         var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID, CorInfoType simdBaseJitType, unsigned simdSize)
2618     {
2619         return gtNewSimdHWIntrinsicNode(type, op1, hwIntrinsicID, simdBaseJitType, simdSize);
2620     }
2621
2622     GenTreeHWIntrinsic* gtNewSimdAsHWIntrinsicNode(var_types      type,
2623                                                    GenTree*       op1,
2624                                                    GenTree*       op2,
2625                                                    NamedIntrinsic hwIntrinsicID,
2626                                                    CorInfoType    simdBaseJitType,
2627                                                    unsigned       simdSize)
2628     {
2629         return gtNewSimdHWIntrinsicNode(type, op1, op2, hwIntrinsicID, simdBaseJitType, simdSize);
2630     }
2631
2632     GenTreeHWIntrinsic* gtNewSimdAsHWIntrinsicNode(var_types      type,
2633                                                    GenTree*       op1,
2634                                                    GenTree*       op2,
2635                                                    GenTree*       op3,
2636                                                    NamedIntrinsic hwIntrinsicID,
2637                                                    CorInfoType    simdBaseJitType,
2638                                                    unsigned       simdSize)
2639     {
2640         return gtNewSimdHWIntrinsicNode(type, op1, op2, op3, hwIntrinsicID, simdBaseJitType, simdSize);
2641     }
2642
2643     GenTree* gtNewSimdAbsNode(
2644         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2645
2646     GenTree* gtNewSimdBinOpNode(genTreeOps  op,
2647                                 var_types   type,
2648                                 GenTree*    op1,
2649                                 GenTree*    op2,
2650                                 CorInfoType simdBaseJitType,
2651                                 unsigned    simdSize);
2652
2653     GenTree* gtNewSimdCeilNode(
2654         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2655
2656     GenTree* gtNewSimdCmpOpNode(genTreeOps  op,
2657                                 var_types   type,
2658                                 GenTree*    op1,
2659                                 GenTree*    op2,
2660                                 CorInfoType simdBaseJitType,
2661                                 unsigned    simdSize);
2662
2663     GenTree* gtNewSimdCmpOpAllNode(genTreeOps  op,
2664                                    var_types   type,
2665                                    GenTree*    op1,
2666                                    GenTree*    op2,
2667                                    CorInfoType simdBaseJitType,
2668                                    unsigned    simdSize);
2669
2670     GenTree* gtNewSimdCmpOpAnyNode(genTreeOps  op,
2671                                    var_types   type,
2672                                    GenTree*    op1,
2673                                    GenTree*    op2,
2674                                    CorInfoType simdBaseJitType,
2675                                    unsigned    simdSize);
2676
2677     GenTree* gtNewSimdCndSelNode(var_types   type,
2678                                  GenTree*    op1,
2679                                  GenTree*    op2,
2680                                  GenTree*    op3,
2681                                  CorInfoType simdBaseJitType,
2682                                  unsigned    simdSize);
2683
2684     GenTree* gtNewSimdCreateBroadcastNode(
2685         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2686
2687     GenTree* gtNewSimdCreateScalarNode(
2688         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2689
2690     GenTree* gtNewSimdCreateScalarUnsafeNode(
2691         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2692
2693     GenTree* gtNewSimdDotProdNode(var_types   type,
2694                                   GenTree*    op1,
2695                                   GenTree*    op2,
2696                                   CorInfoType simdBaseJitType,
2697                                   unsigned    simdSize);
2698
2699     GenTree* gtNewSimdFloorNode(
2700         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2701
2702     GenTree* gtNewSimdGetElementNode(var_types   type,
2703                                      GenTree*    op1,
2704                                      GenTree*    op2,
2705                                      CorInfoType simdBaseJitType,
2706                                      unsigned    simdSize);
2707
2708     GenTree* gtNewSimdGetLowerNode(var_types   type,
2709                                    GenTree*    op1,
2710                                    CorInfoType simdBaseJitType,
2711                                    unsigned    simdSize);
2712
2713     GenTree* gtNewSimdGetUpperNode(var_types   type,
2714                                    GenTree*    op1,
2715                                    CorInfoType simdBaseJitType,
2716                                    unsigned    simdSize);
2717
2718     GenTree* gtNewSimdLoadNode(
2719         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2720
2721     GenTree* gtNewSimdLoadAlignedNode(
2722         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2723
2724     GenTree* gtNewSimdLoadNonTemporalNode(
2725         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2726
2727     GenTree* gtNewSimdMaxNode(var_types   type,
2728                               GenTree*    op1,
2729                               GenTree*    op2,
2730                               CorInfoType simdBaseJitType,
2731                               unsigned    simdSize);
2732
2733     GenTree* gtNewSimdMinNode(var_types   type,
2734                               GenTree*    op1,
2735                               GenTree*    op2,
2736                               CorInfoType simdBaseJitType,
2737                               unsigned    simdSize);
2738
2739     GenTree* gtNewSimdNarrowNode(var_types   type,
2740                                  GenTree*    op1,
2741                                  GenTree*    op2,
2742                                  CorInfoType simdBaseJitType,
2743                                  unsigned    simdSize);
2744
2745     GenTree* gtNewSimdShuffleNode(var_types   type,
2746                                   GenTree*    op1,
2747                                   GenTree*    op2,
2748                                   CorInfoType simdBaseJitType,
2749                                   unsigned    simdSize);
2750
2751     GenTree* gtNewSimdSqrtNode(
2752         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2753
2754     GenTree* gtNewSimdStoreNode(
2755         GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize);
2756
2757     GenTree* gtNewSimdStoreAlignedNode(
2758         GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize);
2759
2760     GenTree* gtNewSimdStoreNonTemporalNode(
2761         GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize);
2762
2763     GenTree* gtNewSimdSumNode(
2764         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2765
2766 #if defined(TARGET_XARCH)
2767     GenTree* gtNewSimdTernaryLogicNode(var_types   type,
2768                                        GenTree*    op1,
2769                                        GenTree*    op2,
2770                                        GenTree*    op3,
2771                                        GenTree*    op4,
2772                                        CorInfoType simdBaseJitType,
2773                                        unsigned    simdSize);
2774 #endif // TARGET_XARCH
2775
2776     GenTree* gtNewSimdUnOpNode(genTreeOps  op,
2777                                var_types   type,
2778                                GenTree*    op1,
2779                                CorInfoType simdBaseJitType,
2780                                unsigned    simdSize);
2781
2782     GenTree* gtNewSimdWidenLowerNode(
2783         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2784
2785     GenTree* gtNewSimdWidenUpperNode(
2786         var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
2787
2788     GenTree* gtNewSimdWithElementNode(var_types   type,
2789                                       GenTree*    op1,
2790                                       GenTree*    op2,
2791                                       GenTree*    op3,
2792                                       CorInfoType simdBaseJitType,
2793                                       unsigned    simdSize);
2794
2795     GenTree* gtNewSimdWithLowerNode(var_types   type,
2796                                     GenTree*    op1,
2797                                     GenTree*    op2,
2798                                     CorInfoType simdBaseJitType,
2799                                     unsigned    simdSize);
2800
2801     GenTree* gtNewSimdWithUpperNode(var_types   type,
2802                                     GenTree*    op1,
2803                                     GenTree*    op2,
2804                                     CorInfoType simdBaseJitType,
2805                                     unsigned    simdSize);
2806
2807     GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types type, NamedIntrinsic hwIntrinsicID);
2808     GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID);
2809     GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types      type,
2810                                                    GenTree*       op1,
2811                                                    GenTree*       op2,
2812                                                    NamedIntrinsic hwIntrinsicID);
2813     GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(
2814         var_types type, GenTree* op1, GenTree* op2, GenTree* op3, NamedIntrinsic hwIntrinsicID);
2815     CorInfoType getBaseJitTypeFromArgIfNeeded(NamedIntrinsic       intrinsic,
2816                                               CORINFO_CLASS_HANDLE clsHnd,
2817                                               CORINFO_SIG_INFO*    sig,
2818                                               CorInfoType          simdBaseJitType);
2819
2820 #ifdef TARGET_ARM64
2821     GenTreeFieldList* gtConvertTableOpToFieldList(GenTree* op, unsigned fieldCount);
2822 #endif
2823 #endif // FEATURE_HW_INTRINSICS
2824
2825     GenTree* gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd);
2826
2827     GenTreeLclFld* gtNewLclFldNode(unsigned lnum, var_types type, unsigned offset);
2828     GenTreeRetExpr* gtNewInlineCandidateReturnExpr(GenTreeCall* inlineCandidate, var_types type);
2829
2830     GenTreeFieldAddr* gtNewFieldAddrNode(var_types            type,
2831                                          CORINFO_FIELD_HANDLE fldHnd,
2832                                          GenTree*             obj    = nullptr,
2833                                          DWORD                offset = 0);
2834
2835     GenTreeFieldAddr* gtNewFieldAddrNode(CORINFO_FIELD_HANDLE fldHnd, GenTree* obj, unsigned offset)
2836     {
2837         return gtNewFieldAddrNode(varTypeIsGC(obj) ? TYP_BYREF : TYP_I_IMPL, fldHnd, obj, offset);
2838     }
2839
2840     GenTreeIndexAddr* gtNewIndexAddr(GenTree*             arrayOp,
2841                                      GenTree*             indexOp,
2842                                      var_types            elemType,
2843                                      CORINFO_CLASS_HANDLE elemClassHandle,
2844                                      unsigned             firstElemOffset,
2845                                      unsigned             lengthOffset);
2846
2847     GenTreeIndexAddr* gtNewArrayIndexAddr(GenTree*             arrayOp,
2848                                           GenTree*             indexOp,
2849                                           var_types            elemType,
2850                                           CORINFO_CLASS_HANDLE elemClassHandle);
2851
2852     GenTreeIndir* gtNewIndexIndir(GenTreeIndexAddr* indexAddr);
2853
2854     void gtAnnotateNewArrLen(GenTree* arrLen, BasicBlock* block);
2855
2856     GenTreeArrLen* gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset, BasicBlock* block);
2857
2858     GenTreeMDArr* gtNewMDArrLen(GenTree* arrayOp, unsigned dim, unsigned rank, BasicBlock* block);
2859
2860     GenTreeMDArr* gtNewMDArrLowerBound(GenTree* arrayOp, unsigned dim, unsigned rank, BasicBlock* block);
2861
2862     void gtInitializeStoreNode(GenTree* store, GenTree* data);
2863
2864     void gtInitializeIndirNode(GenTreeIndir* indir, GenTreeFlags indirFlags);
2865
2866     GenTreeBlk* gtNewBlkIndir(ClassLayout* layout, GenTree* addr, GenTreeFlags indirFlags = GTF_EMPTY);
2867
2868     GenTreeIndir* gtNewIndir(var_types typ, GenTree* addr, GenTreeFlags indirFlags = GTF_EMPTY);
2869
2870     GenTreeBlk* gtNewStoreBlkNode(
2871         ClassLayout* layout, GenTree* addr, GenTree* data, GenTreeFlags indirFlags = GTF_EMPTY);
2872
2873     GenTreeStoreInd* gtNewStoreIndNode(
2874         var_types type, GenTree* addr, GenTree* data, GenTreeFlags indirFlags = GTF_EMPTY);
2875
2876     GenTree* gtNewLoadValueNode(
2877         var_types type, ClassLayout* layout, GenTree* addr, GenTreeFlags indirFlags = GTF_EMPTY);
2878
2879     GenTree* gtNewLoadValueNode(ClassLayout* layout, GenTree* addr, GenTreeFlags indirFlags = GTF_EMPTY)
2880     {
2881         return gtNewLoadValueNode(layout->GetType(), layout, addr, indirFlags);
2882     }
2883
2884     GenTree* gtNewLoadValueNode(var_types type, GenTree* addr, GenTreeFlags indirFlags = GTF_EMPTY)
2885     {
2886         return gtNewLoadValueNode(type, nullptr, addr, indirFlags);
2887     }
2888
2889     GenTree* gtNewStoreValueNode(
2890         var_types type, ClassLayout* layout, GenTree* addr, GenTree* data, GenTreeFlags indirFlags = GTF_EMPTY);
2891
2892     GenTree* gtNewStoreValueNode(ClassLayout* layout, GenTree* addr, GenTree* data, GenTreeFlags indirFlags = GTF_EMPTY)
2893     {
2894         return gtNewStoreValueNode(layout->GetType(), layout, addr, data, indirFlags);
2895     }
2896
2897     GenTree* gtNewStoreValueNode(var_types type, GenTree* addr, GenTree* data, GenTreeFlags indirFlags = GTF_EMPTY)
2898     {
2899         return gtNewStoreValueNode(type, nullptr, addr, data, indirFlags);
2900     }
2901
2902     GenTree* gtNewNullCheck(GenTree* addr, BasicBlock* basicBlock);
2903
2904     var_types gtTypeForNullCheck(GenTree* tree);
2905     void gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block);
2906
2907     GenTree* gtNewTempStore(unsigned         tmp,
2908                             GenTree*         val,
2909                             unsigned         curLevel   = CHECK_SPILL_NONE,
2910                             Statement**      pAfterStmt = nullptr,
2911                             const DebugInfo& di         = DebugInfo(),
2912                             BasicBlock*      block      = nullptr);
2913
2914     GenTree* gtNewRefCOMfield(GenTree*                objPtr,
2915                               CORINFO_RESOLVED_TOKEN* pResolvedToken,
2916                               CORINFO_ACCESS_FLAGS    access,
2917                               CORINFO_FIELD_INFO*     pFieldInfo,
2918                               var_types               lclTyp,
2919                               GenTree*                assg);
2920
2921     GenTree* gtNewNothingNode();
2922
2923     GenTree* gtUnusedValNode(GenTree* expr);
2924
2925     GenTree* gtNewKeepAliveNode(GenTree* op);
2926
2927     GenTreeCast* gtNewCastNode(var_types typ, GenTree* op1, bool fromUnsigned, var_types castType);
2928
2929     GenTreeCast* gtNewCastNodeL(var_types typ, GenTree* op1, bool fromUnsigned, var_types castType);
2930
2931     GenTreeAllocObj* gtNewAllocObjNode(
2932         unsigned int helper, bool helperHasSideEffects, CORINFO_CLASS_HANDLE clsHnd, var_types type, GenTree* op1);
2933
2934     GenTreeAllocObj* gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool useParent);
2935
2936     GenTree* gtNewRuntimeLookup(CORINFO_GENERIC_HANDLE hnd, CorInfoGenericHandleType hndTyp, GenTree* lookupTree);
2937
2938     GenTreeIndir* gtNewMethodTableLookup(GenTree* obj);
2939
2940     //------------------------------------------------------------------------
2941     // Other GenTree functions
2942
2943     GenTree* gtClone(GenTree* tree, bool complexOK = false);
2944
2945     // If `tree` is a lclVar with lclNum `varNum`, return an IntCns with value `varVal`; otherwise,
2946     // create a copy of `tree`, adding specified flags, replacing uses of lclVar `deepVarNum` with
2947     // IntCnses with value `deepVarVal`.
2948     GenTree* gtCloneExpr(
2949         GenTree* tree, GenTreeFlags addFlags, unsigned varNum, int varVal, unsigned deepVarNum, int deepVarVal);
2950
2951     // Create a copy of `tree`, optionally adding specified flags, and optionally mapping uses of local
2952     // `varNum` to int constants with value `varVal`.
2953     GenTree* gtCloneExpr(GenTree*     tree,
2954                          GenTreeFlags addFlags = GTF_EMPTY,
2955                          unsigned     varNum   = BAD_VAR_NUM,
2956                          int          varVal   = 0)
2957     {
2958         return gtCloneExpr(tree, addFlags, varNum, varVal, varNum, varVal);
2959     }
2960
2961     Statement* gtCloneStmt(Statement* stmt)
2962     {
2963         GenTree* exprClone = gtCloneExpr(stmt->GetRootNode());
2964         return gtNewStmt(exprClone, stmt->GetDebugInfo());
2965     }
2966
2967     // Internal helper for cloning a call
2968     GenTreeCall* gtCloneExprCallHelper(GenTreeCall* call,
2969                                        GenTreeFlags addFlags   = GTF_EMPTY,
2970                                        unsigned     deepVarNum = BAD_VAR_NUM,
2971                                        int          deepVarVal = 0);
2972
2973     // Create copy of an inline or guarded devirtualization candidate tree.
2974     GenTreeCall* gtCloneCandidateCall(GenTreeCall* call);
2975
2976     void gtUpdateSideEffects(Statement* stmt, GenTree* tree);
2977
2978     void gtUpdateTreeAncestorsSideEffects(GenTree* tree);
2979
2980     void gtUpdateStmtSideEffects(Statement* stmt);
2981
2982     void gtUpdateNodeSideEffects(GenTree* tree);
2983
2984     void gtUpdateNodeOperSideEffects(GenTree* tree);
2985
2986     // Returns "true" iff the complexity (not formally defined, but first interpretation
2987     // is #of nodes in subtree) of "tree" is greater than "limit".
2988     // (This is somewhat redundant with the "GetCostEx()/GetCostSz()" fields, but can be used
2989     // before they have been set.)
2990     bool gtComplexityExceeds(GenTree* tree, unsigned limit);
2991
2992     GenTree* gtReverseCond(GenTree* tree);
2993
2994     static bool gtHasRef(GenTree* tree, unsigned lclNum);
2995
2996     bool gtHasLocalsWithAddrOp(GenTree* tree);
2997     bool gtHasAddressExposedLocals(GenTree* tree);
2998
2999     unsigned gtSetCallArgsOrder(CallArgs* args, bool lateArgs, int* callCostEx, int* callCostSz);
3000     unsigned gtSetMultiOpOrder(GenTreeMultiOp* multiOp);
3001
3002     void gtWalkOp(GenTree** op1, GenTree** op2, GenTree* base, bool constOnly);
3003
3004 #ifdef DEBUG
3005     unsigned gtHashValue(GenTree* tree);
3006
3007     GenTree* gtWalkOpEffectiveVal(GenTree* op);
3008 #endif
3009
3010     void gtPrepareCost(GenTree* tree);
3011     bool gtIsLikelyRegVar(GenTree* tree);
3012     void gtGetLclVarNodeCost(GenTreeLclVar* node, int* pCostEx, int* pCostSz, bool isLikelyRegVar);
3013     void gtGetLclFldNodeCost(GenTreeLclFld* node, int* pCostEx, int* pCostSz);
3014     bool gtGetIndNodeCost(GenTreeIndir* node, int* pCostEx, int* pCostSz);
3015
3016     // Returns true iff the secondNode can be swapped with firstNode.
3017     bool gtCanSwapOrder(GenTree* firstNode, GenTree* secondNode);
3018
3019     // Given an address expression, compute its costs and addressing mode opportunities,
3020     // and mark addressing mode candidates as GTF_DONT_CSE.
3021     // TODO-Throughput - Consider actually instantiating these early, to avoid
3022     // having to re-run the algorithm that looks for them (might also improve CQ).
3023     bool gtMarkAddrMode(GenTree* addr, int* costEx, int* costSz, var_types type);
3024
3025     unsigned gtSetEvalOrder(GenTree* tree);
3026
3027     void gtSetStmtInfo(Statement* stmt);
3028
3029     // Returns "true" iff "node" has any of the side effects in "flags".
3030     bool gtNodeHasSideEffects(GenTree* node, GenTreeFlags flags);
3031
3032     // Returns "true" iff "tree" or its (transitive) children have any of the side effects in "flags".
3033     bool gtTreeHasSideEffects(GenTree* tree, GenTreeFlags flags);
3034
3035     void gtExtractSideEffList(GenTree*     expr,
3036                               GenTree**    pList,
3037                               GenTreeFlags GenTreeFlags = GTF_SIDE_EFFECT,
3038                               bool         ignoreRoot   = false);
3039
3040     bool gtSplitTree(
3041         BasicBlock* block, Statement* stmt, GenTree* splitPoint, Statement** firstNewStmt, GenTree*** splitPointUse);
3042
3043     // Static fields of struct types (and sometimes the types that those are reduced to) are represented by having the
3044     // static field contain an object pointer to the boxed struct.  This simplifies the GC implementation...but
3045     // complicates the JIT somewhat.  This predicate returns "true" iff a node with type "fieldNodeType", representing
3046     // the given "fldHnd", is such an object pointer.
3047     bool gtIsStaticFieldPtrToBoxedStruct(var_types fieldNodeType, CORINFO_FIELD_HANDLE fldHnd);
3048
3049     bool gtStoreDefinesField(
3050         LclVarDsc* fieldVarDsc, ssize_t offset, unsigned size, ssize_t* pFieldStoreOffset, unsigned* pFieldStoreSize);
3051
3052     void gtPeelOffsets(GenTree** addr, target_ssize_t* offset, FieldSeq** fldSeq);
3053
3054     // Return true if call is a recursive call; return false otherwise.
3055     // Note when inlining, this looks for calls back to the root method.
3056     bool gtIsRecursiveCall(GenTreeCall* call)
3057     {
3058         return gtIsRecursiveCall(call->gtCallMethHnd);
3059     }
3060
3061     bool gtIsRecursiveCall(CORINFO_METHOD_HANDLE callMethodHandle)
3062     {
3063         return (callMethodHandle == impInlineRoot()->info.compMethodHnd);
3064     }
3065
3066     //-------------------------------------------------------------------------
3067
3068     GenTree* gtFoldExpr(GenTree* tree);
3069     GenTree* gtFoldExprConst(GenTree* tree);
3070     GenTree* gtFoldIndirConst(GenTreeIndir* indir);
3071     GenTree* gtFoldExprSpecial(GenTree* tree);
3072     GenTree* gtFoldBoxNullable(GenTree* tree);
3073     GenTree* gtFoldExprCompare(GenTree* tree);
3074     GenTree* gtFoldExprConditional(GenTree* tree);
3075     GenTree* gtFoldExprCall(GenTreeCall* call);
3076     GenTree* gtFoldTypeCompare(GenTree* tree);
3077     GenTree* gtFoldTypeEqualityCall(bool isEq, GenTree* op1, GenTree* op2);
3078
3079     // Options to control behavior of gtTryRemoveBoxUpstreamEffects
3080     enum BoxRemovalOptions
3081     {
3082         BR_REMOVE_AND_NARROW, // remove effects, minimize remaining work, return possibly narrowed source tree
3083         BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE, // remove effects and minimize remaining work, return type handle tree
3084         BR_REMOVE_BUT_NOT_NARROW,              // remove effects, return original source tree
3085         BR_DONT_REMOVE,                        // check if removal is possible, return copy source tree
3086         BR_DONT_REMOVE_WANT_TYPE_HANDLE,       // check if removal is possible, return type handle tree
3087         BR_MAKE_LOCAL_COPY                     // revise box to copy to temp local and return local's address
3088     };
3089
3090     GenTree* gtTryRemoveBoxUpstreamEffects(GenTree* tree, BoxRemovalOptions options = BR_REMOVE_AND_NARROW);
3091     GenTree* gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp);
3092
3093     //-------------------------------------------------------------------------
3094     // Get the handle for a ref type.
3095     CORINFO_CLASS_HANDLE gtGetClassHandle(GenTree* tree, bool* pIsExact, bool* pIsNonNull);
3096     // Get the class handle for an helper call
3097     CORINFO_CLASS_HANDLE gtGetHelperCallClassHandle(GenTreeCall* call, bool* pIsExact, bool* pIsNonNull);
3098     // Get the element handle for an array of ref type.
3099     CORINFO_CLASS_HANDLE gtGetArrayElementClassHandle(GenTree* array);
3100     // Get a class handle from a helper call argument
3101     CORINFO_CLASS_HANDLE gtGetHelperArgClassHandle(GenTree* array);
3102     // Get the class handle for a field
3103     CORINFO_CLASS_HANDLE gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsExact, bool* pIsNonNull);
3104     // Check if this tree is a typeof()
3105     bool gtIsTypeof(GenTree* tree, CORINFO_CLASS_HANDLE* handle = nullptr);
3106
3107     GenTreeLclVarCommon* gtCallGetDefinedRetBufLclAddr(GenTreeCall* call);
3108
3109 //-------------------------------------------------------------------------
3110 // Functions to display the trees
3111
3112 #ifdef DEBUG
3113     void gtDispNode(GenTree* tree, IndentStack* indentStack, _In_z_ const char* msg, bool isLIR);
3114
3115     void gtDispConst(GenTree* tree);
3116     void gtDispLeaf(GenTree* tree, IndentStack* indentStack);
3117     void gtDispLocal(GenTreeLclVarCommon* tree, IndentStack* indentStack);
3118     void gtDispNodeName(GenTree* tree);
3119 #if FEATURE_MULTIREG_RET
3120     unsigned gtDispMultiRegCount(GenTree* tree);
3121 #endif
3122     void gtDispRegVal(GenTree* tree);
3123     void gtDispVN(GenTree* tree);
3124     void gtDispCommonEndLine(GenTree* tree);
3125
3126     enum IndentInfo
3127     {
3128         IINone,
3129         IIArc,
3130         IIArcTop,
3131         IIArcBottom,
3132         IIEmbedded,
3133         IIError,
3134         IndentInfoCount
3135     };
3136     void gtDispChild(GenTree*             child,
3137                      IndentStack*         indentStack,
3138                      IndentInfo           arcType,
3139                      _In_opt_ const char* msg     = nullptr,
3140                      bool                 topOnly = false);
3141     void gtDispTree(GenTree*             tree,
3142                     IndentStack*         indentStack = nullptr,
3143                     _In_opt_ const char* msg         = nullptr,
3144                     bool                 topOnly     = false,
3145                     bool                 isLIR       = false);
3146     void gtGetLclVarNameInfo(unsigned lclNum, const char** ilKindOut, const char** ilNameOut, unsigned* ilNumOut);
3147     int gtGetLclVarName(unsigned lclNum, char* buf, unsigned buf_remaining);
3148     char* gtGetLclVarName(unsigned lclNum);
3149     void gtDispLclVar(unsigned lclNum, bool padForBiggestDisp = true);
3150     void gtDispLclVarStructType(unsigned lclNum);
3151     void gtDispSsaName(unsigned lclNum, unsigned ssaNum, bool isDef);
3152     void gtDispClassLayout(ClassLayout* layout, var_types type);
3153     void gtDispILLocation(const ILLocation& loc);
3154     void gtDispStmt(Statement* stmt, const char* msg = nullptr);
3155     void gtDispBlockStmts(BasicBlock* block);
3156     void gtPrintArgPrefix(GenTreeCall* call, CallArg* arg, char** bufp, unsigned* bufLength);
3157     const char* gtGetWellKnownArgNameForArgMsg(WellKnownArg arg);
3158     void gtGetArgMsg(GenTreeCall* call, CallArg* arg, char* bufp, unsigned bufLength);
3159     void gtGetLateArgMsg(GenTreeCall* call, CallArg* arg, char* bufp, unsigned bufLength);
3160     void gtDispArgList(GenTreeCall* call, GenTree* lastCallOperand, IndentStack* indentStack);
3161     void gtDispFieldSeq(FieldSeq* fieldSeq, ssize_t offset);
3162
3163     void gtDispRange(LIR::ReadOnlyRange const& range);
3164
3165     void gtDispTreeRange(LIR::Range& containingRange, GenTree* tree);
3166
3167     void gtDispLIRNode(GenTree* node, const char* prefixMsg = nullptr);
3168 #endif
3169
3170     // For tree walks
3171
3172     enum fgWalkResult
3173     {
3174         WALK_CONTINUE,
3175         WALK_SKIP_SUBTREES,
3176         WALK_ABORT
3177     };
3178     struct fgWalkData;
3179     typedef fgWalkResult(fgWalkPreFn)(GenTree** pTree, fgWalkData* data);
3180     typedef fgWalkResult(fgWalkPostFn)(GenTree** pTree, fgWalkData* data);
3181
3182     static fgWalkPreFn gtMarkColonCond;
3183     static fgWalkPreFn gtClearColonCond;
3184
3185     struct FindLinkData
3186     {
3187         GenTree*  nodeToFind;
3188         GenTree** result;
3189         GenTree*  parent;
3190     };
3191
3192     FindLinkData gtFindLink(Statement* stmt, GenTree* node);
3193     bool gtHasCatchArg(GenTree* tree);
3194
3195     typedef ArrayStack<GenTree*> GenTreeStack;
3196
3197 //=========================================================================
3198 // BasicBlock functions
3199 #ifdef DEBUG
3200     // This is a debug flag we will use to assert when creating block during codegen
3201     // as this interferes with procedure splitting. If you know what you're doing, set
3202     // it to true before creating the block. (DEBUG only)
3203     bool fgSafeBasicBlockCreation;
3204 #endif
3205
3206     BasicBlock* bbNewBasicBlock(BBjumpKinds jumpKind);
3207
3208     /*
3209     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3210     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3211     XX                                                                           XX
3212     XX                           LclVarsInfo                                     XX
3213     XX                                                                           XX
3214     XX   The variables to be used by the code generator.                         XX
3215     XX                                                                           XX
3216     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3217     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3218     */
3219
3220     //
3221     // For both PROMOTION_TYPE_NONE and PROMOTION_TYPE_DEPENDENT the struct will
3222     // be placed in the stack frame and it's fields must be laid out sequentially.
3223     //
3224     // For PROMOTION_TYPE_INDEPENDENT each of the struct's fields is replaced by
3225     //  a local variable that can be enregistered or placed in the stack frame.
3226     //  The fields do not need to be laid out sequentially
3227     //
3228     enum lvaPromotionType
3229     {
3230         PROMOTION_TYPE_NONE,        // The struct local is not promoted
3231         PROMOTION_TYPE_INDEPENDENT, // The struct local is promoted,
3232                                     //   and its field locals are independent of its parent struct local.
3233         PROMOTION_TYPE_DEPENDENT    // The struct local is promoted,
3234                                     //   but its field locals depend on its parent struct local.
3235     };
3236
3237     /*****************************************************************************/
3238
3239     enum FrameLayoutState
3240     {
3241         NO_FRAME_LAYOUT,
3242         INITIAL_FRAME_LAYOUT,
3243         PRE_REGALLOC_FRAME_LAYOUT,
3244         REGALLOC_FRAME_LAYOUT,
3245         TENTATIVE_FRAME_LAYOUT,
3246         FINAL_FRAME_LAYOUT
3247     };
3248
3249 public:
3250     RefCountState lvaRefCountState; // Current local ref count state
3251
3252     bool lvaLocalVarRefCounted() const
3253     {
3254         return lvaRefCountState == RCS_NORMAL;
3255     }
3256
3257     bool     lvaTrackedFixed; // true: We cannot add new 'tracked' variable
3258     unsigned lvaCount;        // total number of locals, which includes function arguments,
3259                               // special arguments, IL local variables, and JIT temporary variables
3260
3261     LclVarDsc* lvaTable;    // variable descriptor table
3262     unsigned   lvaTableCnt; // lvaTable size (>= lvaCount)
3263
3264     unsigned lvaTrackedCount;             // actual # of locals being tracked
3265     unsigned lvaTrackedCountInSizeTUnits; // min # of size_t's sufficient to hold a bit for all the locals being tracked
3266
3267 #ifdef DEBUG
3268     VARSET_TP lvaTrackedVars; // set of tracked variables
3269 #endif
3270 #ifndef TARGET_64BIT
3271     VARSET_TP lvaLongVars; // set of long (64-bit) variables
3272 #endif
3273     VARSET_TP lvaFloatVars; // set of floating-point (32-bit and 64-bit) variables
3274
3275     unsigned lvaCurEpoch; // VarSets are relative to a specific set of tracked var indices.
3276                           // It that changes, this changes.  VarSets from different epochs
3277                           // cannot be meaningfully combined.
3278
3279     unsigned GetCurLVEpoch()
3280     {
3281         return lvaCurEpoch;
3282     }
3283
3284     // reverse map of tracked number to var number
3285     unsigned  lvaTrackedToVarNumSize;
3286     unsigned* lvaTrackedToVarNum;
3287
3288 #if DOUBLE_ALIGN
3289 #ifdef DEBUG
3290     // # of procs compiled a with double-aligned stack
3291     static unsigned s_lvaDoubleAlignedProcsCount;
3292 #endif
3293 #endif
3294
3295     // Getters and setters for address-exposed and do-not-enregister local var properties.
3296     bool lvaVarAddrExposed(unsigned varNum) const;
3297     void lvaSetVarAddrExposed(unsigned varNum DEBUGARG(AddressExposedReason reason));
3298     void lvaSetHiddenBufferStructArg(unsigned varNum);
3299     void lvaSetVarLiveInOutOfHandler(unsigned varNum);
3300     bool lvaVarDoNotEnregister(unsigned varNum);
3301
3302     void lvSetMinOptsDoNotEnreg();
3303
3304     bool lvaEnregEHVars;
3305     bool lvaEnregMultiRegVars;
3306
3307     void lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(DoNotEnregisterReason reason));
3308
3309     unsigned lvaVarargsHandleArg;
3310 #ifdef TARGET_X86
3311     unsigned lvaVarargsBaseOfStkArgs; // Pointer (computed based on incoming varargs handle) to the start of the stack
3312                                       // arguments
3313 #endif                                // TARGET_X86
3314
3315     unsigned lvaInlinedPInvokeFrameVar; // variable representing the InlinedCallFrame
3316     unsigned lvaReversePInvokeFrameVar; // variable representing the reverse PInvoke frame
3317     unsigned lvaMonAcquired; // boolean variable introduced into in synchronized methods
3318                              // that tracks whether the lock has been taken
3319
3320     unsigned lvaArg0Var; // The lclNum of arg0. Normally this will be info.compThisArg.
3321                          // However, if there is a "ldarga 0" or "starg 0" in the IL,
3322                          // we will redirect all "ldarg(a) 0" and "starg 0" to this temp.
3323
3324     unsigned lvaInlineeReturnSpillTemp; // The temp to spill the non-VOID return expression
3325                                         // in case there are multiple BBJ_RETURN blocks in the inlinee
3326                                         // or if the inlinee has GC ref locals.
3327
3328 #if FEATURE_FIXED_OUT_ARGS
3329     unsigned            lvaOutgoingArgSpaceVar;  // var that represents outgoing argument space
3330     PhasedVar<unsigned> lvaOutgoingArgSpaceSize; // size of fixed outgoing argument space
3331 #endif                                           // FEATURE_FIXED_OUT_ARGS
3332
3333     static unsigned GetOutgoingArgByteSize(unsigned sizeWithoutPadding)
3334     {
3335         return roundUp(sizeWithoutPadding, TARGET_POINTER_SIZE);
3336     }
3337
3338     // Variable representing the return address. The helper-based tailcall
3339     // mechanism passes the address of the return address to a runtime helper
3340     // where it is used to detect tail-call chains.
3341     unsigned lvaRetAddrVar;
3342
3343 #if defined(DEBUG) && defined(TARGET_XARCH)
3344
3345     unsigned lvaReturnSpCheck; // Stores SP to confirm it is not corrupted on return.
3346
3347 #endif // defined(DEBUG) && defined(TARGET_XARCH)
3348
3349 #if defined(DEBUG) && defined(TARGET_X86)
3350
3351     unsigned lvaCallSpCheck; // Stores SP to confirm it is not corrupted after every call.
3352
3353 #endif // defined(DEBUG) && defined(TARGET_X86)
3354
3355     bool lvaGenericsContextInUse;
3356
3357     bool lvaKeepAliveAndReportThis(); // Synchronized instance method of a reference type, or
3358                                       // CORINFO_GENERICS_CTXT_FROM_THIS?
3359     bool lvaReportParamTypeArg();     // Exceptions and CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG?
3360
3361 //-------------------------------------------------------------------------
3362 // All these frame offsets are inter-related and must be kept in sync
3363
3364 #if !defined(FEATURE_EH_FUNCLETS)
3365     // This is used for the callable handlers
3366     unsigned lvaShadowSPslotsVar; // Block-layout TYP_STRUCT variable for all the shadow SP slots
3367 #endif                            // FEATURE_EH_FUNCLETS
3368
3369     int lvaCachedGenericContextArgOffs;
3370     int lvaCachedGenericContextArgOffset(); // For CORINFO_CALLCONV_PARAMTYPE and if generic context is passed as
3371                                             // THIS pointer
3372
3373 #ifdef JIT32_GCENCODER
3374
3375     unsigned lvaLocAllocSPvar; // variable which stores the value of ESP after the last alloca/localloc
3376
3377 #endif // JIT32_GCENCODER
3378
3379     unsigned lvaNewObjArrayArgs; // variable with arguments for new MD array helper
3380
3381     // TODO-Review: Prior to reg predict we reserve 24 bytes for Spill temps.
3382     //              after the reg predict we will use a computed maxTmpSize
3383     //              which is based upon the number of spill temps predicted by reg predict
3384     //              All this is necessary because if we under-estimate the size of the spill
3385     //              temps we could fail when encoding instructions that reference stack offsets for ARM.
3386     //
3387     // Pre codegen max spill temp size.
3388     static const unsigned MAX_SPILL_TEMP_SIZE = 24;
3389
3390     //-------------------------------------------------------------------------
3391
3392     unsigned lvaGetMaxSpillTempSize();
3393 #ifdef TARGET_ARM
3394     bool lvaIsPreSpilled(unsigned lclNum, regMaskTP preSpillMask);
3395 #endif // TARGET_ARM
3396     void lvaAssignFrameOffsets(FrameLayoutState curState);
3397     void lvaFixVirtualFrameOffsets();
3398     void lvaUpdateArgWithInitialReg(LclVarDsc* varDsc);
3399     void lvaUpdateArgsWithInitialReg();
3400     void lvaAssignVirtualFrameOffsetsToArgs();
3401 #ifdef UNIX_AMD64_ABI
3402     int lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, unsigned argSize, int argOffs, int* callerArgOffset);
3403 #else  // !UNIX_AMD64_ABI
3404     int lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, unsigned argSize, int argOffs);
3405 #endif // !UNIX_AMD64_ABI
3406     void lvaAssignVirtualFrameOffsetsToLocals();
3407     int lvaAllocLocalAndSetVirtualOffset(unsigned lclNum, unsigned size, int stkOffs);
3408 #ifdef TARGET_AMD64
3409     // Returns true if compCalleeRegsPushed (including RBP if used as frame pointer) is even.
3410     bool lvaIsCalleeSavedIntRegCountEven();
3411 #endif
3412     void lvaAlignFrame();
3413     void lvaAssignFrameOffsetsToPromotedStructs();
3414     int lvaAllocateTemps(int stkOffs, bool mustDoubleAlign);
3415
3416 #ifdef DEBUG
3417     void lvaDumpRegLocation(unsigned lclNum);
3418     void lvaDumpFrameLocation(unsigned lclNum);
3419     void lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t refCntWtdWidth = 6);
3420     void lvaTableDump(FrameLayoutState curState = NO_FRAME_LAYOUT); // NO_FRAME_LAYOUT means use the current frame
3421                                                                     // layout state defined by lvaDoneFrameLayout
3422 #endif
3423
3424 // Limit frames size to 1GB. The maximum is 2GB in theory - make it intentionally smaller
3425 // to avoid bugs from borderline cases.
3426 #define MAX_FrameSize 0x3FFFFFFF
3427     void lvaIncrementFrameSize(unsigned size);
3428
3429     unsigned lvaFrameSize(FrameLayoutState curState);
3430
3431     // Returns the caller-SP-relative offset for the SP/FP relative offset determined by FP based.
3432     int lvaToCallerSPRelativeOffset(int offs, bool isFpBased, bool forRootFrame = true) const;
3433
3434     // Returns the caller-SP-relative offset for the local variable "varNum."
3435     int lvaGetCallerSPRelativeOffset(unsigned varNum);
3436
3437     // Returns the SP-relative offset for the local variable "varNum". Illegal to ask this for functions with localloc.
3438     int lvaGetSPRelativeOffset(unsigned varNum);
3439
3440     int lvaToInitialSPRelativeOffset(unsigned offset, bool isFpBased);
3441     int lvaGetInitialSPRelativeOffset(unsigned varNum);
3442
3443     // True if this is an OSR compilation and this local is potentially
3444     // located on the original method stack frame.
3445     bool lvaIsOSRLocal(unsigned varNum);
3446
3447     //------------------------ For splitting types ----------------------------
3448
3449     void lvaInitTypeRef();
3450
3451     void lvaInitArgs(InitVarDscInfo* varDscInfo);
3452     void lvaInitThisPtr(InitVarDscInfo* varDscInfo);
3453     void lvaInitRetBuffArg(InitVarDscInfo* varDscInfo, bool useFixedRetBufReg);
3454     void lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, unsigned takeArgs);
3455     void lvaInitGenericsCtxt(InitVarDscInfo* varDscInfo);
3456     void lvaInitVarArgsHandle(InitVarDscInfo* varDscInfo);
3457
3458     void lvaInitVarDsc(LclVarDsc*              varDsc,
3459                        unsigned                varNum,
3460                        CorInfoType             corInfoType,
3461                        CORINFO_CLASS_HANDLE    typeHnd,
3462                        CORINFO_ARG_LIST_HANDLE varList,
3463                        CORINFO_SIG_INFO*       varSig);
3464
3465     var_types lvaGetActualType(unsigned lclNum);
3466     var_types lvaGetRealType(unsigned lclNum);
3467
3468     //-------------------------------------------------------------------------
3469
3470     void lvaInit();
3471
3472     LclVarDsc* lvaGetDesc(unsigned lclNum)
3473     {
3474         assert(lclNum < lvaCount);
3475         return &lvaTable[lclNum];
3476     }
3477
3478     LclVarDsc* lvaGetDesc(unsigned lclNum) const
3479     {
3480         assert(lclNum < lvaCount);
3481         return &lvaTable[lclNum];
3482     }
3483
3484     LclVarDsc* lvaGetDesc(const GenTreeLclVarCommon* lclVar)
3485     {
3486         return lvaGetDesc(lclVar->GetLclNum());
3487     }
3488
3489     unsigned lvaTrackedIndexToLclNum(unsigned trackedIndex)
3490     {
3491         assert(trackedIndex < lvaTrackedCount);
3492         unsigned lclNum = lvaTrackedToVarNum[trackedIndex];
3493         assert(lclNum < lvaCount);
3494         return lclNum;
3495     }
3496
3497     LclVarDsc* lvaGetDescByTrackedIndex(unsigned trackedIndex)
3498     {
3499         return lvaGetDesc(lvaTrackedIndexToLclNum(trackedIndex));
3500     }
3501
3502     unsigned lvaGetLclNum(const LclVarDsc* varDsc)
3503     {
3504         assert((lvaTable <= varDsc) && (varDsc < lvaTable + lvaCount)); // varDsc must point within the table
3505         assert(((char*)varDsc - (char*)lvaTable) % sizeof(LclVarDsc) ==
3506                0); // varDsc better not point in the middle of a variable
3507         unsigned varNum = (unsigned)(varDsc - lvaTable);
3508         assert(varDsc == &lvaTable[varNum]);
3509         return varNum;
3510     }
3511
3512     unsigned lvaLclSize(unsigned varNum);
3513     unsigned lvaLclExactSize(unsigned varNum);
3514
3515     bool lvaHaveManyLocals(float percent = 1.0f) const;
3516
3517     unsigned lvaGrabTemp(bool shortLifetime DEBUGARG(const char* reason));
3518     unsigned lvaGrabTemps(unsigned cnt DEBUGARG(const char* reason));
3519     unsigned lvaGrabTempWithImplicitUse(bool shortLifetime DEBUGARG(const char* reason));
3520
3521     void lvaSortByRefCount();
3522
3523     PhaseStatus lvaMarkLocalVars(); // Local variable ref-counting
3524     void lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers);
3525     void lvaMarkLocalVars(BasicBlock* block, bool isRecompute);
3526
3527     void lvaAllocOutgoingArgSpaceVar(); // Set up lvaOutgoingArgSpaceVar
3528
3529 #ifdef DEBUG
3530     struct lvaStressLclFldArgs
3531     {
3532         Compiler* m_pCompiler;
3533         bool      m_bFirstPass;
3534     };
3535
3536     static fgWalkPreFn lvaStressLclFldCB;
3537     void               lvaStressLclFld();
3538     unsigned lvaStressLclFldPadding(unsigned lclNum);
3539
3540     void lvaDispVarSet(VARSET_VALARG_TP set, VARSET_VALARG_TP allVars);
3541     void lvaDispVarSet(VARSET_VALARG_TP set);
3542
3543 #endif
3544
3545 #ifdef TARGET_ARM
3546     int lvaFrameAddress(int varNum, bool mustBeFPBased, regNumber* pBaseReg, int addrModeOffset, bool isFloatUsage);
3547 #else
3548     int lvaFrameAddress(int varNum, bool* pFPbased);
3549 #endif
3550
3551     bool lvaIsParameter(unsigned varNum);
3552     bool lvaIsRegArgument(unsigned varNum);
3553     bool lvaIsOriginalThisArg(unsigned varNum); // Is this varNum the original this argument?
3554     bool lvaIsOriginalThisReadOnly();           // return true if there is no place in the code
3555                                                 // that writes to arg0
3556
3557 #ifdef TARGET_X86
3558     bool lvaIsArgAccessedViaVarArgsCookie(unsigned lclNum)
3559     {
3560         if (!info.compIsVarArgs)
3561         {
3562             return false;
3563         }
3564
3565         LclVarDsc* varDsc = lvaGetDesc(lclNum);
3566         return varDsc->lvIsParam && !varDsc->lvIsRegArg && (lclNum != lvaVarargsHandleArg);
3567     }
3568 #endif // TARGET_X86
3569
3570     bool lvaIsImplicitByRefLocal(unsigned lclNum) const;
3571     bool lvaIsLocalImplicitlyAccessedByRef(unsigned lclNum) const;
3572
3573     // Returns true if this local var is a multireg struct
3574     bool lvaIsMultiregStruct(LclVarDsc* varDsc, bool isVararg);
3575
3576     // If the local is a TYP_STRUCT, get/set a class handle describing it
3577     void lvaSetStruct(unsigned varNum, ClassLayout* layout, bool unsafeValueClsCheck);
3578     void lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool unsafeValueClsCheck);
3579     void lvaSetStructUsedAsVarArg(unsigned varNum);
3580
3581     // If the local is TYP_REF, set or update the associated class information.
3582     void lvaSetClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false);
3583     void lvaSetClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE stackHandle = nullptr);
3584     void lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false);
3585     void lvaUpdateClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE stackHandle = nullptr);
3586
3587 #define MAX_NumOfFieldsInPromotableStruct 4 // Maximum number of fields in promotable struct
3588
3589     // Info about struct type fields.
3590     struct lvaStructFieldInfo
3591     {
3592         // Class handle for SIMD type recognition, see CORINFO_TYPE_LAYOUT_NODE
3593         // for more details on the restrictions.
3594         CORINFO_CLASS_HANDLE fldSIMDTypeHnd = NO_CLASS_HANDLE;
3595         uint8_t              fldOffset = 0;
3596         uint8_t              fldOrdinal = 0;
3597         var_types            fldType = TYP_UNDEF;
3598         unsigned             fldSize = 0;
3599
3600 #ifdef DEBUG
3601         // Field handle for diagnostic purposes only. See CORINFO_TYPE_LAYOUT_NODE.
3602         CORINFO_FIELD_HANDLE diagFldHnd = NO_FIELD_HANDLE;
3603 #endif
3604     };
3605
3606     // Info about a struct type, instances of which may be candidates for promotion.
3607     struct lvaStructPromotionInfo
3608     {
3609         CORINFO_CLASS_HANDLE typeHnd;
3610         bool                 canPromote;
3611         bool                 containsHoles;
3612         bool                 anySignificantPadding;
3613         bool                 fieldsSorted;
3614         unsigned char        fieldCnt;
3615         lvaStructFieldInfo   fields[MAX_NumOfFieldsInPromotableStruct];
3616
3617         lvaStructPromotionInfo(CORINFO_CLASS_HANDLE typeHnd = nullptr)
3618             : typeHnd(typeHnd)
3619             , canPromote(false)
3620             , containsHoles(false)
3621             , anySignificantPadding(false)
3622             , fieldsSorted(false)
3623             , fieldCnt(0)
3624         {
3625         }
3626     };
3627
3628     // This class is responsible for checking validity and profitability of struct promotion.
3629     // If it is both legal and profitable, then TryPromoteStructVar promotes the struct and initializes
3630     // necessary information for fgMorphStructField to use.
3631     class StructPromotionHelper
3632     {
3633     public:
3634         StructPromotionHelper(Compiler* compiler);
3635
3636         bool CanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd);
3637         bool TryPromoteStructVar(unsigned lclNum);
3638         void Clear()
3639         {
3640             structPromotionInfo.typeHnd = NO_CLASS_HANDLE;
3641         }
3642
3643     private:
3644         bool CanPromoteStructVar(unsigned lclNum);
3645         bool ShouldPromoteStructVar(unsigned lclNum);
3646         void PromoteStructVar(unsigned lclNum);
3647         void SortStructFields();
3648
3649         var_types TryPromoteValueClassAsPrimitive(CORINFO_TYPE_LAYOUT_NODE* treeNodes, size_t maxTreeNodes, size_t index);
3650         void AdvanceSubTree(CORINFO_TYPE_LAYOUT_NODE* treeNodes, size_t maxTreeNodes, size_t* index);
3651
3652     private:
3653         Compiler*              compiler;
3654         lvaStructPromotionInfo structPromotionInfo;
3655     };
3656
3657     StructPromotionHelper* structPromotionHelper;
3658
3659     unsigned lvaGetFieldLocal(const LclVarDsc* varDsc, unsigned int fldOffset);
3660     lvaPromotionType lvaGetPromotionType(const LclVarDsc* varDsc);
3661     lvaPromotionType lvaGetPromotionType(unsigned varNum);
3662     lvaPromotionType lvaGetParentPromotionType(const LclVarDsc* varDsc);
3663     lvaPromotionType lvaGetParentPromotionType(unsigned varNum);
3664     bool lvaIsFieldOfDependentlyPromotedStruct(const LclVarDsc* varDsc);
3665     bool lvaIsGCTracked(const LclVarDsc* varDsc);
3666
3667 #if defined(FEATURE_SIMD)
3668     bool lvaMapSimd12ToSimd16(const LclVarDsc* varDsc)
3669     {
3670         assert(varDsc->lvType == TYP_SIMD12);
3671
3672 #if defined(TARGET_64BIT)
3673         assert(compMacOsArm64Abi() || varDsc->lvSize() == 16);
3674 #endif // defined(TARGET_64BIT)
3675
3676         // We make local variable SIMD12 types 16 bytes instead of just 12.
3677         // lvSize() will return 16 bytes for SIMD12, even for fields.
3678         // However, we can't do that mapping if the var is a dependently promoted struct field.
3679         // Such a field must remain its exact size within its parent struct unless it is a single
3680         // field *and* it is the only field in a struct of 16 bytes.
3681         if (varDsc->lvSize() != 16)
3682         {
3683             return false;
3684         }
3685         if (lvaIsFieldOfDependentlyPromotedStruct(varDsc))
3686         {
3687             LclVarDsc* parentVarDsc = lvaGetDesc(varDsc->lvParentLcl);
3688             return (parentVarDsc->lvFieldCnt == 1) && (parentVarDsc->lvSize() == 16);
3689         }
3690         return true;
3691     }
3692 #endif // defined(FEATURE_SIMD)
3693
3694     unsigned lvaGSSecurityCookie; // LclVar number
3695     bool     lvaTempsHaveLargerOffsetThanVars();
3696
3697     // Returns "true" iff local variable "lclNum" is in SSA form.
3698     bool lvaInSsa(unsigned lclNum) const
3699     {
3700         return lvaGetDesc(lclNum)->lvInSsa;
3701     }
3702
3703     unsigned lvaStubArgumentVar; // variable representing the secret stub argument coming in EAX
3704
3705 #if defined(FEATURE_EH_FUNCLETS)
3706     unsigned lvaPSPSym; // variable representing the PSPSym
3707 #endif
3708
3709     InlineInfo*     impInlineInfo; // Only present for inlinees
3710     InlineStrategy* m_inlineStrategy;
3711
3712     InlineContext* compInlineContext; // Always present
3713
3714     // The Compiler* that is the root of the inlining tree of which "this" is a member.
3715     Compiler* impInlineRoot();
3716
3717 #if defined(DEBUG) || defined(INLINE_DATA)
3718     unsigned __int64 getInlineCycleCount()
3719     {
3720         return m_compCycles;
3721     }
3722 #endif // defined(DEBUG) || defined(INLINE_DATA)
3723
3724     bool fgNoStructPromotion;      // Set to TRUE to turn off struct promotion for this method.
3725     bool fgNoStructParamPromotion; // Set to TRUE to turn off struct promotion for parameters this method.
3726
3727     //=========================================================================
3728     //                          PROTECTED
3729     //=========================================================================
3730
3731 protected:
3732     //---------------- Local variable ref-counting ----------------------------
3733
3734     void lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, bool isRecompute);
3735     bool IsDominatedByExceptionalEntry(BasicBlock* block);
3736     void SetVolatileHint(LclVarDsc* varDsc);
3737
3738     // Keeps the mapping from SSA #'s to VN's for the implicit memory variables.
3739     SsaDefArray<SsaMemDef> lvMemoryPerSsaData;
3740
3741 public:
3742     // Returns the address of the per-Ssa data for memory at the given ssaNum (which is required
3743     // not to be the SsaConfig::RESERVED_SSA_NUM, which indicates that the variable is
3744     // not an SSA variable).
3745     SsaMemDef* GetMemoryPerSsaData(unsigned ssaNum)
3746     {
3747         return lvMemoryPerSsaData.GetSsaDef(ssaNum);
3748     }
3749
3750     /*
3751     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3752     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3753     XX                                                                           XX
3754     XX                           Importer                                        XX
3755     XX                                                                           XX
3756     XX   Imports the given method and converts it to semantic trees              XX
3757     XX                                                                           XX
3758     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3759     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3760     */
3761
3762 private:
3763     // For prefixFlags
3764     enum
3765     {
3766         PREFIX_TAILCALL_EXPLICIT = 0x00000001, // call has "tail" IL prefix
3767         PREFIX_TAILCALL_IMPLICIT =
3768             0x00000010, // call is treated as having "tail" prefix even though there is no "tail" IL prefix
3769         PREFIX_TAILCALL_STRESS =
3770             0x00000100, // call doesn't "tail" IL prefix but is treated as explicit because of tail call stress
3771         PREFIX_TAILCALL    = (PREFIX_TAILCALL_EXPLICIT | PREFIX_TAILCALL_IMPLICIT | PREFIX_TAILCALL_STRESS),
3772         PREFIX_VOLATILE    = 0x00001000,
3773         PREFIX_UNALIGNED   = 0x00010000,
3774         PREFIX_CONSTRAINED = 0x00100000,
3775         PREFIX_READONLY    = 0x01000000
3776     };
3777
3778     static void impValidateMemoryAccessOpcode(const BYTE* codeAddr, const BYTE* codeEndp, bool volatilePrefix);
3779     static OPCODE impGetNonPrefixOpcode(const BYTE* codeAddr, const BYTE* codeEndp);
3780     static GenTreeFlags impPrefixFlagsToIndirFlags(unsigned prefixFlags);
3781     static bool impOpcodeIsCallOpcode(OPCODE opcode);
3782
3783 public:
3784     void impInit();
3785     void impImport();
3786     void impFixPredLists();
3787
3788     CORINFO_CLASS_HANDLE impGetRefAnyClass();
3789     CORINFO_CLASS_HANDLE impGetRuntimeArgumentHandle();
3790     CORINFO_CLASS_HANDLE impGetTypeHandleClass();
3791     CORINFO_CLASS_HANDLE impGetStringClass();
3792     CORINFO_CLASS_HANDLE impGetObjectClass();
3793
3794     // Returns underlying type of handles returned by ldtoken instruction
3795     var_types GetRuntimeHandleUnderlyingType()
3796     {
3797         // RuntimeTypeHandle is backed by raw pointer on NativeAOT and by object reference on other runtimes
3798         return IsTargetAbi(CORINFO_NATIVEAOT_ABI) ? TYP_I_IMPL : TYP_REF;
3799     }
3800
3801     void impDevirtualizeCall(GenTreeCall*            call,
3802                              CORINFO_RESOLVED_TOKEN* pResolvedToken,
3803                              CORINFO_METHOD_HANDLE*  method,
3804                              unsigned*               methodFlags,
3805                              CORINFO_CONTEXT_HANDLE* contextHandle,
3806                              CORINFO_CONTEXT_HANDLE* exactContextHandle,
3807                              bool                    isLateDevirtualization,
3808                              bool                    isExplicitTailCall,
3809                              IL_OFFSET               ilOffset = BAD_IL_OFFSET);
3810
3811     bool impConsiderCallProbe(GenTreeCall* call, IL_OFFSET ilOffset);
3812
3813     enum class GDVProbeType
3814     {
3815         None,
3816         ClassProfile,
3817         MethodProfile,
3818         MethodAndClassProfile,
3819     };
3820
3821     GDVProbeType compClassifyGDVProbeType(GenTreeCall* call);
3822
3823     //=========================================================================
3824     //                          PROTECTED
3825     //=========================================================================
3826
3827 protected:
3828     //-------------------- Stack manipulation ---------------------------------
3829
3830     unsigned impStkSize; // Size of the full stack
3831
3832 #define SMALL_STACK_SIZE 16 // number of elements in impSmallStack
3833
3834     struct SavedStack // used to save/restore stack contents.
3835     {
3836         unsigned    ssDepth; // number of values on stack
3837         StackEntry* ssTrees; // saved tree values
3838     };
3839
3840     bool impIsPrimitive(CorInfoType type);
3841     bool impILConsumesAddr(const BYTE* codeAddr);
3842
3843     void impResolveToken(const BYTE* addr, CORINFO_RESOLVED_TOKEN* pResolvedToken, CorInfoTokenKind kind);
3844
3845     void impPushOnStack(GenTree* tree, typeInfo ti);
3846     StackEntry impPopStack();
3847     void impPopStack(unsigned n);
3848     StackEntry& impStackTop(unsigned n = 0);
3849     unsigned impStackHeight();
3850
3851     void impSaveStackState(SavedStack* savePtr, bool copy);
3852     void impRestoreStackState(SavedStack* savePtr);
3853
3854     GenTree* impImportLdvirtftn(GenTree* thisPtr, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
3855
3856     enum class BoxPatterns
3857     {
3858         None                  = 0,
3859         IsByRefLike           = 1,
3860         MakeInlineObservation = 2,
3861     };
3862
3863     int impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3864                            const BYTE*             codeAddr,
3865                            const BYTE*             codeEndp,
3866                            BoxPatterns             opts);
3867     void impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken);
3868
3869     void impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
3870
3871     bool impCanPInvokeInline();
3872     bool impCanPInvokeInlineCallSite(BasicBlock* block);
3873     void impCheckForPInvokeCall(
3874         GenTreeCall* call, CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sig, unsigned mflags, BasicBlock* block);
3875     GenTreeCall* impImportIndirectCall(CORINFO_SIG_INFO* sig, const DebugInfo& di = DebugInfo());
3876     void impPopArgsForUnmanagedCall(GenTreeCall* call, CORINFO_SIG_INFO* sig);
3877
3878     void impInsertHelperCall(CORINFO_HELPER_DESC* helperCall);
3879     void impHandleAccessAllowed(CorInfoIsAccessAllowedResult result, CORINFO_HELPER_DESC* helperCall);
3880     void impHandleAccessAllowedInternal(CorInfoIsAccessAllowedResult result, CORINFO_HELPER_DESC* helperCall);
3881
3882     var_types impImportCall(OPCODE                  opcode,
3883                             CORINFO_RESOLVED_TOKEN* pResolvedToken,
3884                             CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, // Is this a "constrained." call on a
3885                                                                                // type parameter?
3886                             GenTree*           newobjThis,
3887                             int                prefixFlags,
3888                             CORINFO_CALL_INFO* callInfo,
3889                             IL_OFFSET          rawILOffset);
3890
3891     CORINFO_CLASS_HANDLE impGetSpecialIntrinsicExactReturnType(GenTreeCall* call);
3892
3893     GenTree* impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HANDLE retClsHnd);
3894
3895     GenTree* impFixupStructReturnType(GenTree* op);
3896
3897 #ifdef DEBUG
3898     var_types impImportJitTestLabelMark(int numArgs);
3899 #endif // DEBUG
3900
3901     GenTree* impInitClass(CORINFO_RESOLVED_TOKEN* pResolvedToken);
3902
3903     GenTree* impImportStaticReadOnlyField(CORINFO_FIELD_HANDLE field, CORINFO_CLASS_HANDLE ownerCls);
3904
3905     GenTree* impImportStaticFieldAddress(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3906                                          CORINFO_ACCESS_FLAGS    access,
3907                                          CORINFO_FIELD_INFO*     pFieldInfo,
3908                                          var_types               lclTyp,
3909                                          GenTreeFlags*           pIndirFlags,
3910                                          bool*                   pIsHoistable = nullptr);
3911     void impAnnotateFieldIndir(GenTreeIndir* indir);
3912
3913     static void impBashVarAddrsToI(GenTree* tree1, GenTree* tree2 = nullptr);
3914
3915     GenTree* impImplicitIorI4Cast(GenTree* tree, var_types dstTyp, bool zeroExtend = false);
3916
3917     GenTree* impImplicitR4orR8Cast(GenTree* tree, var_types dstTyp);
3918
3919     void impImportLeave(BasicBlock* block);
3920     void impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr);
3921     GenTree* impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom);
3922
3923     // Mirrors StringComparison.cs
3924     enum StringComparison
3925     {
3926         Ordinal           = 4,
3927         OrdinalIgnoreCase = 5
3928     };
3929     enum StringComparisonJoint
3930     {
3931         Eq,  // (d1 == cns1) && (s2 == cns2)
3932         Xor, // (d1 ^ cns1) | (s2 ^ cns2)
3933     };
3934     GenTree* impStringEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO* sig, unsigned methodFlags);
3935     GenTree* impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO* sig, unsigned methodFlags);
3936     GenTree* impExpandHalfConstEquals(GenTreeLclVarCommon*   data,
3937                                       GenTree*         lengthFld,
3938                                       bool             checkForNull,
3939                                       bool             startsWith,
3940                                       WCHAR*           cnsData,
3941                                       int              len,
3942                                       int              dataOffset,
3943                                       StringComparison cmpMode);
3944     GenTree* impCreateCompareInd(GenTreeLclVarCommon*        obj,
3945                                  var_types             type,
3946                                  ssize_t               offset,
3947                                  ssize_t               value,
3948                                  StringComparison      ignoreCase,
3949                                  StringComparisonJoint joint = Eq);
3950     GenTree* impExpandHalfConstEqualsSWAR(
3951         GenTreeLclVarCommon* data, WCHAR* cns, int len, int dataOffset, StringComparison cmpMode);
3952     GenTree* impExpandHalfConstEqualsSIMD(
3953         GenTreeLclVarCommon* data, WCHAR* cns, int len, int dataOffset, StringComparison cmpMode);
3954     GenTreeStrCon* impGetStrConFromSpan(GenTree* span);
3955
3956     GenTree* impIntrinsic(GenTree*                newobjThis,
3957                           CORINFO_CLASS_HANDLE    clsHnd,
3958                           CORINFO_METHOD_HANDLE   method,
3959                           CORINFO_SIG_INFO*       sig,
3960                           unsigned                methodFlags,
3961                           CORINFO_RESOLVED_TOKEN* pResolvedToken,
3962                           bool                    readonlyCall,
3963                           bool                    tailCall,
3964                           bool                    callvirt,
3965                           CORINFO_RESOLVED_TOKEN* pContstrainedResolvedToken,
3966                           CORINFO_THIS_TRANSFORM  constraintCallThisTransform,
3967                           NamedIntrinsic*         pIntrinsicName,
3968                           bool*                   isSpecialIntrinsic = nullptr);
3969     GenTree* impMathIntrinsic(CORINFO_METHOD_HANDLE method,
3970                               CORINFO_SIG_INFO*     sig,
3971                               var_types             callType,
3972                               NamedIntrinsic        intrinsicName,
3973                               bool                  tailCall);
3974     GenTree* impMinMaxIntrinsic(CORINFO_METHOD_HANDLE method,
3975                                 CORINFO_SIG_INFO*     sig,
3976                                 CorInfoType           callJitType,
3977                                 NamedIntrinsic        intrinsicName,
3978                                 bool                  tailCall,
3979                                 bool                  isMax,
3980                                 bool                  isMagnitude,
3981                                 bool                  isNumber);
3982     NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method);
3983     NamedIntrinsic lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDLE method, const char* methodName);
3984     NamedIntrinsic lookupPrimitiveIntNamedIntrinsic(CORINFO_METHOD_HANDLE method, const char* methodName);
3985     GenTree* impUnsupportedNamedIntrinsic(unsigned              helper,
3986                                           CORINFO_METHOD_HANDLE method,
3987                                           CORINFO_SIG_INFO*     sig,
3988                                           bool                  mustExpand);
3989
3990     GenTree* impSRCSUnsafeIntrinsic(NamedIntrinsic        intrinsic,
3991                                     CORINFO_CLASS_HANDLE  clsHnd,
3992                                     CORINFO_METHOD_HANDLE method,
3993                                     CORINFO_SIG_INFO*     sig,
3994         CORINFO_RESOLVED_TOKEN* pResolvedToken);
3995
3996     GenTree* impPrimitiveNamedIntrinsic(NamedIntrinsic        intrinsic,
3997                                         CORINFO_CLASS_HANDLE  clsHnd,
3998                                         CORINFO_METHOD_HANDLE method,
3999                                         CORINFO_SIG_INFO*     sig);
4000
4001 #ifdef FEATURE_HW_INTRINSICS
4002     GenTree* impHWIntrinsic(NamedIntrinsic        intrinsic,
4003                             CORINFO_CLASS_HANDLE  clsHnd,
4004                             CORINFO_METHOD_HANDLE method,
4005                             CORINFO_SIG_INFO*     sig,
4006                             bool                  mustExpand);
4007     GenTree* impSimdAsHWIntrinsic(NamedIntrinsic        intrinsic,
4008                                   CORINFO_CLASS_HANDLE  clsHnd,
4009                                   CORINFO_METHOD_HANDLE method,
4010                                   CORINFO_SIG_INFO*     sig,
4011                                   GenTree*              newobjThis);
4012
4013 protected:
4014     bool compSupportsHWIntrinsic(CORINFO_InstructionSet isa);
4015
4016     GenTree* impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
4017                                          CORINFO_CLASS_HANDLE clsHnd,
4018                                          CORINFO_SIG_INFO*    sig,
4019                                          var_types            retType,
4020                                          CorInfoType          simdBaseJitType,
4021                                          unsigned             simdSize,
4022                                          GenTree*             newobjThis);
4023
4024     GenTree* impSpecialIntrinsic(NamedIntrinsic        intrinsic,
4025                                  CORINFO_CLASS_HANDLE  clsHnd,
4026                                  CORINFO_METHOD_HANDLE method,
4027                                  CORINFO_SIG_INFO*     sig,
4028                                  CorInfoType           simdBaseJitType,
4029                                  var_types             retType,
4030                                  unsigned              simdSize);
4031
4032     GenTree* getArgForHWIntrinsic(var_types            argType,
4033                                   CORINFO_CLASS_HANDLE argClass,
4034                                   bool                 expectAddr = false,
4035                                   GenTree*             newobjThis = nullptr);
4036     GenTree* impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, CorInfoType simdBaseJitType);
4037     GenTree* addRangeCheckIfNeeded(
4038         NamedIntrinsic intrinsic, GenTree* immOp, bool mustExpand, int immLowerBound, int immUpperBound);
4039     GenTree* addRangeCheckForHWIntrinsic(GenTree* immOp, int immLowerBound, int immUpperBound);
4040
4041 #endif // FEATURE_HW_INTRINSICS
4042     GenTree* impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
4043                                      CORINFO_SIG_INFO*    sig,
4044                                      int                  memberRef,
4045                                      bool                 readonlyCall,
4046                                      NamedIntrinsic       intrinsicName);
4047     GenTree* impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig);
4048     GenTree* impCreateSpanIntrinsic(CORINFO_SIG_INFO* sig);
4049
4050     GenTree* impKeepAliveIntrinsic(GenTree* objToKeepAlive);
4051
4052     GenTree* impMethodPointer(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
4053
4054     GenTree* impTransformThis(GenTree*                thisPtr,
4055                               CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
4056                               CORINFO_THIS_TRANSFORM  transform);
4057
4058     //----------------- Manipulating the trees and stmts ----------------------
4059
4060     Statement* impStmtList; // Statements for the BB being imported.
4061     Statement* impLastStmt; // The last statement for the current BB.
4062
4063 public:
4064     static const unsigned CHECK_SPILL_ALL  = static_cast<unsigned>(-1);
4065     static const unsigned CHECK_SPILL_NONE = static_cast<unsigned>(-2);
4066
4067     void impBeginTreeList();
4068     void impEndTreeList(BasicBlock* block, Statement* firstStmt, Statement* lastStmt);
4069     void impEndTreeList(BasicBlock* block);
4070     void impAppendStmtCheck(Statement* stmt, unsigned chkLevel);
4071     void impAppendStmt(Statement* stmt, unsigned chkLevel, bool checkConsumedDebugInfo = true);
4072     void impAppendStmt(Statement* stmt);
4073     void impInsertStmtBefore(Statement* stmt, Statement* stmtBefore);
4074     Statement* impAppendTree(GenTree* tree, unsigned chkLevel, const DebugInfo& di, bool checkConsumedDebugInfo = true);
4075     void impStoreTemp(unsigned         lclNum,
4076                       GenTree*         val,
4077                       unsigned         curLevel,
4078                       Statement**      pAfterStmt = nullptr,
4079                       const DebugInfo& di         = DebugInfo(),
4080                       BasicBlock*      block      = nullptr);
4081     Statement* impExtractLastStmt();
4082     GenTree* impCloneExpr(GenTree*             tree,
4083                           GenTree**            clone,
4084                           unsigned             curLevel,
4085                           Statement** pAfterStmt DEBUGARG(const char* reason));
4086     GenTree* impStoreStruct(GenTree*         store,
4087                              unsigned         curLevel,
4088                              Statement**      pAfterStmt = nullptr,
4089                              const DebugInfo& di         = DebugInfo(),
4090                              BasicBlock*      block      = nullptr);
4091     GenTree* impStoreStructPtr(GenTree* destAddr, GenTree* value, unsigned curLevel);
4092
4093     GenTree* impGetNodeAddr(GenTree* val, unsigned curLevel, GenTreeFlags* pDerefFlags);
4094
4095     var_types impNormStructType(CORINFO_CLASS_HANDLE structHnd, CorInfoType* simdBaseJitType = nullptr);
4096
4097     GenTree* impNormStructVal(GenTree* structVal, unsigned curLevel);
4098
4099     GenTree* impTokenToHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken,
4100                               bool*                   pRuntimeLookup    = nullptr,
4101                               bool                    mustRestoreHandle = false,
4102                               bool                    importParent      = false);
4103
4104     GenTree* impParentClassTokenToHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken,
4105                                          bool*                   pRuntimeLookup    = nullptr,
4106                                          bool                    mustRestoreHandle = false)
4107     {
4108         return impTokenToHandle(pResolvedToken, pRuntimeLookup, mustRestoreHandle, true);
4109     }
4110
4111     GenTree* impLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
4112                              CORINFO_LOOKUP*         pLookup,
4113                              GenTreeFlags            flags,
4114                              void*                   compileTimeHandle);
4115
4116     GenTree* getRuntimeContextTree(CORINFO_RUNTIME_LOOKUP_KIND kind);
4117
4118     GenTree* impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
4119                                     CORINFO_LOOKUP*         pLookup,
4120                                     void*                   compileTimeHandle);
4121
4122     GenTree* impReadyToRunLookupToTree(CORINFO_CONST_LOOKUP* pLookup, GenTreeFlags flags, void* compileTimeHandle);
4123
4124     GenTreeCall* impReadyToRunHelperToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
4125                                            CorInfoHelpFunc         helper,
4126                                            var_types               type,
4127                                            CORINFO_LOOKUP_KIND*    pGenericLookupKind = nullptr,
4128                                            GenTree*                arg1               = nullptr);
4129
4130     bool impIsCastHelperEligibleForClassProbe(GenTree* tree);
4131     bool impIsCastHelperMayHaveProfileData(CorInfoHelpFunc helper);
4132
4133     GenTree* impCastClassOrIsInstToTree(
4134         GenTree* op1, GenTree* op2, CORINFO_RESOLVED_TOKEN* pResolvedToken, bool isCastClass, IL_OFFSET ilOffset);
4135
4136     GenTree* impOptimizeCastClassOrIsInst(GenTree* op1, CORINFO_RESOLVED_TOKEN* pResolvedToken, bool isCastClass);
4137
4138     bool VarTypeIsMultiByteAndCanEnreg(var_types                type,
4139                                        CORINFO_CLASS_HANDLE     typeClass,
4140                                        unsigned*                typeSize,
4141                                        bool                     forReturn,
4142                                        bool                     isVarArg,
4143                                        CorInfoCallConvExtension callConv);
4144
4145     bool IsIntrinsicImplementedByUserCall(NamedIntrinsic intrinsicName);
4146     bool IsTargetIntrinsic(NamedIntrinsic intrinsicName);
4147     bool IsMathIntrinsic(NamedIntrinsic intrinsicName);
4148     bool IsMathIntrinsic(GenTree* tree);
4149
4150 private:
4151     //----------------- Importing the method ----------------------------------
4152
4153     CORINFO_CONTEXT_HANDLE impTokenLookupContextHandle; // The context used for looking up tokens.
4154
4155 #ifdef DEBUG
4156     unsigned    impCurOpcOffs;
4157     const char* impCurOpcName;
4158     bool        impNestedStackSpill;
4159
4160     // For displaying instrs with generated native code (-n:B)
4161     Statement* impLastILoffsStmt; // oldest stmt added for which we did not call SetLastILOffset().
4162     void       impNoteLastILoffs();
4163 #endif
4164
4165     // Debug info of current statement being imported. It gets set to contain
4166     // no IL location (!impCurStmtDI.GetLocation().IsValid) after it has been
4167     // set in the appended trees. Then it gets updated at IL instructions for
4168     // which we have to report mapping info.
4169     // It will always contain the current inline context.
4170     DebugInfo impCurStmtDI;
4171
4172     DebugInfo impCreateDIWithCurrentStackInfo(IL_OFFSET offs, bool isCall);
4173     void impCurStmtOffsSet(IL_OFFSET offs);
4174
4175     void impNoteBranchOffs();
4176
4177     unsigned impInitBlockLineInfo();
4178
4179     bool impIsThis(GenTree* obj);
4180
4181     void impPopCallArgs(CORINFO_SIG_INFO* sig, GenTreeCall* call);
4182
4183 public:
4184     static bool impCheckImplicitArgumentCoercion(var_types sigType, var_types nodeType);
4185
4186 private:
4187     void impPopReverseCallArgs(CORINFO_SIG_INFO* sig, GenTreeCall* call, unsigned skipReverseCount);
4188
4189     //---------------- Spilling the importer stack ----------------------------
4190
4191     // The maximum number of bytes of IL processed without clean stack state.
4192     // It allows to limit the maximum tree size and depth.
4193     static const unsigned MAX_TREE_SIZE = 200;
4194     bool impCanSpillNow(OPCODE prevOpcode);
4195
4196     struct PendingDsc
4197     {
4198         PendingDsc* pdNext;
4199         BasicBlock* pdBB;
4200         SavedStack  pdSavedStack;
4201     };
4202
4203     PendingDsc* impPendingList; // list of BBs currently waiting to be imported.
4204     PendingDsc* impPendingFree; // Freed up dscs that can be reused
4205
4206     // We keep a byte-per-block map (dynamically extended) in the top-level Compiler object of a compilation.
4207     JitExpandArray<BYTE> impPendingBlockMembers;
4208
4209     // Return the byte for "b" (allocating/extending impPendingBlockMembers if necessary.)
4210     // Operates on the map in the top-level ancestor.
4211     BYTE impGetPendingBlockMember(BasicBlock* blk)
4212     {
4213         return impInlineRoot()->impPendingBlockMembers.Get(blk->bbInd());
4214     }
4215
4216     // Set the byte for "b" to "val" (allocating/extending impPendingBlockMembers if necessary.)
4217     // Operates on the map in the top-level ancestor.
4218     void impSetPendingBlockMember(BasicBlock* blk, BYTE val)
4219     {
4220         impInlineRoot()->impPendingBlockMembers.Set(blk->bbInd(), val);
4221     }
4222
4223     bool impCanReimport;
4224
4225     bool impSpillStackEntry(unsigned level,
4226                             unsigned varNum
4227 #ifdef DEBUG
4228                             ,
4229                             bool        bAssertOnRecursion,
4230                             const char* reason
4231 #endif
4232                             );
4233
4234     void impSpillStackEnsure(bool spillLeaves = false);
4235     void impEvalSideEffects();
4236     void impSpillSpecialSideEff();
4237     void impSpillSideEffect(bool spillGlobEffects, unsigned chkLevel DEBUGARG(const char* reason));
4238     void impSpillSideEffects(bool spillGlobEffects, unsigned chkLevel DEBUGARG(const char* reason));
4239     void impSpillLclRefs(unsigned lclNum, unsigned chkLevel);
4240
4241     BasicBlock* impPushCatchArgOnStack(BasicBlock* hndBlk, CORINFO_CLASS_HANDLE clsHnd, bool isSingleBlockFilter);
4242
4243     bool impBlockIsInALoop(BasicBlock* block);
4244     void impImportBlockCode(BasicBlock* block);
4245
4246     void impReimportMarkBlock(BasicBlock* block);
4247     void impReimportMarkSuccessors(BasicBlock* block);
4248
4249     void impVerifyEHBlock(BasicBlock* block, bool isTryStart);
4250
4251     void impImportBlockPending(BasicBlock* block);
4252
4253     // Similar to impImportBlockPending, but assumes that block has already been imported once and is being
4254     // reimported for some reason.  It specifically does *not* look at verCurrentState to set the EntryState
4255     // for the block, but instead, just re-uses the block's existing EntryState.
4256     void impReimportBlockPending(BasicBlock* block);
4257
4258     var_types impGetByRefResultType(genTreeOps oper, bool fUnsigned, GenTree** pOp1, GenTree** pOp2);
4259
4260     void impImportBlock(BasicBlock* block);
4261
4262     // Assumes that "block" is a basic block that completes with a non-empty stack. We will assign the values
4263     // on the stack to local variables (the "spill temp" variables). The successor blocks will assume that
4264     // its incoming stack contents are in those locals. This requires "block" and its successors to agree on
4265     // the variables that will be used -- and for all the predecessors of those successors, and the
4266     // successors of those predecessors, etc. Call such a set of blocks closed under alternating
4267     // successor/predecessor edges a "spill clique." A block is a "predecessor" or "successor" member of the
4268     // clique (or, conceivably, both). Each block has a specified sequence of incoming and outgoing spill
4269     // temps. If "block" already has its outgoing spill temps assigned (they are always a contiguous series
4270     // of local variable numbers, so we represent them with the base local variable number), returns that.
4271     // Otherwise, picks a set of spill temps, and propagates this choice to all blocks in the spill clique of
4272     // which "block" is a member (asserting, in debug mode, that no block in this clique had its spill temps
4273     // chosen already. More precisely, that the incoming or outgoing spill temps are not chosen, depending
4274     // on which kind of member of the clique the block is).
4275     unsigned impGetSpillTmpBase(BasicBlock* block);
4276
4277     // Assumes that "block" is a basic block that completes with a non-empty stack. We have previously
4278     // assigned the values on the stack to local variables (the "spill temp" variables). The successor blocks
4279     // will assume that its incoming stack contents are in those locals. This requires "block" and its
4280     // successors to agree on the variables and their types that will be used.  The CLI spec allows implicit
4281     // conversions between 'int' and 'native int' or 'float' and 'double' stack types. So one predecessor can
4282     // push an int and another can push a native int.  For 64-bit we have chosen to implement this by typing
4283     // the "spill temp" as native int, and then importing (or re-importing as needed) so that all the
4284     // predecessors in the "spill clique" push a native int (sign-extending if needed), and all the
4285     // successors receive a native int. Similarly float and double are unified to double.
4286     // This routine is called after a type-mismatch is detected, and it will walk the spill clique to mark
4287     // blocks for re-importation as appropriate (both successors, so they get the right incoming type, and
4288     // predecessors, so they insert an upcast if needed).
4289     void impReimportSpillClique(BasicBlock* block);
4290
4291     // When we compute a "spill clique" (see above) these byte-maps are allocated to have a byte per basic
4292     // block, and represent the predecessor and successor members of the clique currently being computed.
4293     // *** Access to these will need to be locked in a parallel compiler.
4294     JitExpandArray<BYTE> impSpillCliquePredMembers;
4295     JitExpandArray<BYTE> impSpillCliqueSuccMembers;
4296
4297     enum SpillCliqueDir
4298     {
4299         SpillCliquePred,
4300         SpillCliqueSucc
4301     };
4302
4303     // Abstract class for receiving a callback while walking a spill clique
4304     class SpillCliqueWalker
4305     {
4306     public:
4307         virtual void Visit(SpillCliqueDir predOrSucc, BasicBlock* blk) = 0;
4308     };
4309
4310     // This class is used for setting the bbStkTempsIn and bbStkTempsOut on the blocks within a spill clique
4311     class SetSpillTempsBase : public SpillCliqueWalker
4312     {
4313         unsigned m_baseTmp;
4314
4315     public:
4316         SetSpillTempsBase(unsigned baseTmp) : m_baseTmp(baseTmp)
4317         {
4318         }
4319         virtual void Visit(SpillCliqueDir predOrSucc, BasicBlock* blk);
4320     };
4321
4322     // This class is used for implementing impReimportSpillClique part on each block within the spill clique
4323     class ReimportSpillClique : public SpillCliqueWalker
4324     {
4325         Compiler* m_pComp;
4326
4327     public:
4328         ReimportSpillClique(Compiler* pComp) : m_pComp(pComp)
4329         {
4330         }
4331         virtual void Visit(SpillCliqueDir predOrSucc, BasicBlock* blk);
4332     };
4333
4334     // This is the heart of the algorithm for walking spill cliques. It invokes callback->Visit for each
4335     // predecessor or successor within the spill clique
4336     void impWalkSpillCliqueFromPred(BasicBlock* pred, SpillCliqueWalker* callback);
4337
4338     // For a BasicBlock that has already been imported, the EntryState has an array of GenTrees for the
4339     // incoming locals. This walks that list an resets the types of the GenTrees to match the types of
4340     // the VarDscs. They get out of sync when we have int/native int issues (see impReimportSpillClique).
4341     void impRetypeEntryStateTemps(BasicBlock* blk);
4342
4343     BYTE impSpillCliqueGetMember(SpillCliqueDir predOrSucc, BasicBlock* blk);
4344     void impSpillCliqueSetMember(SpillCliqueDir predOrSucc, BasicBlock* blk, BYTE val);
4345
4346     GenTreeLclVar* impCreateLocalNode(unsigned lclNum DEBUGARG(IL_OFFSET offset));
4347     void impLoadVar(unsigned lclNum, IL_OFFSET offset);
4348     void impLoadArg(unsigned ilArgNum, IL_OFFSET offset);
4349     void impLoadLoc(unsigned ilLclNum, IL_OFFSET offset);
4350     bool impReturnInstruction(int prefixFlags, OPCODE& opcode);
4351     void impPoisonImplicitByrefsBeforeReturn();
4352
4353     // A free list of linked list nodes used to represent to-do stacks of basic blocks.
4354     struct BlockListNode
4355     {
4356         BasicBlock*    m_blk;
4357         BlockListNode* m_next;
4358         BlockListNode(BasicBlock* blk, BlockListNode* next = nullptr) : m_blk(blk), m_next(next)
4359         {
4360         }
4361         void* operator new(size_t sz, Compiler* comp);
4362     };
4363     BlockListNode* impBlockListNodeFreeList;
4364
4365     void FreeBlockListNode(BlockListNode* node);
4366
4367     var_types mangleVarArgsType(var_types type);
4368
4369     regNumber getCallArgIntRegister(regNumber floatReg);
4370     regNumber getCallArgFloatRegister(regNumber intReg);
4371
4372     static unsigned jitTotalMethodCompiled;
4373
4374 #ifdef DEBUG
4375     static LONG jitNestingLevel;
4376 #endif // DEBUG
4377
4378     static bool impIsInvariant(const GenTree* tree);
4379     static bool impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut = nullptr);
4380
4381     void impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, InlineResult* inlineResult);
4382
4383     // STATIC inlining decision based on the IL code.
4384     void impCanInlineIL(CORINFO_METHOD_HANDLE fncHandle,
4385                         CORINFO_METHOD_INFO*  methInfo,
4386                         bool                  forceInline,
4387                         InlineResult*         inlineResult);
4388
4389     void impCheckCanInline(GenTreeCall*           call,
4390                            uint8_t                candidateIndex,
4391                            CORINFO_METHOD_HANDLE  fncHandle,
4392                            unsigned               methAttr,
4393                            CORINFO_CONTEXT_HANDLE exactContextHnd,
4394                            InlineCandidateInfo**  ppInlineCandidateInfo,
4395                            InlineResult*          inlineResult);
4396
4397     void impInlineRecordArgInfo(InlineInfo* pInlineInfo, CallArg* arg, unsigned argNum, InlineResult* inlineResult);
4398
4399     void impInlineInitVars(InlineInfo* pInlineInfo);
4400
4401     unsigned impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reason));
4402
4403     GenTree* impInlineFetchArg(unsigned lclNum, InlArgInfo* inlArgInfo, InlLclVarInfo* lclTypeInfo);
4404
4405     bool impInlineIsThis(GenTree* tree, InlArgInfo* inlArgInfo);
4406
4407     bool impInlineIsGuaranteedThisDerefBeforeAnySideEffects(GenTree*    additionalTree,
4408                                                             CallArgs*   additionalCallArgs,
4409                                                             GenTree*    dereferencedAddress,
4410                                                             InlArgInfo* inlArgInfo);
4411
4412     void impMarkInlineCandidate(GenTree*               call,
4413                                 CORINFO_CONTEXT_HANDLE exactContextHnd,
4414                                 bool                   exactContextNeedsRuntimeLookup,
4415                                 CORINFO_CALL_INFO*     callInfo,
4416                                 IL_OFFSET              ilOffset);
4417
4418     void impMarkInlineCandidateHelper(GenTreeCall*           call,
4419                                       uint8_t                candidateIndex,
4420                                       CORINFO_CONTEXT_HANDLE exactContextHnd,
4421                                       bool                   exactContextNeedsRuntimeLookup,
4422                                       CORINFO_CALL_INFO*     callInfo,
4423                                       IL_OFFSET              ilOffset,
4424                                       InlineResult*          inlineResult);
4425
4426     bool impTailCallRetTypeCompatible(bool                     allowWidening,
4427                                       var_types                callerRetType,
4428                                       CORINFO_CLASS_HANDLE     callerRetTypeClass,
4429                                       CorInfoCallConvExtension callerCallConv,
4430                                       var_types                calleeRetType,
4431                                       CORINFO_CLASS_HANDLE     calleeRetTypeClass,
4432                                       CorInfoCallConvExtension calleeCallConv);
4433
4434     bool impIsTailCallILPattern(
4435         bool tailPrefixed, OPCODE curOpcode, const BYTE* codeAddrOfNextOpcode, const BYTE* codeEnd, bool isRecursive);
4436
4437     bool impIsImplicitTailCallCandidate(
4438         OPCODE curOpcode, const BYTE* codeAddrOfNextOpcode, const BYTE* codeEnd, int prefixFlags, bool isRecursive);
4439
4440     bool impIsClassExact(CORINFO_CLASS_HANDLE classHnd);
4441     bool impCanSkipCovariantStoreCheck(GenTree* value, GenTree* array);
4442
4443     methodPointerInfo* impAllocateMethodPointerInfo(const CORINFO_RESOLVED_TOKEN& token, mdToken tokenConstrained);
4444
4445     /*
4446     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
4447     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
4448     XX                                                                           XX
4449     XX                           FlowGraph                                       XX
4450     XX                                                                           XX
4451     XX   Info about the basic-blocks, their contents and the flow analysis       XX
4452     XX                                                                           XX
4453     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
4454     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
4455     */
4456
4457 public:
4458     BasicBlock* fgFirstBB;        // Beginning of the basic block list
4459     BasicBlock* fgLastBB;         // End of the basic block list
4460     BasicBlock* fgFirstColdBlock; // First block to be placed in the cold section
4461     BasicBlock* fgEntryBB;        // For OSR, the original method's entry point
4462     BasicBlock* fgOSREntryBB;     // For OSR, the logical entry point (~ patchpoint)
4463 #if defined(FEATURE_EH_FUNCLETS)
4464     BasicBlock* fgFirstFuncletBB; // First block of outlined funclets (to allow block insertion before the funclets)
4465 #endif
4466     BasicBlock* fgFirstBBScratch;   // Block inserted for initialization stuff. Is nullptr if no such block has been
4467                                     // created.
4468     BasicBlockList* fgReturnBlocks; // list of BBJ_RETURN blocks
4469     unsigned        fgEdgeCount;    // # of control flow edges between the BBs
4470     unsigned        fgBBcount;      // # of BBs in the method
4471 #ifdef DEBUG
4472     unsigned                     fgBBcountAtCodegen; // # of BBs in the method at the start of codegen
4473     jitstd::vector<BasicBlock*>* fgBBOrder;          // ordered vector of BBs
4474 #endif
4475     unsigned     fgBBNumMax;           // The max bbNum that has been assigned to basic blocks
4476     unsigned     fgDomBBcount;         // # of BBs for which we have dominator and reachability information
4477     BasicBlock** fgBBReversePostorder; // Blocks in reverse postorder
4478
4479     // After the dominance tree is computed, we cache a DFS preorder number and DFS postorder number to compute
4480     // dominance queries in O(1). fgDomTreePreOrder and fgDomTreePostOrder are arrays giving the block's preorder and
4481     // postorder number, respectively. The arrays are indexed by basic block number. (Note that blocks are numbered
4482     // starting from one. Thus, we always waste element zero. This makes debugging easier and makes the code less likely
4483     // to suffer from bugs stemming from forgetting to add or subtract one from the block number to form an array
4484     // index). The arrays are of size fgBBNumMax + 1.
4485     unsigned* fgDomTreePreOrder;
4486     unsigned* fgDomTreePostOrder;
4487
4488     // Dominator tree used by SSA construction and copy propagation (the two are expected to use the same tree
4489     // in order to avoid the need for SSA reconstruction and an "out of SSA" phase).
4490     DomTreeNode* fgSsaDomTree;
4491
4492     bool fgBBVarSetsInited;
4493
4494     // Track how many artificial ref counts we've added to fgEntryBB (for OSR)
4495     unsigned fgEntryBBExtraRefs;
4496
4497     // Allocate array like T* a = new T[fgBBNumMax + 1];
4498     // Using helper so we don't keep forgetting +1.
4499     template <typename T>
4500     T* fgAllocateTypeForEachBlk(CompMemKind cmk = CMK_Unknown)
4501     {
4502         return getAllocator(cmk).allocate<T>(fgBBNumMax + 1);
4503     }
4504
4505     // BlockSets are relative to a specific set of BasicBlock numbers. If that changes
4506     // (if the blocks are renumbered), this changes. BlockSets from different epochs
4507     // cannot be meaningfully combined. Note that new blocks can be created with higher
4508     // block numbers without changing the basic block epoch. These blocks *cannot*
4509     // participate in a block set until the blocks are all renumbered, causing the epoch
4510     // to change. This is useful if continuing to use previous block sets is valuable.
4511     // If the epoch is zero, then it is uninitialized, and block sets can't be used.
4512     unsigned fgCurBBEpoch;
4513
4514     unsigned GetCurBasicBlockEpoch()
4515     {
4516         return fgCurBBEpoch;
4517     }
4518
4519     // The number of basic blocks in the current epoch. When the blocks are renumbered,
4520     // this is fgBBcount. As blocks are added, fgBBcount increases, fgCurBBEpochSize remains
4521     // the same, until a new BasicBlock epoch is created, such as when the blocks are all renumbered.
4522     unsigned fgCurBBEpochSize;
4523
4524     // The number of "size_t" elements required to hold a bitset large enough for fgCurBBEpochSize
4525     // bits. This is precomputed to avoid doing math every time BasicBlockBitSetTraits::GetArrSize() is called.
4526     unsigned fgBBSetCountInSizeTUnits;
4527
4528     void NewBasicBlockEpoch()
4529     {
4530         INDEBUG(unsigned oldEpochArrSize = fgBBSetCountInSizeTUnits);
4531
4532         // We have a new epoch. Compute and cache the size needed for new BlockSets.
4533         fgCurBBEpoch++;
4534         fgCurBBEpochSize = fgBBNumMax + 1;
4535         fgBBSetCountInSizeTUnits =
4536             roundUp(fgCurBBEpochSize, (unsigned)(sizeof(size_t) * 8)) / unsigned(sizeof(size_t) * 8);
4537
4538 #ifdef DEBUG
4539         // All BlockSet objects are now invalid!
4540         fgReachabilitySetsValid = false; // the bbReach sets are now invalid!
4541         fgEnterBlksSetValid     = false; // the fgEnterBlks set is now invalid!
4542
4543         if (verbose)
4544         {
4545             unsigned epochArrSize = BasicBlockBitSetTraits::GetArrSize(this);
4546             printf("\nNew BlockSet epoch %d, # of blocks (including unused BB00): %u, bitset array size: %u (%s)",
4547                    fgCurBBEpoch, fgCurBBEpochSize, epochArrSize, (epochArrSize <= 1) ? "short" : "long");
4548             if ((fgCurBBEpoch != 1) && ((oldEpochArrSize <= 1) != (epochArrSize <= 1)))
4549             {
4550                 // If we're not just establishing the first epoch, and the epoch array size has changed such that we're
4551                 // going to change our bitset representation from short (just a size_t bitset) to long (a pointer to an
4552                 // array of size_t bitsets), then print that out.
4553                 printf("; NOTE: BlockSet size was previously %s!", (oldEpochArrSize <= 1) ? "short" : "long");
4554             }
4555             printf("\n");
4556         }
4557 #endif // DEBUG
4558     }
4559
4560     void EnsureBasicBlockEpoch()
4561     {
4562         if (fgCurBBEpochSize != fgBBNumMax + 1)
4563         {
4564             NewBasicBlockEpoch();
4565         }
4566     }
4567
4568     BasicBlock* fgNewBasicBlock(BBjumpKinds jumpKind);
4569     bool fgEnsureFirstBBisScratch();
4570     bool fgFirstBBisScratch();
4571     bool fgBBisScratch(BasicBlock* block);
4572
4573     void fgExtendEHRegionBefore(BasicBlock* block);
4574     void fgExtendEHRegionAfter(BasicBlock* block);
4575
4576     BasicBlock* fgNewBBbefore(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion);
4577
4578     BasicBlock* fgNewBBafter(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion);
4579
4580     BasicBlock* fgNewBBFromTreeAfter(BBjumpKinds jumpKind, BasicBlock* block, GenTree* tree, DebugInfo& debugInfo, bool updateSideEffects = false);
4581
4582     BasicBlock* fgNewBBinRegion(BBjumpKinds jumpKind,
4583                                 unsigned    tryIndex,
4584                                 unsigned    hndIndex,
4585                                 BasicBlock* nearBlk,
4586                                 bool        putInFilter = false,
4587                                 bool        runRarely   = false,
4588                                 bool        insertAtEnd = false);
4589
4590     BasicBlock* fgNewBBinRegion(BBjumpKinds jumpKind,
4591                                 BasicBlock* srcBlk,
4592                                 bool        runRarely   = false,
4593                                 bool        insertAtEnd = false);
4594
4595     BasicBlock* fgNewBBinRegion(BBjumpKinds jumpKind);
4596
4597     BasicBlock* fgNewBBinRegionWorker(BBjumpKinds jumpKind,
4598                                       BasicBlock* afterBlk,
4599                                       unsigned    xcptnIndex,
4600                                       bool        putInTryRegion);
4601
4602     void fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk);
4603     void fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk);
4604     void fgUnlinkBlock(BasicBlock* block);
4605
4606 #ifdef FEATURE_JIT_METHOD_PERF
4607     unsigned fgMeasureIR();
4608 #endif // FEATURE_JIT_METHOD_PERF
4609
4610     bool fgModified;             // True if the flow graph has been modified recently
4611     bool fgPredsComputed;        // Have we computed the bbPreds list
4612     bool fgDomsComputed;         // Have we computed the dominator sets?
4613     bool fgReturnBlocksComputed; // Have we computed the return blocks list?
4614     bool fgOptimizedFinally;     // Did we optimize any try-finallys?
4615
4616     bool fgHasSwitch; // any BBJ_SWITCH jumps?
4617
4618     BlockSet fgEnterBlks; // Set of blocks which have a special transfer of control; the "entry" blocks plus EH handler
4619                           // begin blocks.
4620 #if defined(FEATURE_EH_FUNCLETS) && defined(TARGET_ARM)
4621     BlockSet fgAlwaysBlks; // Set of blocks which are BBJ_ALWAYS part  of BBJ_CALLFINALLY/BBJ_ALWAYS pair that should
4622                            // never be removed due to a requirement to use the BBJ_ALWAYS for generating code and
4623                            // not have "retless" blocks.
4624
4625 #endif // defined(FEATURE_EH_FUNCLETS) && defined(TARGET_ARM)
4626
4627 #ifdef DEBUG
4628     bool fgReachabilitySetsValid; // Are the bbReach sets valid?
4629     bool fgEnterBlksSetValid;     // Is the fgEnterBlks set valid?
4630 #endif                            // DEBUG
4631
4632     bool fgRemoveRestOfBlock; // true if we know that we will throw
4633     bool fgStmtRemoved;       // true if we remove statements -> need new DFA
4634
4635     enum FlowGraphOrder
4636     {
4637         FGOrderTree,
4638         FGOrderLinear
4639     };
4640     // There are two modes for ordering of the trees.
4641     //  - In FGOrderTree, the dominant ordering is the tree order, and the nodes contained in
4642     //    each tree and sub-tree are contiguous, and can be traversed (in gtNext/gtPrev order)
4643     //    by traversing the tree according to the order of the operands.
4644     //  - In FGOrderLinear, the dominant ordering is the linear order.
4645     FlowGraphOrder fgOrder;
4646
4647     // The following are flags that keep track of the state of internal data structures
4648
4649     // Even in tree form (fgOrder == FGOrderTree) the trees are threaded in a
4650     // doubly linked lists during certain phases of the compilation.
4651     // - Local morph threads all locals to be used for early liveness and
4652     //   forward sub when optimizing. This is kept valid until after forward sub.
4653     //   The first local is kept in Statement::GetTreeList() and the last
4654     //   local in Statement::GetTreeListEnd(). fgSequenceLocals can be used
4655     //   to (re-)sequence a statement into this form, and
4656     //   Statement::LocalsTreeList for range-based iteration. The order must
4657     //   match tree order.
4658     //
4659     // - fgSetBlockOrder threads all nodes. This is kept valid until LIR form.
4660     //   In this form the first node is given by Statement::GetTreeList and the
4661     //   last node is given by Statement::GetRootNode(). fgSetStmtSeq can be used
4662     //   to (re-)sequence a statement into this form, and Statement::TreeList for
4663     //   range-based iteration. The order must match tree order.
4664     //
4665     // - Rationalization links all nodes into linear form which is kept until
4666     //   the end of compilation. The first and last nodes are stored in the block.
4667     NodeThreading fgNodeThreading;
4668     bool          fgCanRelocateEHRegions;   // true if we are allowed to relocate the EH regions
4669     bool          fgEdgeWeightsComputed;    // true after we have called fgComputeEdgeWeights
4670     bool          fgHaveValidEdgeWeights;   // true if we were successful in computing all of the edge weights
4671     bool          fgSlopUsedInEdgeWeights;  // true if their was some slop used when computing the edge weights
4672     bool          fgRangeUsedInEdgeWeights; // true if some of the edgeWeight are expressed in Min..Max form
4673     weight_t      fgCalledCount;            // count of the number of times this method was called
4674                                             // This is derived from the profile data
4675                                             // or is BB_UNITY_WEIGHT when we don't have profile data
4676
4677 #if defined(FEATURE_EH_FUNCLETS)
4678     bool fgFuncletsCreated; // true if the funclet creation phase has been run
4679 #endif                      // FEATURE_EH_FUNCLETS
4680
4681     bool fgGlobalMorph; // indicates if we are during the global morphing phase
4682                         // since fgMorphTree can be called from several places
4683
4684     bool     impBoxTempInUse; // the temp below is valid and available
4685     unsigned impBoxTemp;      // a temporary that is used for boxing
4686
4687 #ifdef DEBUG
4688     bool jitFallbackCompile; // Are we doing a fallback compile? That is, have we executed a NO_WAY assert,
4689                              //   and we are trying to compile again in a "safer", minopts mode?
4690 #endif
4691
4692 #if defined(DEBUG)
4693     unsigned impInlinedCodeSize;
4694     bool     fgPrintInlinedMethods;
4695 #endif
4696
4697     jitstd::vector<FlowEdge*>* fgPredListSortVector;
4698
4699     //-------------------------------------------------------------------------
4700
4701     void fgInit();
4702
4703     PhaseStatus fgImport();
4704
4705     PhaseStatus fgTransformIndirectCalls();
4706
4707     PhaseStatus fgTransformPatchpoints();
4708
4709     PhaseStatus fgMorphInit();
4710
4711     PhaseStatus fgInline();
4712
4713     PhaseStatus fgRemoveEmptyTry();
4714
4715     PhaseStatus fgRemoveEmptyFinally();
4716
4717     PhaseStatus fgMergeFinallyChains();
4718
4719     PhaseStatus fgCloneFinally();
4720
4721     void fgCleanupContinuation(BasicBlock* continuation);
4722
4723 #if defined(FEATURE_EH_FUNCLETS) && defined(TARGET_ARM)
4724
4725     PhaseStatus fgUpdateFinallyTargetFlags();
4726
4727     void fgClearAllFinallyTargetBits();
4728
4729     void fgAddFinallyTargetFlags();
4730
4731     void fgFixFinallyTargetFlags(BasicBlock* pred, BasicBlock* succ, BasicBlock* newBlock);
4732
4733 #endif // defined(FEATURE_EH_FUNCLETS) && defined(TARGET_ARM)
4734     PhaseStatus fgTailMergeThrows();
4735     void fgTailMergeThrowsFallThroughHelper(BasicBlock* predBlock,
4736                                             BasicBlock* nonCanonicalBlock,
4737                                             BasicBlock* canonicalBlock,
4738                                             FlowEdge*   predEdge);
4739     void fgTailMergeThrowsJumpToHelper(BasicBlock* predBlock,
4740                                        BasicBlock* nonCanonicalBlock,
4741                                        BasicBlock* canonicalBlock,
4742                                        FlowEdge*   predEdge);
4743
4744     bool fgRetargetBranchesToCanonicalCallFinally(BasicBlock*      block,
4745                                                   BasicBlock*      handler,
4746                                                   BlockToBlockMap& continuationMap);
4747
4748     GenTree* fgGetCritSectOfStaticMethod();
4749
4750 #if defined(FEATURE_EH_FUNCLETS)
4751
4752     void fgAddSyncMethodEnterExit();
4753
4754     GenTree* fgCreateMonitorTree(unsigned lvaMonitorBool, unsigned lvaThisVar, BasicBlock* block, bool enter);
4755
4756     void fgConvertSyncReturnToLeave(BasicBlock* block);
4757
4758 #endif // FEATURE_EH_FUNCLETS
4759
4760     void fgAddReversePInvokeEnterExit();
4761
4762     bool fgMoreThanOneReturnBlock();
4763
4764     // The number of separate return points in the method.
4765     unsigned fgReturnCount;
4766
4767     PhaseStatus fgAddInternal();
4768
4769     enum class FoldResult
4770     {
4771         FOLD_DID_NOTHING,
4772         FOLD_CHANGED_CONTROL_FLOW,
4773         FOLD_REMOVED_LAST_STMT,
4774         FOLD_ALTERED_LAST_STMT,
4775     };
4776
4777     FoldResult fgFoldConditional(BasicBlock* block);
4778
4779     void fgMorphStmts(BasicBlock* block);
4780     void fgMorphBlocks();
4781
4782     void fgMergeBlockReturn(BasicBlock* block);
4783
4784     bool fgMorphBlockStmt(BasicBlock* block, Statement* stmt DEBUGARG(const char* msg));
4785     void fgMorphStmtBlockOps(BasicBlock* block, Statement* stmt);
4786
4787     //------------------------------------------------------------------------------------------------------------
4788     // MorphMDArrayTempCache: a simple cache of compiler temporaries in the local variable table, used to minimize
4789     // the number of locals allocated when doing early multi-dimensional array operation expansion. Two types of
4790     // temps are created and cached (due to the two types of temps needed by the MD array expansion): TYP_INT and
4791     // TYP_REF. `GrabTemp` either returns an available temp from the cache or allocates a new temp and returns it
4792     // after adding it to the cache. `Reset` makes all the temps in the cache available for subsequent re-use.
4793     //
4794     class MorphMDArrayTempCache
4795     {
4796     private:
4797         class TempList
4798         {
4799         public:
4800             TempList(Compiler* compiler)
4801                 : m_compiler(compiler), m_first(nullptr), m_insertPtr(&m_first), m_nextAvail(nullptr)
4802             {
4803             }
4804
4805             unsigned GetTemp();
4806
4807             void Reset()
4808             {
4809                 m_nextAvail = m_first;
4810             }
4811
4812         private:
4813             struct Node
4814             {
4815                 Node(unsigned tmp) : next(nullptr), tmp(tmp)
4816                 {
4817                 }
4818
4819                 Node*    next;
4820                 unsigned tmp;
4821             };
4822
4823             Compiler* m_compiler;
4824             Node*     m_first;
4825             Node**    m_insertPtr;
4826             Node*     m_nextAvail;
4827         };
4828
4829         TempList intTemps; // Temps for genActualType() == TYP_INT
4830         TempList refTemps; // Temps for TYP_REF
4831
4832     public:
4833         MorphMDArrayTempCache(Compiler* compiler) : intTemps(compiler), refTemps(compiler)
4834         {
4835         }
4836
4837         unsigned GrabTemp(var_types type);
4838
4839         void Reset()
4840         {
4841             intTemps.Reset();
4842             refTemps.Reset();
4843         }
4844     };
4845
4846     bool fgMorphArrayOpsStmt(MorphMDArrayTempCache* pTempCache, BasicBlock* block, Statement* stmt);
4847     PhaseStatus fgMorphArrayOps();
4848
4849     void fgSetOptions();
4850
4851 #ifdef DEBUG
4852     void fgPreExpandQmarkChecks(GenTree* expr);
4853     void fgPostExpandQmarkChecks();
4854 #endif
4855
4856     IL_OFFSET fgFindBlockILOffset(BasicBlock* block);
4857     void fgFixEntryFlowForOSR();
4858
4859     BasicBlock* fgSplitBlockAtBeginning(BasicBlock* curr);
4860     BasicBlock* fgSplitBlockAtEnd(BasicBlock* curr);
4861     BasicBlock* fgSplitBlockAfterStatement(BasicBlock* curr, Statement* stmt);
4862     BasicBlock* fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node); // for LIR
4863     BasicBlock* fgSplitEdge(BasicBlock* curr, BasicBlock* succ);
4864     BasicBlock* fgSplitBlockBeforeTree(BasicBlock* block, Statement* stmt, GenTree* splitPoint, Statement** firstNewStmt, GenTree*** splitNodeUse);
4865
4866     Statement* fgNewStmtFromTree(GenTree* tree, BasicBlock* block, const DebugInfo& di);
4867     Statement* fgNewStmtFromTree(GenTree* tree);
4868     Statement* fgNewStmtFromTree(GenTree* tree, BasicBlock* block);
4869     Statement* fgNewStmtFromTree(GenTree* tree, const DebugInfo& di);
4870
4871     GenTree* fgGetTopLevelQmark(GenTree* expr, GenTree** ppDst = nullptr);
4872     void fgExpandQmarkForCastInstOf(BasicBlock* block, Statement* stmt);
4873     void fgExpandQmarkStmt(BasicBlock* block, Statement* stmt);
4874     void fgExpandQmarkNodes();
4875
4876     // Do "simple lowering."  This functionality is (conceptually) part of "general"
4877     // lowering that is distributed between fgMorph and the lowering phase of LSRA.
4878     PhaseStatus fgSimpleLowering();
4879
4880     bool fgSimpleLowerCastOfSmpOp(LIR::Range& range, GenTreeCast* cast);
4881
4882 #if FEATURE_LOOP_ALIGN
4883     PhaseStatus placeLoopAlignInstructions();
4884 #endif
4885
4886     // This field keep the R2R helper call that would be inserted to trigger the constructor
4887     // of the static class. It is set as nongc or gc static base if they are imported, so
4888     // CSE can eliminate the repeated call, or the chepeast helper function that triggers it.
4889     CorInfoHelpFunc m_preferredInitCctor;
4890     void            fgSetPreferredInitCctor();
4891
4892     GenTree* fgInitThisClass();
4893
4894     GenTreeCall* fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfoHelpFunc helper, uint32_t typeIndex = 0);
4895
4896     GenTreeCall* fgGetSharedCCtor(CORINFO_CLASS_HANDLE cls);
4897
4898     bool backendRequiresLocalVarLifetimes()
4899     {
4900         return !opts.MinOpts() || m_pLinearScan->willEnregisterLocalVars();
4901     }
4902
4903     void fgLocalVarLiveness();
4904
4905     void fgLocalVarLivenessInit();
4906
4907     void fgPerNodeLocalVarLiveness(GenTree* node);
4908     void fgPerBlockLocalVarLiveness();
4909
4910 #if defined(FEATURE_HW_INTRINSICS)
4911     void fgPerNodeLocalVarLiveness(GenTreeHWIntrinsic* hwintrinsic);
4912 #endif // FEATURE_HW_INTRINSICS
4913
4914     void fgAddHandlerLiveVars(BasicBlock* block, VARSET_TP& ehHandlerLiveVars);
4915
4916     void fgLiveVarAnalysis(bool updateInternalOnly = false);
4917
4918     void fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call);
4919
4920     void fgComputeLifeTrackedLocalUse(VARSET_TP& life, LclVarDsc& varDsc, GenTreeLclVarCommon* node);
4921     bool fgComputeLifeTrackedLocalDef(VARSET_TP&           life,
4922                                       VARSET_VALARG_TP     keepAliveVars,
4923                                       LclVarDsc&           varDsc,
4924                                       GenTreeLclVarCommon* node);
4925     bool fgComputeLifeUntrackedLocal(VARSET_TP&           life,
4926                                      VARSET_VALARG_TP     keepAliveVars,
4927                                      LclVarDsc&           varDsc,
4928                                      GenTreeLclVarCommon* lclVarNode);
4929     bool fgComputeLifeLocal(VARSET_TP& life, VARSET_VALARG_TP keepAliveVars, GenTree* lclVarNode);
4930
4931     GenTree* fgTryRemoveDeadStoreEarly(Statement* stmt, GenTreeLclVarCommon* dst);
4932
4933     void fgComputeLife(VARSET_TP&       life,
4934                        GenTree*         startNode,
4935                        GenTree*         endNode,
4936                        VARSET_VALARG_TP volatileVars,
4937                        bool* pStmtInfoDirty DEBUGARG(bool* treeModf));
4938
4939     void fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALARG_TP volatileVars);
4940
4941     bool fgTryRemoveNonLocal(GenTree* node, LIR::Range* blockRange);
4942
4943     bool fgTryRemoveDeadStoreLIR(GenTree* store, GenTreeLclVarCommon* lclNode, BasicBlock* block);
4944
4945     bool fgRemoveDeadStore(GenTree**        pTree,
4946                            LclVarDsc*       varDsc,
4947                            VARSET_VALARG_TP life,
4948                            bool*            doAgain,
4949                            bool*            pStmtInfoDirty,
4950                            bool* pStoreRemoved DEBUGARG(bool* treeModf));
4951
4952     void fgInterBlockLocalVarLiveness();
4953
4954     // Blocks: convenience methods for enabling range-based `for` iteration over the function's blocks, e.g.:
4955     // 1.   for (BasicBlock* const block : compiler->Blocks()) ...
4956     // 2.   for (BasicBlock* const block : compiler->Blocks(startBlock)) ...
4957     // 3.   for (BasicBlock* const block : compiler->Blocks(startBlock, endBlock)) ...
4958     // In case (1), the block list can be empty. In case (2), `startBlock` can be nullptr. In case (3),
4959     // both `startBlock` and `endBlock` must be non-null.
4960     //
4961     BasicBlockSimpleList Blocks() const
4962     {
4963         return BasicBlockSimpleList(fgFirstBB);
4964     }
4965
4966     BasicBlockSimpleList Blocks(BasicBlock* startBlock) const
4967     {
4968         return BasicBlockSimpleList(startBlock);
4969     }
4970
4971     BasicBlockRangeList Blocks(BasicBlock* startBlock, BasicBlock* endBlock) const
4972     {
4973         return BasicBlockRangeList(startBlock, endBlock);
4974     }
4975
4976     // This array, managed by the SSA numbering infrastructure, keeps "outlined composite SSA numbers".
4977     // See "SsaNumInfo::GetNum" for more details on when this is needed.
4978     JitExpandArrayStack<unsigned>* m_outlinedCompositeSsaNums;
4979
4980     // This map tracks nodes whose value numbers explicitly or implicitly depend on memory states.
4981     // The map provides the entry block of the most closely enclosing loop that
4982     // defines the memory region accessed when defining the nodes's VN.
4983     //
4984     // This information should be consulted when considering hoisting node out of a loop, as the VN
4985     // for the node will only be valid within the indicated loop.
4986     //
4987     // It is not fine-grained enough to track memory dependence within loops, so cannot be used
4988     // for more general code motion.
4989     //
4990     // If a node does not have an entry in the map we currently assume the VN is not memory dependent
4991     // and so memory does not constrain hoisting.
4992     //
4993     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, BasicBlock*> NodeToLoopMemoryBlockMap;
4994     NodeToLoopMemoryBlockMap* m_nodeToLoopMemoryBlockMap;
4995     NodeToLoopMemoryBlockMap* GetNodeToLoopMemoryBlockMap()
4996     {
4997         if (m_nodeToLoopMemoryBlockMap == nullptr)
4998         {
4999             m_nodeToLoopMemoryBlockMap = new (getAllocator()) NodeToLoopMemoryBlockMap(getAllocator());
5000         }
5001         return m_nodeToLoopMemoryBlockMap;
5002     }
5003
5004     typedef JitHashTable<void*, JitPtrKeyFuncs<void>, CORINFO_RUNTIME_LOOKUP> SignatureToLookupInfoMap;
5005     SignatureToLookupInfoMap* m_signatureToLookupInfoMap;
5006     SignatureToLookupInfoMap* GetSignatureToLookupInfoMap()
5007     {
5008         if (m_signatureToLookupInfoMap == nullptr)
5009         {
5010             m_signatureToLookupInfoMap = new (getAllocator()) SignatureToLookupInfoMap(getAllocator());
5011         }
5012         return m_signatureToLookupInfoMap;
5013     }
5014
5015     void optRecordLoopMemoryDependence(GenTree* tree, BasicBlock* block, ValueNum memoryVN);
5016     void optCopyLoopMemoryDependence(GenTree* fromTree, GenTree* toTree);
5017
5018     inline bool PreciseRefCountsRequired();
5019
5020     // Performs SSA conversion.
5021     PhaseStatus fgSsaBuild();
5022
5023     // Reset any data structures to the state expected by "fgSsaBuild", so it can be run again.
5024     void fgResetForSsa();
5025
5026     unsigned fgSsaPassesCompleted; // Number of times fgSsaBuild has been run.
5027     bool     fgSsaChecksEnabled;   // True if SSA info can be cross-checked versus IR
5028
5029 #ifdef DEBUG
5030     void DumpSsaSummary();
5031 #endif
5032
5033     // Returns "true" if this is a special variable that is never zero initialized in the prolog.
5034     inline bool fgVarIsNeverZeroInitializedInProlog(unsigned varNum);
5035
5036     // Returns "true" if the variable needs explicit zero initialization.
5037     inline bool fgVarNeedsExplicitZeroInit(unsigned varNum, bool bbInALoop, bool bbIsReturn);
5038
5039     // The value numbers for this compilation.
5040     ValueNumStore* vnStore;
5041
5042 public:
5043     ValueNumStore* GetValueNumStore()
5044     {
5045         return vnStore;
5046     }
5047
5048     // Do value numbering (assign a value number to each
5049     // tree node).
5050     PhaseStatus fgValueNumber();
5051
5052     void fgValueNumberLocalStore(GenTree*             storeNode,
5053                                  GenTreeLclVarCommon* lclDefNode,
5054                                  ssize_t              offset,
5055                                  unsigned             storeSize,
5056                                  ValueNumPair         value,
5057                                  bool                 normalize = true);
5058
5059     void fgValueNumberArrayElemLoad(GenTree* loadTree, VNFuncApp* addrFunc);
5060
5061     void fgValueNumberArrayElemStore(GenTree* storeNode, VNFuncApp* addrFunc, unsigned storeSize, ValueNum value);
5062
5063     void fgValueNumberFieldLoad(GenTree* loadTree, GenTree* baseAddr, FieldSeq* fieldSeq, ssize_t offset);
5064
5065     void fgValueNumberFieldStore(
5066         GenTree* storeNode, GenTree* baseAddr, FieldSeq* fieldSeq, ssize_t offset, unsigned storeSize, ValueNum value);
5067
5068     bool fgValueNumberConstLoad(GenTreeIndir* tree);
5069
5070     // Compute the value number for a byref-exposed load of the given type via the given pointerVN.
5071     ValueNum fgValueNumberByrefExposedLoad(var_types type, ValueNum pointerVN);
5072
5073     unsigned fgVNPassesCompleted; // Number of times fgValueNumber has been run.
5074
5075     // Utility functions for fgValueNumber.
5076
5077     // Perform value-numbering for the trees in "blk".
5078     void fgValueNumberBlock(BasicBlock* blk);
5079
5080     // Requires that "entryBlock" is the entry block of loop "loopNum", and that "loopNum" is the
5081     // innermost loop of which "entryBlock" is the entry.  Returns the value number that should be
5082     // assumed for the memoryKind at the start "entryBlk".
5083     ValueNum fgMemoryVNForLoopSideEffects(MemoryKind memoryKind, BasicBlock* entryBlock, unsigned loopNum);
5084
5085     // Called when an operation (performed by "tree", described by "msg") may cause the GcHeap to be mutated.
5086     // As GcHeap is a subset of ByrefExposed, this will also annotate the ByrefExposed mutation.
5087     void fgMutateGcHeap(GenTree* tree DEBUGARG(const char* msg));
5088
5089     // Called when an operation (performed by "tree", described by "msg") may cause an address-exposed local to be
5090     // mutated.
5091     void fgMutateAddressExposedLocal(GenTree* tree DEBUGARG(const char* msg));
5092
5093     // For a GC heap store at curTree, record the new curMemoryVN's and update curTree's MemorySsaMap.
5094     // As GcHeap is a subset of ByrefExposed, this will also record the ByrefExposed store.
5095     void recordGcHeapStore(GenTree* curTree, ValueNum gcHeapVN DEBUGARG(const char* msg));
5096
5097     // For a store to an address-exposed local at curTree, record the new curMemoryVN and update curTree's MemorySsaMap.
5098     void recordAddressExposedLocalStore(GenTree* curTree, ValueNum memoryVN DEBUGARG(const char* msg));
5099
5100     void fgSetCurrentMemoryVN(MemoryKind memoryKind, ValueNum newMemoryVN);
5101
5102     // Tree caused an update in the current memory VN.  If "tree" has an associated heap SSA #, record that
5103     // value in that SSA #.
5104     void fgValueNumberRecordMemorySsa(MemoryKind memoryKind, GenTree* tree);
5105
5106     // The input 'tree' is a leaf node that is a constant
5107     // Assign the proper value number to the tree
5108     void fgValueNumberTreeConst(GenTree* tree);
5109
5110     // If the VN store has been initialized, reassign the
5111     // proper value number to the constant tree.
5112     void fgUpdateConstTreeValueNumber(GenTree* tree);
5113
5114     // Assumes that all inputs to "tree" have had value numbers assigned; assigns a VN to tree.
5115     // (With some exceptions: the VN of the lhs of an assignment is assigned as part of the
5116     // assignment.)
5117     void fgValueNumberTree(GenTree* tree);
5118
5119     void fgValueNumberStore(GenTree* tree);
5120
5121     void fgValueNumberSsaVarDef(GenTreeLclVarCommon* lcl);
5122
5123     // Does value-numbering for a cast tree.
5124     void fgValueNumberCastTree(GenTree* tree);
5125
5126     // Does value-numbering for a bitcast tree.
5127     void fgValueNumberBitCast(GenTree* tree);
5128
5129     // Does value-numbering for an intrinsic tree.
5130     void fgValueNumberIntrinsic(GenTree* tree);
5131
5132     void fgValueNumberArrIndexAddr(GenTreeArrAddr* arrAddr);
5133
5134 #ifdef FEATURE_HW_INTRINSICS
5135     // Does value-numbering for a GT_HWINTRINSIC tree
5136     void fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree);
5137 #endif // FEATURE_HW_INTRINSICS
5138
5139     // Does value-numbering for a call.  We interpret some helper calls.
5140     void fgValueNumberCall(GenTreeCall* call);
5141
5142     // Does value-numbering for a helper representing a cast operation.
5143     void fgValueNumberCastHelper(GenTreeCall* call);
5144
5145     // Does value-numbering for a helper "call" that has a VN function symbol "vnf".
5146     void fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueNumPair vnpExc);
5147
5148     // Requires "helpCall" to be a helper call.  Assigns it a value number;
5149     // we understand the semantics of some of the calls.  Returns "true" if
5150     // the call may modify the heap (we assume arbitrary memory side effects if so).
5151     bool fgValueNumberHelperCall(GenTreeCall* helpCall);
5152
5153     // Requires that "helpFunc" is one of the pure Jit Helper methods.
5154     // Returns the corresponding VNFunc to use for value numbering
5155     VNFunc fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc);
5156
5157     // Adds the exception set for the current tree node which has a memory indirection operation
5158     void fgValueNumberAddExceptionSetForIndirection(GenTree* tree, GenTree* baseAddr);
5159
5160     // Adds the exception sets for the current tree node which is performing a division or modulus operation
5161     void fgValueNumberAddExceptionSetForDivision(GenTree* tree);
5162
5163     // Adds the exception set for the current tree node which is performing a overflow checking operation
5164     void fgValueNumberAddExceptionSetForOverflow(GenTree* tree);
5165
5166     // Adds the exception set for the current tree node which is performing a bounds check operation
5167     void fgValueNumberAddExceptionSetForBoundsCheck(GenTree* tree);
5168
5169     // Adds the exception set for the current tree node which is performing a ckfinite operation
5170     void fgValueNumberAddExceptionSetForCkFinite(GenTree* tree);
5171
5172     // Adds the exception sets for the current tree node
5173     void fgValueNumberAddExceptionSet(GenTree* tree);
5174
5175 #ifdef DEBUG
5176     void fgDebugCheckExceptionSets();
5177 #endif
5178
5179     // These are the current value number for the memory implicit variables while
5180     // doing value numbering.  These are the value numbers under the "liberal" interpretation
5181     // of memory values; the "conservative" interpretation needs no VN, since every access of
5182     // memory yields an unknown value.
5183     ValueNum fgCurMemoryVN[MemoryKindCount];
5184
5185     // Return a "pseudo"-class handle for an array element type.  If "elemType" is TYP_STRUCT,
5186     // requires "elemStructType" to be non-null (and to have a low-order zero).  Otherwise, low order bit
5187     // is 1, and the rest is an encoding of "elemTyp".
5188     static CORINFO_CLASS_HANDLE EncodeElemType(var_types elemTyp, CORINFO_CLASS_HANDLE elemStructType)
5189     {
5190         if (elemStructType != nullptr)
5191         {
5192             assert(varTypeIsStruct(elemTyp) || elemTyp == TYP_REF || elemTyp == TYP_BYREF ||
5193                    varTypeIsIntegral(elemTyp));
5194             assert((size_t(elemStructType) & 0x1) == 0x0); // Make sure the encoding below is valid.
5195             return elemStructType;
5196         }
5197         else
5198         {
5199             assert(elemTyp != TYP_STRUCT);
5200             elemTyp = varTypeToSigned(elemTyp);
5201             return CORINFO_CLASS_HANDLE(size_t(elemTyp) << 1 | 0x1);
5202         }
5203     }
5204     // If "clsHnd" is the result of an "EncodePrim" call, returns true and sets "*pPrimType" to the
5205     // var_types it represents.  Otherwise, returns TYP_STRUCT (on the assumption that "clsHnd" is
5206     // the struct type of the element).
5207     static var_types DecodeElemType(CORINFO_CLASS_HANDLE clsHnd)
5208     {
5209         size_t clsHndVal = size_t(clsHnd);
5210         if (clsHndVal & 0x1)
5211         {
5212             return var_types(clsHndVal >> 1);
5213         }
5214         else
5215         {
5216             return TYP_STRUCT;
5217         }
5218     }
5219
5220     bool GetObjectHandleAndOffset(GenTree* tree, ssize_t* byteOffset, CORINFO_OBJECT_HANDLE* pObj);
5221
5222     // Convert a BYTE which represents the VM's CorInfoGCtype to the JIT's var_types
5223     var_types getJitGCType(BYTE gcType);
5224
5225     // Returns true if the provided type should be treated as a primitive type
5226     // for the unmanaged calling conventions.
5227     bool isNativePrimitiveStructType(CORINFO_CLASS_HANDLE clsHnd);
5228
5229     enum structPassingKind
5230     {
5231         SPK_Unknown,       // Invalid value, never returned
5232         SPK_PrimitiveType, // The struct is passed/returned using a primitive type.
5233         SPK_EnclosingType, // Like SPK_Primitive type, but used for return types that
5234                            //  require a primitive type temp that is larger than the struct size.
5235                            //  Currently used for structs of size 3, 5, 6, or 7 bytes.
5236         SPK_ByValue,       // The struct is passed/returned by value (using the ABI rules)
5237                            //  for ARM64 and UNIX_X64 in multiple registers. (when all of the
5238                            //   parameters registers are used, then the stack will be used)
5239                            //  for X86 passed on the stack, for ARM32 passed in registers
5240                            //   or the stack or split between registers and the stack.
5241         SPK_ByValueAsHfa,  // The struct is passed/returned as an HFA in multiple registers.
5242         SPK_ByReference
5243     }; // The struct is passed/returned by reference to a copy/buffer.
5244
5245     // Get the "primitive" type that is used when we are given a struct of size 'structSize'.
5246     // For pointer sized structs the 'clsHnd' is used to determine if the struct contains GC ref.
5247     // A "primitive" type is one of the scalar types: byte, short, int, long, ref, float, double
5248     // If we can't or shouldn't use a "primitive" type then TYP_UNKNOWN is returned.
5249     //
5250     // isVarArg is passed for use on Windows Arm64 to change the decision returned regarding
5251     // hfa types.
5252     //
5253     var_types getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS_HANDLE clsHnd, bool isVarArg);
5254
5255     // Get the type that is used to pass values of the given struct type.
5256     // isVarArg is passed for use on Windows Arm64 to change the decision returned regarding
5257     // hfa types.
5258     //
5259     var_types getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
5260                                   structPassingKind*   wbPassStruct,
5261                                   bool                 isVarArg,
5262                                   unsigned             structSize);
5263
5264     // Get the type that is used to return values of the given struct type.
5265     // If the size is unknown, pass 0 and it will be determined from 'clsHnd'.
5266     var_types getReturnTypeForStruct(CORINFO_CLASS_HANDLE     clsHnd,
5267                                      CorInfoCallConvExtension callConv,
5268                                      structPassingKind*       wbPassStruct = nullptr,
5269                                      unsigned                 structSize   = 0);
5270
5271 #ifdef DEBUG
5272     // Print a representation of "vnp" or "vn" on standard output.
5273     // If "level" is non-zero, we also print out a partial expansion of the value.
5274     void vnpPrint(ValueNumPair vnp, unsigned level);
5275     void vnPrint(ValueNum vn, unsigned level);
5276 #endif
5277
5278     bool fgDominate(const BasicBlock* b1, const BasicBlock* b2); // Return true if b1 dominates b2
5279
5280     // Dominator computation member functions
5281     // Not exposed outside Compiler
5282 protected:
5283     bool fgReachable(BasicBlock* b1, BasicBlock* b2); // Returns true if block b1 can reach block b2
5284
5285     // Compute immediate dominators, the dominator tree and and its pre/post-order travsersal numbers.
5286     void fgComputeDoms();
5287
5288     void fgCompDominatedByExceptionalEntryBlocks();
5289
5290     BlockSet_ValRet_T fgGetDominatorSet(BasicBlock* block); // Returns a set of blocks that dominate the given block.
5291     // Note: this is relatively slow compared to calling fgDominate(),
5292     // especially if dealing with a single block versus block check.
5293
5294     void fgComputeReachabilitySets(); // Compute bbReach sets. (Also sets BBF_GC_SAFE_POINT flag on blocks.)
5295
5296     void fgComputeReturnBlocks(); // Initialize fgReturnBlocks to a list of BBJ_RETURN blocks.
5297
5298     void fgComputeEnterBlocksSet(); // Compute the set of entry blocks, 'fgEnterBlks'.
5299
5300     // Remove blocks determined to be unreachable by the 'canRemoveBlock'.
5301     template <typename CanRemoveBlockBody>
5302     bool fgRemoveUnreachableBlocks(CanRemoveBlockBody canRemoveBlock);
5303
5304     PhaseStatus fgComputeReachability(); // Perform flow graph node reachability analysis.
5305
5306     bool fgRemoveDeadBlocks(); // Identify and remove dead blocks.
5307
5308     BasicBlock* fgIntersectDom(BasicBlock* a, BasicBlock* b); // Intersect two immediate dominator sets.
5309
5310     void fgDfsReversePostorder();
5311     void fgDfsReversePostorderHelper(BasicBlock* block,
5312                                      BlockSet&   visited,
5313                                      unsigned&   preorderIndex,
5314                                      unsigned&   reversePostorderIndex);
5315
5316     BlockSet_ValRet_T fgDomFindStartNodes(); // Computes which basic blocks don't have incoming edges in the flow graph.
5317                                              // Returns this as a set.
5318
5319     INDEBUG(void fgDispDomTree(DomTreeNode* domTree);) // Helper that prints out the Dominator Tree in debug builds.
5320
5321     DomTreeNode* fgBuildDomTree(); // Once we compute all the immediate dominator sets for each node in the flow graph
5322                                    // (performed by fgComputeDoms), this procedure builds the dominance tree represented
5323                                    // adjacency lists.
5324
5325     // In order to speed up the queries of the form 'Does A dominates B', we can perform a DFS preorder and postorder
5326     // traversal of the dominance tree and the dominance query will become A dominates B iif preOrder(A) <= preOrder(B)
5327     // && postOrder(A) >= postOrder(B) making the computation O(1).
5328     void fgNumberDomTree(DomTreeNode* domTree);
5329
5330     // When the flow graph changes, we need to update the block numbers, reachability sets,
5331     // dominators, and possibly loops.
5332     //
5333     void fgUpdateChangedFlowGraph(FlowGraphUpdates updates);
5334
5335 public:
5336     enum GCPollType
5337     {
5338         GCPOLL_NONE,
5339         GCPOLL_CALL,
5340         GCPOLL_INLINE
5341     };
5342
5343     // Initialize the per-block variable sets (used for liveness analysis).
5344     void fgInitBlockVarSets();
5345
5346     PhaseStatus StressSplitTree();
5347     void SplitTreesRandomly();
5348     void SplitTreesRemoveCommas();
5349
5350     template <bool (Compiler::*ExpansionFunction)(BasicBlock**, Statement*, GenTreeCall*)>
5351     PhaseStatus fgExpandHelper(bool skipRarelyRunBlocks);
5352
5353     template <bool (Compiler::*ExpansionFunction)(BasicBlock**, Statement*, GenTreeCall*)>
5354     bool fgExpandHelperForBlock(BasicBlock** pBlock);
5355
5356     PhaseStatus fgExpandRuntimeLookups();
5357     bool fgExpandRuntimeLookupsForCall(BasicBlock** pBlock, Statement* stmt, GenTreeCall* call);
5358
5359     PhaseStatus fgExpandThreadLocalAccess();
5360     bool fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* stmt, GenTreeCall* call);
5361
5362     PhaseStatus fgExpandStaticInit();
5363     bool fgExpandStaticInitForCall(BasicBlock** pBlock, Statement* stmt, GenTreeCall* call);
5364
5365     PhaseStatus fgVNBasedIntrinsicExpansion();
5366     bool fgVNBasedIntrinsicExpansionForCall(BasicBlock** pBlock, Statement* stmt, GenTreeCall* call);
5367     bool fgVNBasedIntrinsicExpansionForCall_ReadUtf8(BasicBlock** pBlock, Statement* stmt, GenTreeCall* call);
5368
5369     PhaseStatus fgInsertGCPolls();
5370     BasicBlock* fgCreateGCPoll(GCPollType pollType, BasicBlock* block);
5371
5372     // Requires that "block" is a block that returns from
5373     // a finally.  Returns the number of successors (jump targets of
5374     // of blocks in the covered "try" that did a "LEAVE".)
5375     unsigned fgNSuccsOfFinallyRet(BasicBlock* block);
5376
5377     // Requires that "block" is a block that returns (in the sense of BBJ_EHFINALLYRET) from
5378     // a finally.  Returns its "i"th successor (jump targets of
5379     // of blocks in the covered "try" that did a "LEAVE".)
5380     // Requires that "i" < fgNSuccsOfFinallyRet(block).
5381     BasicBlock* fgSuccOfFinallyRet(BasicBlock* block, unsigned i);
5382
5383 private:
5384     // Factor out common portions of the impls of the methods above.
5385     void fgSuccOfFinallyRetWork(BasicBlock* block, unsigned i, BasicBlock** bres, unsigned* nres);
5386
5387 public:
5388     // For many purposes, it is desirable to be able to enumerate the *distinct* targets of a switch statement,
5389     // skipping duplicate targets.  (E.g., in flow analyses that are only interested in the set of possible targets.)
5390     // SwitchUniqueSuccSet contains the non-duplicated switch targets.
5391     // (Code that modifies the jump table of a switch has an obligation to call Compiler::UpdateSwitchTableTarget,
5392     // which in turn will call the "UpdateTarget" method of this type if a SwitchUniqueSuccSet has already
5393     // been computed for the switch block.  If a switch block is deleted or is transformed into a non-switch,
5394     // we leave the entry associated with the block, but it will no longer be accessed.)
5395     struct SwitchUniqueSuccSet
5396     {
5397         unsigned     numDistinctSuccs; // Number of distinct targets of the switch.
5398         BasicBlock** nonDuplicates;    // Array of "numDistinctSuccs", containing all the distinct switch target
5399                                        // successors.
5400
5401         // The switch block "switchBlk" just had an entry with value "from" modified to the value "to".
5402         // Update "this" as necessary: if "from" is no longer an element of the jump table of "switchBlk",
5403         // remove it from "this", and ensure that "to" is a member.  Use "alloc" to do any required allocation.
5404         void UpdateTarget(CompAllocator alloc, BasicBlock* switchBlk, BasicBlock* from, BasicBlock* to);
5405     };
5406
5407     typedef JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, SwitchUniqueSuccSet> BlockToSwitchDescMap;
5408
5409 private:
5410     // Maps BasicBlock*'s that end in switch statements to SwitchUniqueSuccSets that allow
5411     // iteration over only the distinct successors.
5412     BlockToSwitchDescMap* m_switchDescMap;
5413
5414 public:
5415     BlockToSwitchDescMap* GetSwitchDescMap(bool createIfNull = true)
5416     {
5417         if ((m_switchDescMap == nullptr) && createIfNull)
5418         {
5419             m_switchDescMap = new (getAllocator()) BlockToSwitchDescMap(getAllocator());
5420         }
5421         return m_switchDescMap;
5422     }
5423
5424     // Invalidate the map of unique switch block successors. For example, since the hash key of the map
5425     // depends on block numbers, we must invalidate the map when the blocks are renumbered, to ensure that
5426     // we don't accidentally look up and return the wrong switch data.
5427     void InvalidateUniqueSwitchSuccMap()
5428     {
5429         m_switchDescMap = nullptr;
5430     }
5431
5432     // Requires "switchBlock" to be a block that ends in a switch.  Returns
5433     // the corresponding SwitchUniqueSuccSet.
5434     SwitchUniqueSuccSet GetDescriptorForSwitch(BasicBlock* switchBlk);
5435
5436     // The switch block "switchBlk" just had an entry with value "from" modified to the value "to".
5437     // Update "this" as necessary: if "from" is no longer an element of the jump table of "switchBlk",
5438     // remove it from "this", and ensure that "to" is a member.
5439     void UpdateSwitchTableTarget(BasicBlock* switchBlk, BasicBlock* from, BasicBlock* to);
5440
5441     // Remove the "SwitchUniqueSuccSet" of "switchBlk" in the BlockToSwitchDescMap.
5442     void fgInvalidateSwitchDescMapEntry(BasicBlock* switchBlk);
5443
5444     BasicBlock* fgFirstBlockOfHandler(BasicBlock* block);
5445
5446     bool fgIsFirstBlockOfFilterOrHandler(BasicBlock* block);
5447
5448     FlowEdge* fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred);
5449
5450     FlowEdge* fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, FlowEdge*** ptrToPred);
5451
5452     FlowEdge* fgRemoveRefPred(BasicBlock* block, BasicBlock* blockPred);
5453
5454     FlowEdge* fgRemoveAllRefPreds(BasicBlock* block, BasicBlock* blockPred);
5455
5456     void fgRemoveBlockAsPred(BasicBlock* block);
5457
5458     void fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSwitchBlock);
5459
5460     void fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* newTarget, BasicBlock* oldTarget);
5461
5462     void fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget);
5463
5464     void fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* newPred);
5465
5466     // initializingPreds is only 'true' when we are computing preds in fgLinkBasicBlocks()
5467     template <bool initializingPreds = false>
5468     FlowEdge* fgAddRefPred(BasicBlock* block, BasicBlock* blockPred, FlowEdge* oldEdge = nullptr);
5469
5470     void fgFindBasicBlocks();
5471
5472     bool fgIsBetterFallThrough(BasicBlock* bCur, BasicBlock* bAlt);
5473
5474     bool fgCheckEHCanInsertAfterBlock(BasicBlock* blk, unsigned regionIndex, bool putInTryRegion);
5475
5476     BasicBlock* fgFindInsertPoint(unsigned    regionIndex,
5477                                   bool        putInTryRegion,
5478                                   BasicBlock* startBlk,
5479                                   BasicBlock* endBlk,
5480                                   BasicBlock* nearBlk,
5481                                   BasicBlock* jumpBlk,
5482                                   bool        runRarely);
5483
5484     unsigned fgGetNestingLevel(BasicBlock* block, unsigned* pFinallyNesting = nullptr);
5485
5486     PhaseStatus fgPostImportationCleanup();
5487
5488     void fgRemoveStmt(BasicBlock* block, Statement* stmt DEBUGARG(bool isUnlink = false));
5489     void fgUnlinkStmt(BasicBlock* block, Statement* stmt);
5490
5491     bool fgCheckRemoveStmt(BasicBlock* block, Statement* stmt);
5492
5493     bool fgCreateLoopPreHeader(unsigned lnum);
5494
5495     void fgUnreachableBlock(BasicBlock* block);
5496
5497     void fgRemoveConditionalJump(BasicBlock* block);
5498
5499     BasicBlock* fgLastBBInMainFunction();
5500
5501     BasicBlock* fgEndBBAfterMainFunction();
5502
5503     BasicBlock* fgGetDomSpeculatively(const BasicBlock* block);
5504
5505     void fgUnlinkRange(BasicBlock* bBeg, BasicBlock* bEnd);
5506
5507     void fgRemoveBlock(BasicBlock* block, bool unreachable);
5508
5509     bool fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext);
5510
5511     void fgCompactBlocks(BasicBlock* block, BasicBlock* bNext);
5512
5513     void fgUpdateLoopsAfterCompacting(BasicBlock* block, BasicBlock* bNext);
5514
5515     BasicBlock* fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst);
5516
5517     bool fgRenumberBlocks();
5518
5519     bool fgExpandRarelyRunBlocks();
5520
5521     bool fgEhAllowsMoveBlock(BasicBlock* bBefore, BasicBlock* bAfter);
5522
5523     void fgMoveBlocksAfter(BasicBlock* bStart, BasicBlock* bEnd, BasicBlock* insertAfterBlk);
5524
5525     PhaseStatus fgTailMerge();
5526
5527     enum FG_RELOCATE_TYPE
5528     {
5529         FG_RELOCATE_TRY,    // relocate the 'try' region
5530         FG_RELOCATE_HANDLER // relocate the handler region (including the filter if necessary)
5531     };
5532     BasicBlock* fgRelocateEHRange(unsigned regionIndex, FG_RELOCATE_TYPE relocateType);
5533
5534 #if defined(FEATURE_EH_FUNCLETS)
5535 #if defined(TARGET_ARM)
5536     void fgClearFinallyTargetBit(BasicBlock* block);
5537 #endif // defined(TARGET_ARM)
5538     bool fgIsIntraHandlerPred(BasicBlock* predBlock, BasicBlock* block);
5539     bool fgAnyIntraHandlerPreds(BasicBlock* block);
5540     void fgInsertFuncletPrologBlock(BasicBlock* block);
5541     void        fgCreateFuncletPrologBlocks();
5542     PhaseStatus fgCreateFunclets();
5543 #else  // !FEATURE_EH_FUNCLETS
5544     bool fgRelocateEHRegions();
5545 #endif // !FEATURE_EH_FUNCLETS
5546
5547     bool fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* target);
5548
5549     bool fgBlockEndFavorsTailDuplication(BasicBlock* block, unsigned lclNum);
5550
5551     bool fgBlockIsGoodTailDuplicationCandidate(BasicBlock* block, unsigned* lclNum);
5552
5553     bool fgOptimizeEmptyBlock(BasicBlock* block);
5554
5555     bool fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBlock* bDest);
5556
5557     bool fgOptimizeBranch(BasicBlock* bJump);
5558
5559     bool fgOptimizeSwitchBranches(BasicBlock* block);
5560
5561     bool fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev);
5562
5563     bool fgOptimizeSwitchJumps();
5564 #ifdef DEBUG
5565     void fgPrintEdgeWeights();
5566 #endif
5567     PhaseStatus fgComputeBlockAndEdgeWeights();
5568     bool fgComputeMissingBlockWeights(weight_t* returnWeight);
5569     bool fgComputeCalledCount(weight_t returnWeight);
5570     PhaseStatus fgComputeEdgeWeights();
5571
5572     bool fgReorderBlocks(bool useProfile);
5573
5574 #ifdef FEATURE_EH_FUNCLETS
5575     bool fgFuncletsAreCold();
5576 #endif // FEATURE_EH_FUNCLETS
5577
5578     PhaseStatus fgDetermineFirstColdBlock();
5579
5580     bool fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc = nullptr);
5581
5582     bool fgUpdateFlowGraph(bool doTailDup = false, bool isPhase = false);
5583     PhaseStatus fgUpdateFlowGraphPhase();
5584
5585     PhaseStatus fgFindOperOrder();
5586
5587     // method that returns if you should split here
5588     typedef bool(fgSplitPredicate)(GenTree* tree, GenTree* parent, fgWalkData* data);
5589
5590     PhaseStatus fgSetBlockOrder();
5591
5592     void fgRemoveReturnBlock(BasicBlock* block);
5593
5594     /* Helper code that has been factored out */
5595     inline void fgConvertBBToThrowBB(BasicBlock* block);
5596
5597     bool fgCastNeeded(GenTree* tree, var_types toType);
5598
5599     // The following check for loops that don't execute calls
5600     bool fgLoopCallMarked;
5601
5602     void fgLoopCallTest(BasicBlock* srcBB, BasicBlock* dstBB);
5603     void fgLoopCallMark();
5604
5605     void fgMarkLoopHead(BasicBlock* block);
5606
5607     unsigned fgGetCodeEstimate(BasicBlock* block);
5608
5609 #if DUMP_FLOWGRAPHS
5610     enum class PhasePosition
5611     {
5612         PrePhase,
5613         PostPhase
5614     };
5615     const char* fgProcessEscapes(const char* nameIn, escapeMapping_t* map);
5616     static void fgDumpTree(FILE* fgxFile, GenTree* const tree);
5617     FILE* fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, PhasePosition pos, const char* type);
5618     bool fgDumpFlowGraph(Phases phase, PhasePosition pos);
5619 #endif // DUMP_FLOWGRAPHS
5620
5621 #ifdef DEBUG
5622
5623     void fgDispDoms();
5624     void fgDispReach();
5625     void fgDispBBLiveness(BasicBlock* block);
5626     void fgDispBBLiveness();
5627     void fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth = 0);
5628     void fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, bool dumpTrees);
5629     void fgDispBasicBlocks(bool dumpTrees = false);
5630     void fgDumpStmtTree(Statement* stmt, unsigned bbNum);
5631     void fgDumpBlock(BasicBlock* block);
5632     void fgDumpTrees(BasicBlock* firstBlock, BasicBlock* lastBlock);
5633
5634     static fgWalkPreFn fgStress64RsltMulCB;
5635     void               fgStress64RsltMul();
5636     void               fgDebugCheckUpdate();
5637
5638     void fgDebugCheckBBNumIncreasing();
5639     void fgDebugCheckBBlist(bool checkBBNum = false, bool checkBBRefs = true);
5640     void fgDebugCheckBlockLinks();
5641     void fgDebugCheckLinks(bool morphTrees = false);
5642     void fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees);
5643     void fgDebugCheckNodeLinks(BasicBlock* block, Statement* stmt);
5644     void fgDebugCheckLinkedLocals();
5645     void fgDebugCheckNodesUniqueness();
5646     void fgDebugCheckLoopTable();
5647     void fgDebugCheckSsa();
5648
5649     void fgDebugCheckFlags(GenTree* tree);
5650     void fgDebugCheckDispFlags(GenTree* tree, GenTreeFlags dispFlags, GenTreeDebugFlags debugFlags);
5651     void fgDebugCheckFlagsHelper(GenTree* tree, GenTreeFlags actualFlags, GenTreeFlags expectedFlags);
5652     void fgDebugCheckTryFinallyExits();
5653     void fgDebugCheckProfileWeights();
5654     void fgDebugCheckProfileWeights(ProfileChecks checks);
5655     bool fgDebugCheckIncomingProfileData(BasicBlock* block, ProfileChecks checks);
5656     bool fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks checks);
5657
5658 #endif // DEBUG
5659
5660     static bool fgProfileWeightsEqual(weight_t weight1, weight_t weight2, weight_t epsilon = 0.01);
5661     static bool fgProfileWeightsConsistent(weight_t weight1, weight_t weight2);
5662
5663     static GenTree* fgGetFirstNode(GenTree* tree);
5664
5665     //--------------------- Walking the trees in the IR -----------------------
5666
5667     struct fgWalkData
5668     {
5669         Compiler*     compiler;
5670         fgWalkPreFn*  wtprVisitorFn;
5671         fgWalkPostFn* wtpoVisitorFn;
5672         void*         pCallbackData; // user-provided data
5673         GenTree*      parent;        // parent of current node, provided to callback
5674         bool          wtprLclsOnly;  // whether to only visit lclvar nodes
5675 #ifdef DEBUG
5676         bool printModified; // callback can use this
5677 #endif
5678     };
5679
5680     fgWalkResult fgWalkTreePre(GenTree**    pTree,
5681                                fgWalkPreFn* visitor,
5682                                void*        pCallBackData = nullptr,
5683                                bool         lclVarsOnly   = false,
5684                                bool         computeStack  = false);
5685
5686     fgWalkResult fgWalkTree(GenTree**     pTree,
5687                             fgWalkPreFn*  preVisitor,
5688                             fgWalkPostFn* postVisitor,
5689                             void*         pCallBackData = nullptr);
5690
5691     void fgWalkAllTreesPre(fgWalkPreFn* visitor, void* pCallBackData);
5692
5693     //----- Postorder
5694
5695     fgWalkResult fgWalkTreePost(GenTree**     pTree,
5696                                 fgWalkPostFn* visitor,
5697                                 void*         pCallBackData = nullptr,
5698                                 bool          computeStack  = false);
5699
5700     /**************************************************************************
5701      *                          PROTECTED
5702      *************************************************************************/
5703
5704 protected:
5705     friend class SsaBuilder;
5706     friend struct ValueNumberState;
5707
5708     //--------------------- Detect the basic blocks ---------------------------
5709
5710     BasicBlock** fgBBs; // Table of pointers to the BBs
5711
5712     void        fgInitBBLookup();
5713     BasicBlock* fgLookupBB(unsigned addr);
5714
5715     bool fgCanSwitchToOptimized();
5716     void fgSwitchToOptimized(const char* reason);
5717
5718     bool fgMayExplicitTailCall();
5719
5720     void fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget);
5721
5722     void fgMarkBackwardJump(BasicBlock* startBlock, BasicBlock* endBlock);
5723
5724     void fgLinkBasicBlocks();
5725
5726     unsigned fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget);
5727
5728     void fgCheckBasicBlockControlFlow();
5729
5730     void fgControlFlowPermitted(BasicBlock* blkSrc,
5731                                 BasicBlock* blkDest,
5732                                 bool        IsLeave = false /* is the src a leave block */);
5733
5734     bool fgFlowToFirstBlockOfInnerTry(BasicBlock* blkSrc, BasicBlock* blkDest, bool sibling);
5735
5736     void fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, bool isInlining);
5737
5738     void fgAdjustForAddressExposedOrWrittenThis();
5739
5740     unsigned fgStressBBProf()
5741     {
5742 #ifdef DEBUG
5743         unsigned result = JitConfig.JitStressBBProf();
5744         if (result == 0)
5745         {
5746             if (compStressCompile(STRESS_BB_PROFILE, 15))
5747             {
5748                 result = 1;
5749             }
5750         }
5751         return result;
5752 #else
5753         return 0;
5754 #endif
5755     }
5756
5757     bool fgHaveProfileData();
5758     bool fgHaveProfileWeights();
5759     bool fgGetProfileWeightForBasicBlock(IL_OFFSET offset, weight_t* weight);
5760
5761     Instrumentor* fgCountInstrumentor;
5762     Instrumentor* fgHistogramInstrumentor;
5763
5764     PhaseStatus fgPrepareToInstrumentMethod();
5765     PhaseStatus fgInstrumentMethod();
5766     PhaseStatus fgIncorporateProfileData();
5767     bool        fgIncorporateBlockCounts();
5768     bool        fgIncorporateEdgeCounts();
5769
5770 public:
5771     const char*                            fgPgoFailReason;
5772     bool                                   fgPgoDisabled;
5773     ICorJitInfo::PgoSource                 fgPgoSource;
5774     ICorJitInfo::PgoInstrumentationSchema* fgPgoSchema;
5775     BYTE*                                  fgPgoData;
5776     UINT32                                 fgPgoSchemaCount;
5777     HRESULT                                fgPgoQueryResult;
5778     UINT32                                 fgNumProfileRuns;
5779     UINT32                                 fgPgoBlockCounts;
5780     UINT32                                 fgPgoEdgeCounts;
5781     UINT32                                 fgPgoClassProfiles;
5782     UINT32                                 fgPgoMethodProfiles;
5783     unsigned                               fgPgoInlineePgo;
5784     unsigned                               fgPgoInlineeNoPgo;
5785     unsigned                               fgPgoInlineeNoPgoSingleBlock;
5786     bool                                   fgPgoHaveWeights;
5787
5788     void WalkSpanningTree(SpanningTreeVisitor* visitor);
5789     void fgSetProfileWeight(BasicBlock* block, weight_t weight);
5790     void fgApplyProfileScale();
5791     bool fgHaveSufficientProfileWeights();
5792     bool fgHaveTrustedProfileWeights();
5793
5794     // fgIsUsingProfileWeights - returns true if we have real profile data for this method
5795     //                           or if we have some fake profile data for the stress mode
5796     bool fgIsUsingProfileWeights()
5797     {
5798         return (fgHaveProfileWeights() || fgStressBBProf());
5799     }
5800
5801     // fgProfileRunsCount - returns total number of scenario runs for the profile data
5802     //                      or BB_UNITY_WEIGHT_UNSIGNED when we aren't using profile data.
5803     unsigned fgProfileRunsCount()
5804     {
5805         return fgIsUsingProfileWeights() ? fgNumProfileRuns : BB_UNITY_WEIGHT_UNSIGNED;
5806     }
5807
5808 //-------- Insert a statement at the start or end of a basic block --------
5809
5810 #ifdef DEBUG
5811 public:
5812     static bool fgBlockContainsStatementBounded(BasicBlock* block, Statement* stmt, bool answerOnBoundExceeded = true);
5813 #endif
5814
5815 public:
5816     Statement* fgNewStmtAtBeg(BasicBlock* block, GenTree* tree, const DebugInfo& di = DebugInfo());
5817     void fgInsertStmtAtEnd(BasicBlock* block, Statement* stmt);
5818     Statement* fgNewStmtAtEnd(BasicBlock* block, GenTree* tree, const DebugInfo& di = DebugInfo());
5819     Statement* fgNewStmtNearEnd(BasicBlock* block, GenTree* tree, const DebugInfo& di = DebugInfo());
5820
5821 private:
5822     void fgInsertStmtNearEnd(BasicBlock* block, Statement* stmt);
5823     void fgInsertStmtAtBeg(BasicBlock* block, Statement* stmt);
5824
5825 public:
5826     void fgInsertStmtAfter(BasicBlock* block, Statement* insertionPoint, Statement* stmt);
5827     void fgInsertStmtBefore(BasicBlock* block, Statement* insertionPoint, Statement* stmt);
5828
5829 private:
5830     Statement* fgInsertStmtListAfter(BasicBlock* block, Statement* stmtAfter, Statement* stmtList);
5831
5832     //                  Create a new temporary variable to hold the result of *ppTree,
5833     //                  and transform the graph accordingly.
5834     GenTree* fgInsertCommaFormTemp(GenTree** ppTree);
5835     TempInfo fgMakeTemp(GenTree* rhs);
5836     GenTree* fgMakeMultiUse(GenTree** ppTree);
5837
5838     //                  Recognize a bitwise rotation pattern and convert into a GT_ROL or a GT_ROR node.
5839     GenTree* fgRecognizeAndMorphBitwiseRotation(GenTree* tree);
5840     bool fgOperIsBitwiseRotationRoot(genTreeOps oper);
5841
5842 #if !defined(TARGET_64BIT)
5843     //                  Recognize and morph a long multiplication with 32 bit operands.
5844     GenTreeOp* fgRecognizeAndMorphLongMul(GenTreeOp* mul);
5845     GenTreeOp* fgMorphLongMul(GenTreeOp* mul);
5846 #endif
5847
5848     //-------- Determine the order in which the trees will be evaluated -------
5849 public:
5850     void fgSetStmtSeq(Statement* stmt);
5851
5852 private:
5853     GenTree* fgSetTreeSeq(GenTree* tree, bool isLIR = false);
5854     void fgSetBlockOrder(BasicBlock* block);
5855
5856     //------------------------- Morphing --------------------------------------
5857
5858     unsigned fgPtrArgCntMax;
5859
5860 public:
5861     //------------------------------------------------------------------------
5862     // fgGetPtrArgCntMax: Return the maximum number of pointer-sized stack arguments that calls inside this method
5863     // can push on the stack. This value is calculated during morph.
5864     //
5865     // Return Value:
5866     //    Returns fgPtrArgCntMax, that is a private field.
5867     //
5868     unsigned fgGetPtrArgCntMax() const
5869     {
5870         return fgPtrArgCntMax;
5871     }
5872
5873     //------------------------------------------------------------------------
5874     // fgSetPtrArgCntMax: Set the maximum number of pointer-sized stack arguments that calls inside this method
5875     // can push on the stack. This function is used during StackLevelSetter to fix incorrect morph calculations.
5876     //
5877     void fgSetPtrArgCntMax(unsigned argCntMax)
5878     {
5879         fgPtrArgCntMax = argCntMax;
5880     }
5881
5882     bool compCanEncodePtrArgCntMax();
5883
5884 private:
5885     hashBv*               fgAvailableOutgoingArgTemps;
5886     ArrayStack<unsigned>* fgUsedSharedTemps;
5887
5888     void fgSetRngChkTarget(GenTree* tree, bool delay = true);
5889
5890     BasicBlock* fgSetRngChkTargetInner(SpecialCodeKind kind, bool delay);
5891
5892 #if REARRANGE_ADDS
5893     void fgMoveOpsLeft(GenTree* tree);
5894 #endif
5895
5896     bool fgIsCommaThrow(GenTree* tree, bool forFolding = false);
5897
5898     bool fgIsThrow(GenTree* tree);
5899
5900     bool fgInDifferentRegions(BasicBlock* blk1, BasicBlock* blk2);
5901     bool fgIsBlockCold(BasicBlock* block);
5902
5903     GenTree* fgMorphCastIntoHelper(GenTree* tree, int helper, GenTree* oper);
5904
5905     GenTree* fgMorphIntoHelperCall(
5906         GenTree* tree, int helper, bool morphArgs, GenTree* arg1 = nullptr, GenTree* arg2 = nullptr);
5907
5908     // A "MorphAddrContext" carries information from the surrounding context.  If we are evaluating a byref address,
5909     // it is useful to know whether the address will be immediately dereferenced, or whether the address value will
5910     // be used, perhaps by passing it as an argument to a called method.  This affects how null checking is done:
5911     // for sufficiently small offsets, we can rely on OS page protection to implicitly null-check addresses that we
5912     // know will be dereferenced.  To know that reliance on implicit null checking is sound, we must further know that
5913     // all offsets between the top-level indirection and the bottom are constant, and that their sum is sufficiently
5914     // small; hence the other fields of MorphAddrContext.
5915     struct MorphAddrContext
5916     {
5917         size_t m_totalOffset = 0;     // Sum of offsets between the top-level indirection and here (current context).
5918         bool   m_used        = false; // Whether this context was used to elide a null check.
5919     };
5920
5921 #ifdef FEATURE_SIMD
5922     GenTree* getSIMDStructFromField(GenTree*  tree,
5923                                     unsigned* indexOut,
5924                                     unsigned* simdSizeOut,
5925                                     bool      ignoreUsedInSIMDIntrinsic = false);
5926     bool fgMorphCombineSIMDFieldStores(BasicBlock* block, Statement* stmt);
5927     void impMarkContiguousSIMDFieldStores(Statement* stmt);
5928
5929     // fgPreviousCandidateSIMDFieldStoreStmt is only used for tracking previous simd field assignment
5930     // in function: Compiler::impMarkContiguousSIMDFieldStores.
5931     Statement* fgPreviousCandidateSIMDFieldStoreStmt;
5932
5933 #endif // FEATURE_SIMD
5934     GenTree* fgMorphIndexAddr(GenTreeIndexAddr* tree);
5935     GenTree* fgMorphExpandCast(GenTreeCast* tree);
5936     GenTreeFieldList* fgMorphLclArgToFieldlist(GenTreeLclVarCommon* lcl);
5937     GenTreeCall* fgMorphArgs(GenTreeCall* call);
5938
5939     void fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg);
5940
5941     GenTree* fgMorphLeafLocal(GenTreeLclVarCommon* lclNode);
5942 #ifdef TARGET_X86
5943     GenTree* fgMorphExpandStackArgForVarArgs(GenTreeLclVarCommon* lclNode);
5944 #endif // TARGET_X86
5945     GenTree* fgMorphExpandImplicitByRefArg(GenTreeLclVarCommon* lclNode);
5946     GenTree* fgMorphExpandLocal(GenTreeLclVarCommon* lclNode);
5947
5948 public:
5949     bool fgAddrCouldBeNull(GenTree* addr);
5950     void fgAssignSetVarDef(GenTree* tree);
5951
5952 private:
5953     GenTree* fgMorphFieldAddr(GenTree* tree, MorphAddrContext* mac);
5954     GenTree* fgMorphExpandInstanceField(GenTree* tree, MorphAddrContext* mac);
5955     GenTree* fgMorphExpandTlsFieldAddr(GenTree* tree);
5956     bool fgCanFastTailCall(GenTreeCall* call, const char** failReason);
5957 #if FEATURE_FASTTAILCALL
5958     bool fgCallHasMustCopyByrefParameter(GenTreeCall* call);
5959     bool fgCallArgWillPointIntoLocalFrame(GenTreeCall* call, CallArg& arg);
5960
5961 #endif
5962     bool     fgCheckStmtAfterTailCall();
5963     GenTree* fgMorphTailCallViaHelpers(GenTreeCall* call, CORINFO_TAILCALL_HELPERS& help);
5964     bool fgCanTailCallViaJitHelper(GenTreeCall* call);
5965     void fgMorphTailCallViaJitHelper(GenTreeCall* call);
5966     GenTree* fgCreateCallDispatcherAndGetResult(GenTreeCall*          origCall,
5967                                                 CORINFO_METHOD_HANDLE callTargetStubHnd,
5968                                                 CORINFO_METHOD_HANDLE dispatcherHnd);
5969     GenTree* getLookupTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
5970                            CORINFO_LOOKUP*         pLookup,
5971                            GenTreeFlags            handleFlags,
5972                            void*                   compileTimeHandle);
5973     GenTree* getRuntimeLookupTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
5974                                   CORINFO_LOOKUP*         pLookup,
5975                                   void*                   compileTimeHandle);
5976     GenTree* getVirtMethodPointerTree(GenTree*                thisPtr,
5977                                       CORINFO_RESOLVED_TOKEN* pResolvedToken,
5978                                       CORINFO_CALL_INFO*      pCallInfo);
5979     GenTree* getTokenHandleTree(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool parent);
5980
5981     GenTree* fgMorphPotentialTailCall(GenTreeCall* call);
5982     void fgValidateIRForTailCall(GenTreeCall* call);
5983     GenTree* fgGetStubAddrArg(GenTreeCall* call);
5984     unsigned fgGetArgParameterLclNum(GenTreeCall* call, CallArg* arg);
5985     void fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCall* recursiveTailCall);
5986     Statement* fgAssignRecursiveCallArgToCallerParam(GenTree*         arg,
5987                                                      CallArg*         callArg,
5988                                                      unsigned         lclParamNum,
5989                                                      BasicBlock*      block,
5990                                                      const DebugInfo& callDI,
5991                                                      Statement*       tmpAssignmentInsertionPoint,
5992                                                      Statement*       paramAssignmentInsertionPoint);
5993     GenTree* fgMorphCall(GenTreeCall* call);
5994     GenTree* fgExpandVirtualVtableCallTarget(GenTreeCall* call);
5995
5996     void fgMorphCallInline(GenTreeCall* call, InlineResult* result);
5997     void fgMorphCallInlineHelper(GenTreeCall* call, InlineResult* result, InlineContext** createdContext);
5998 #if DEBUG
5999     void fgNoteNonInlineCandidate(Statement* stmt, GenTreeCall* call);
6000     static fgWalkPreFn fgFindNonInlineCandidate;
6001 #endif
6002     GenTree* fgOptimizeDelegateConstructor(GenTreeCall*            call,
6003                                            CORINFO_CONTEXT_HANDLE* ExactContextHnd,
6004                                            methodPointerInfo*      ldftnToken);
6005     GenTree* fgMorphLeaf(GenTree* tree);
6006 public:
6007     GenTree* fgMorphInitBlock(GenTree* tree);
6008     GenTree* fgMorphCopyBlock(GenTree* tree);
6009     GenTree* fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree);
6010 private:
6011     GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optAssertionPropDone = nullptr);
6012     void fgTryReplaceStructLocalWithField(GenTree* tree);
6013     GenTree* fgMorphFinalizeIndir(GenTreeIndir* indir);
6014     GenTree* fgOptimizeCast(GenTreeCast* cast);
6015     GenTree* fgOptimizeCastOnStore(GenTree* store);
6016     GenTree* fgOptimizeBitCast(GenTreeUnOp* bitCast);
6017     GenTree* fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp);
6018     GenTree* fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp);
6019     GenTree* fgOptimizeRelationalComparisonWithFullRangeConst(GenTreeOp* cmp);
6020 #ifdef FEATURE_HW_INTRINSICS
6021     GenTree* fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node);
6022 #endif
6023     GenTree* fgOptimizeCommutativeArithmetic(GenTreeOp* tree);
6024     GenTree* fgOptimizeRelationalComparisonWithCasts(GenTreeOp* cmp);
6025     GenTree* fgOptimizeAddition(GenTreeOp* add);
6026     GenTree* fgOptimizeMultiply(GenTreeOp* mul);
6027     GenTree* fgOptimizeBitwiseAnd(GenTreeOp* andOp);
6028     GenTree* fgOptimizeBitwiseXor(GenTreeOp* xorOp);
6029     GenTree* fgPropagateCommaThrow(GenTree* parent, GenTreeOp* commaThrow, GenTreeFlags precedingSideEffects);
6030     GenTree* fgMorphRetInd(GenTreeUnOp* tree);
6031     GenTree* fgMorphModToZero(GenTreeOp* tree);
6032     GenTree* fgMorphModToSubMulDiv(GenTreeOp* tree);
6033     GenTree* fgMorphUModToAndSub(GenTreeOp* tree);
6034     GenTree* fgMorphSmpOpOptional(GenTreeOp* tree, bool* optAssertionPropDone);
6035     GenTree* fgMorphMultiOp(GenTreeMultiOp* multiOp);
6036     GenTree* fgMorphConst(GenTree* tree);
6037
6038     GenTreeOp* fgMorphCommutative(GenTreeOp* tree);
6039
6040     GenTree* fgMorphReduceAddOps(GenTree* tree);
6041
6042 public:
6043     GenTree* fgMorphTree(GenTree* tree, MorphAddrContext* mac = nullptr);
6044
6045 private:
6046     void fgKillDependentAssertionsSingle(unsigned lclNum DEBUGARG(GenTree* tree));
6047     void fgKillDependentAssertions(unsigned lclNum DEBUGARG(GenTree* tree));
6048     void fgMorphTreeDone(GenTree* tree);
6049     void fgMorphTreeDone(GenTree* tree, bool optAssertionPropDone, bool isMorphedTree DEBUGARG(int morphNum = 0));
6050
6051     Statement* fgMorphStmt;
6052     unsigned   fgBigOffsetMorphingTemps[TYP_COUNT];
6053
6054     unsigned fgGetFieldMorphingTemp(GenTreeFieldAddr* fieldNode);
6055
6056     //----------------------- Liveness analysis -------------------------------
6057
6058     VARSET_TP fgCurUseSet; // vars used     by block (before an assignment)
6059     VARSET_TP fgCurDefSet; // vars assigned by block (before a use)
6060
6061     MemoryKindSet fgCurMemoryUse;   // True iff the current basic block uses memory.
6062     MemoryKindSet fgCurMemoryDef;   // True iff the current basic block modifies memory.
6063     MemoryKindSet fgCurMemoryHavoc; // True if  the current basic block is known to set memory to a "havoc" value.
6064
6065     bool byrefStatesMatchGcHeapStates; // True iff GcHeap and ByrefExposed memory have all the same def points.
6066
6067     PhaseStatus fgEarlyLiveness();
6068
6069     void fgMarkUseDef(GenTreeLclVarCommon* tree);
6070
6071     void fgBeginScopeLife(VARSET_TP* inScope, VarScopeDsc* var);
6072     void fgEndScopeLife(VARSET_TP* inScope, VarScopeDsc* var);
6073
6074     void fgMarkInScope(BasicBlock* block, VARSET_VALARG_TP inScope);
6075     void fgUnmarkInScope(BasicBlock* block, VARSET_VALARG_TP unmarkScope);
6076
6077     void fgExtendDbgScopes();
6078     void fgExtendDbgLifetimes();
6079
6080 #ifdef DEBUG
6081     void fgDispDebugScopes();
6082 #endif // DEBUG
6083
6084     //-------------------------------------------------------------------------
6085     //
6086     //  The following keeps track of any code we've added for things like array
6087     //  range checking or explicit calls to enable GC, and so on.
6088     //
6089 public:
6090     struct AddCodeDsc
6091     {
6092         AddCodeDsc*     acdNext;
6093         BasicBlock*     acdDstBlk; // block  to  which we jump
6094         unsigned        acdData;
6095         SpecialCodeKind acdKind; // what kind of a special block is this?
6096 #if !FEATURE_FIXED_OUT_ARGS
6097         bool     acdStkLvlInit; // has acdStkLvl value been already set?
6098         unsigned acdStkLvl;     // stack level in stack slots.
6099 #endif                          // !FEATURE_FIXED_OUT_ARGS
6100     };
6101
6102 private:
6103     static unsigned acdHelper(SpecialCodeKind codeKind);
6104
6105     AddCodeDsc* fgAddCodeList;
6106     bool        fgAddCodeModf;
6107     bool        fgRngChkThrowAdded;
6108     AddCodeDsc* fgExcptnTargetCache[SCK_COUNT];
6109
6110     BasicBlock* fgRngChkTarget(BasicBlock* block, SpecialCodeKind kind);
6111
6112     BasicBlock* fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, SpecialCodeKind kind);
6113
6114 public:
6115     AddCodeDsc* fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData);
6116
6117     bool fgUseThrowHelperBlocks();
6118
6119     AddCodeDsc* fgGetAdditionalCodeDescriptors()
6120     {
6121         return fgAddCodeList;
6122     }
6123
6124 private:
6125     bool fgIsCodeAdded();
6126
6127     bool fgIsThrowHlpBlk(BasicBlock* block);
6128
6129 #if !FEATURE_FIXED_OUT_ARGS
6130     unsigned fgThrowHlpBlkStkLevel(BasicBlock* block);
6131 #endif // !FEATURE_FIXED_OUT_ARGS
6132
6133     unsigned fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo);
6134     bool IsDisallowedRecursiveInline(InlineContext* ancestor, InlineInfo* inlineInfo);
6135     bool ContextComplexityExceeds(CORINFO_CONTEXT_HANDLE handle, int max);
6136     bool MethodInstantiationComplexityExceeds(CORINFO_METHOD_HANDLE handle, int& cur, int max);
6137     bool TypeInstantiationComplexityExceeds(CORINFO_CLASS_HANDLE handle, int& cur, int max);
6138
6139     void fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* result, InlineContext** createdContext);
6140     void fgInsertInlineeBlocks(InlineInfo* pInlineInfo);
6141     Statement* fgInlinePrependStatements(InlineInfo* inlineInfo);
6142     void fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, Statement* stmt);
6143
6144 #ifdef DEBUG
6145     static fgWalkPreFn fgDebugCheckInlineCandidates;
6146
6147     void               CheckNoTransformableIndirectCallsRemain();
6148     static fgWalkPreFn fgDebugCheckForTransformableIndirectCalls;
6149 #endif
6150
6151     PhaseStatus fgPromoteStructs();
6152     void fgMorphLocalField(GenTree* tree, GenTree* parent);
6153
6154     // Reset the refCount for implicit byrefs.
6155     void fgResetImplicitByRefRefCount();
6156
6157     // Identify all candidates for last-use copy omission.
6158     PhaseStatus fgMarkImplicitByRefCopyOmissionCandidates();
6159
6160     // Change implicit byrefs' types from struct to pointer, and for any that were
6161     // promoted, create new promoted struct temps.
6162     PhaseStatus fgRetypeImplicitByRefArgs();
6163
6164     // Clear up annotations for any struct promotion temps created for implicit byrefs.
6165     void fgMarkDemotedImplicitByRefArgs();
6166
6167     PhaseStatus fgMarkAddressExposedLocals();
6168     void fgSequenceLocals(Statement* stmt);
6169
6170     PhaseStatus PhysicalPromotion();
6171
6172     PhaseStatus fgForwardSub();
6173     bool fgForwardSubBlock(BasicBlock* block);
6174     bool fgForwardSubStatement(Statement* statement);
6175     bool fgForwardSubHasStoreInterference(Statement* defStmt, Statement* nextStmt, GenTree* nextStmtUse);
6176     void fgForwardSubUpdateLiveness(GenTree* newSubListFirst, GenTree* newSubListLast);
6177
6178     // The given local variable, required to be a struct variable, is being assigned via
6179     // a "lclField", to make it masquerade as an integral type in the ABI.  Make sure that
6180     // the variable is not enregistered, and is therefore not promoted independently.
6181     void fgLclFldAssign(unsigned lclNum);
6182
6183     enum TypeProducerKind
6184     {
6185         TPK_Unknown = 0, // May not be a RuntimeType
6186         TPK_Handle  = 1, // RuntimeType via handle
6187         TPK_GetType = 2, // RuntimeType via Object.get_Type()
6188         TPK_Null    = 3, // Tree value is null
6189         TPK_Other   = 4  // RuntimeType via other means
6190     };
6191
6192     TypeProducerKind gtGetTypeProducerKind(GenTree* tree);
6193     bool gtIsTypeHandleToRuntimeTypeHelper(GenTreeCall* call);
6194     bool gtIsTypeHandleToRuntimeTypeHandleHelper(GenTreeCall* call, CorInfoHelpFunc* pHelper = nullptr);
6195     bool gtIsActiveCSE_Candidate(GenTree* tree);
6196
6197     bool gtTreeContainsOper(GenTree* tree, genTreeOps op);
6198     ExceptionSetFlags gtCollectExceptions(GenTree* tree);
6199
6200 public:
6201     bool fgIsBigOffset(size_t offset);
6202
6203 private:
6204     bool fgNeedReturnSpillTemp();
6205
6206     /*
6207     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6208     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6209     XX                                                                           XX
6210     XX                           Optimizer                                       XX
6211     XX                                                                           XX
6212     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6213     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6214     */
6215
6216 public:
6217     void optInit();
6218
6219     PhaseStatus rangeCheckPhase();
6220     GenTree* optRemoveRangeCheck(GenTreeBoundsChk* check, GenTree* comma, Statement* stmt);
6221     GenTree* optRemoveStandaloneRangeCheck(GenTreeBoundsChk* check, Statement* stmt);
6222     void optRemoveCommaBasedRangeCheck(GenTree* comma, Statement* stmt);
6223
6224 protected:
6225     // Do hoisting for all loops.
6226     PhaseStatus optHoistLoopCode();
6227
6228     // To represent sets of VN's that have already been hoisted in outer loops.
6229     typedef JitHashTable<ValueNum, JitSmallPrimitiveKeyFuncs<ValueNum>, bool> VNSet;
6230
6231     struct LoopHoistContext
6232     {
6233     private:
6234         // The set of variables hoisted in the current loop (or nullptr if there are none).
6235         VNSet* m_pHoistedInCurLoop;
6236
6237     public:
6238         // Value numbers of expressions that have been hoisted in the current (or most recent) loop in the nest.
6239         // Previous decisions on loop-invariance of value numbers in the current loop.
6240         VNSet m_curLoopVnInvariantCache;
6241
6242         // Get the VN cache for current loop
6243         VNSet* GetHoistedInCurLoop(Compiler* comp)
6244         {
6245             if (m_pHoistedInCurLoop == nullptr)
6246             {
6247                 m_pHoistedInCurLoop = new (comp->getAllocatorLoopHoist()) VNSet(comp->getAllocatorLoopHoist());
6248             }
6249             return m_pHoistedInCurLoop;
6250         }
6251
6252         // Return the so far collected VNs in cache for current loop and reset it.
6253         void ResetHoistedInCurLoop()
6254         {
6255             m_pHoistedInCurLoop = nullptr;
6256             JITDUMP("Resetting m_pHoistedInCurLoop\n");
6257         }
6258
6259         LoopHoistContext(Compiler* comp)
6260             : m_pHoistedInCurLoop(nullptr), m_curLoopVnInvariantCache(comp->getAllocatorLoopHoist())
6261         {
6262         }
6263     };
6264
6265     // Do hoisting of all loops nested within loop "lnum" (an index into the optLoopTable), followed
6266     // by the loop "lnum" itself.
6267     bool optHoistLoopNest(unsigned lnum, LoopHoistContext* hoistCtxt);
6268
6269     // Do hoisting for a particular loop ("lnum" is an index into the optLoopTable.)
6270     bool optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt);
6271
6272     // Hoist all expressions in "blocks" that are invariant in loop "loopNum" (an index into the optLoopTable)
6273     // outside of that loop.
6274     void optHoistLoopBlocks(unsigned loopNum, ArrayStack<BasicBlock*>* blocks, LoopHoistContext* hoistContext);
6275
6276     // Return true if the tree looks profitable to hoist out of loop 'lnum'.
6277     bool optIsProfitableToHoistTree(GenTree* tree, unsigned lnum);
6278
6279     // Performs the hoisting 'tree' into the PreHeader for loop 'lnum'
6280     void optHoistCandidate(GenTree* tree, BasicBlock* treeBb, unsigned lnum, LoopHoistContext* hoistCtxt);
6281
6282     // Note the new SSA uses in tree
6283     void optRecordSsaUses(GenTree* tree, BasicBlock* block);
6284
6285     // Returns true iff the ValueNum "vn" represents a value that is loop-invariant in "lnum".
6286     //   Constants and init values are always loop invariant.
6287     //   VNPhi's connect VN's to the SSA definition, so we can know if the SSA def occurs in the loop.
6288     bool optVNIsLoopInvariant(ValueNum vn, unsigned lnum, VNSet* recordedVNs);
6289
6290     // If "blk" is the entry block of a natural loop, returns true and sets "*pLnum" to the index of the loop
6291     // in the loop table.
6292     bool optBlockIsLoopEntry(BasicBlock* blk, unsigned* pLnum);
6293
6294     // Records the set of "side effects" of all loops: fields (object instance and static)
6295     // written to, and SZ-array element type equivalence classes updated.
6296     void optComputeLoopSideEffects();
6297
6298     // Compute the sets of long and float vars (lvaLongVars, lvaFloatVars).
6299     void optComputeInterestingVarSets();
6300
6301 #ifdef DEBUG
6302     bool optAnyChildNotRemoved(unsigned loopNum);
6303 #endif // DEBUG
6304
6305     // Mark a loop as removed.
6306     void optMarkLoopRemoved(unsigned loopNum);
6307
6308 private:
6309     // Requires "lnum" to be the index of an outermost loop in the loop table.  Traverses the body of that loop,
6310     // including all nested loops, and records the set of "side effects" of the loop: fields (object instance and
6311     // static) written to, and SZ-array element type equivalence classes updated.
6312     void optComputeLoopNestSideEffects(unsigned lnum);
6313
6314     // Given a loop number 'lnum' mark it and any nested loops as having 'memoryHavoc'
6315     void optRecordLoopNestsMemoryHavoc(unsigned lnum, MemoryKindSet memoryHavoc);
6316
6317     // Add the side effects of "blk" (which is required to be within a loop) to all loops of which it is a part.
6318     // Returns false if we encounter a block that is not marked as being inside a loop.
6319     //
6320     bool optComputeLoopSideEffectsOfBlock(BasicBlock* blk);
6321
6322     // Hoist the expression "expr" out of loop "lnum".
6323     void optPerformHoistExpr(GenTree* expr, BasicBlock* exprBb, unsigned lnum);
6324
6325 public:
6326     PhaseStatus optOptimizeBools();
6327
6328 public:
6329     PhaseStatus optInvertLoops();    // Invert loops so they're entered at top and tested at bottom.
6330     PhaseStatus optOptimizeFlow();   // Simplify flow graph and do tail duplication
6331     PhaseStatus optOptimizeLayout(); // Optimize the BasicBlock layout of the method
6332     PhaseStatus optSetBlockWeights();
6333     PhaseStatus optFindLoopsPhase(); // Finds loops and records them in the loop table
6334
6335     void optFindLoops();
6336
6337     PhaseStatus optCloneLoops();
6338     void optCloneLoop(unsigned loopInd, LoopCloneContext* context);
6339     PhaseStatus optUnrollLoops(); // Unrolls loops (needs to have cost info)
6340     void        optRemoveRedundantZeroInits();
6341     PhaseStatus optIfConversion(); // If conversion
6342
6343 protected:
6344     // This enumeration describes what is killed by a call.
6345
6346     enum callInterf
6347     {
6348         CALLINT_NONE,       // no interference                               (most helpers)
6349         CALLINT_REF_INDIRS, // kills GC ref indirections                     (SETFIELD OBJ)
6350         CALLINT_SCL_INDIRS, // kills non GC ref indirections                 (SETFIELD non-OBJ)
6351         CALLINT_ALL_INDIRS, // kills both GC ref and non GC ref indirections (SETFIELD STRUCT)
6352         CALLINT_ALL,        // kills everything                              (normal method call)
6353     };
6354
6355     enum class FieldKindForVN
6356     {
6357         SimpleStatic,
6358         WithBaseAddr
6359     };
6360
6361 public:
6362     // A "LoopDsc" describes a ("natural") loop.  We (currently) require the body of a loop to be a contiguous (in
6363     // bbNext order) sequence of basic blocks.  (At times, we may require the blocks in a loop to be "properly numbered"
6364     // in bbNext order; we use comparisons on the bbNum to decide order.)
6365     // The blocks that define the body are
6366     //   top <= entry <= bottom
6367     // The "head" of the loop is a block outside the loop that has "entry" as a successor. We only support loops with a
6368     // single 'head' block. The meanings of these blocks are given in the definitions below. Also see the picture at
6369     // Compiler::optFindNaturalLoops().
6370     struct LoopDsc
6371     {
6372         BasicBlock* lpHead;   // HEAD of the loop (not part of the looping of the loop) -- has ENTRY as a successor.
6373         BasicBlock* lpTop;    // loop TOP (the back edge from lpBottom reaches here). Lexically first block (in bbNext
6374                               // order) reachable in this loop.
6375         BasicBlock* lpEntry;  // the ENTRY in the loop (in most cases TOP or BOTTOM)
6376         BasicBlock* lpBottom; // loop BOTTOM (from here we have a back edge to the TOP)
6377         BasicBlock* lpExit;   // if a single exit loop this is the EXIT (in most cases BOTTOM)
6378
6379         callInterf   lpAsgCall;     // "callInterf" for calls in the loop
6380         ALLVARSET_TP lpAsgVars;     // set of vars assigned within the loop (all vars, not just tracked)
6381         varRefKinds  lpAsgInds : 8; // set of inds modified within the loop
6382
6383         LoopFlags lpFlags;
6384
6385         unsigned char lpExitCnt; // number of exits from the loop
6386
6387         unsigned char lpParent;  // The index of the most-nested loop that completely contains this one,
6388                                  // or else BasicBlock::NOT_IN_LOOP if no such loop exists.
6389         unsigned char lpChild;   // The index of a nested loop, or else BasicBlock::NOT_IN_LOOP if no child exists.
6390                                  // (Actually, an "immediately" nested loop --
6391                                  // no other child of this loop is a parent of lpChild.)
6392         unsigned char lpSibling; // The index of another loop that is an immediate child of lpParent,
6393                                  // or else BasicBlock::NOT_IN_LOOP.  One can enumerate all the children of a loop
6394                                  // by following "lpChild" then "lpSibling" links.
6395
6396         bool lpLoopHasMemoryHavoc[MemoryKindCount]; // The loop contains an operation that we assume has arbitrary
6397                                                     // memory side effects.  If this is set, the fields below
6398                                                     // may not be accurate (since they become irrelevant.)
6399
6400         VARSET_TP lpVarInOut;  // The set of variables that are IN or OUT during the execution of this loop
6401         VARSET_TP lpVarUseDef; // The set of variables that are USE or DEF during the execution of this loop
6402
6403         // The following counts are used for hoisting profitability checks.
6404
6405         int lpHoistedExprCount; // The register count for the non-FP expressions from inside this loop that have been
6406                                 // hoisted
6407         int lpLoopVarCount;     // The register count for the non-FP LclVars that are read/written inside this loop
6408         int lpVarInOutCount;    // The register count for the non-FP LclVars that are alive inside or across this loop
6409
6410         int lpHoistedFPExprCount; // The register count for the FP expressions from inside this loop that have been
6411                                   // hoisted
6412         int lpLoopVarFPCount;     // The register count for the FP LclVars that are read/written inside this loop
6413         int lpVarInOutFPCount;    // The register count for the FP LclVars that are alive inside or across this loop
6414
6415         typedef JitHashTable<CORINFO_FIELD_HANDLE, JitPtrKeyFuncs<struct CORINFO_FIELD_STRUCT_>, FieldKindForVN>
6416                         FieldHandleSet;
6417         FieldHandleSet* lpFieldsModified; // This has entries for all static field and object instance fields modified
6418                                           // in the loop.
6419
6420         typedef JitHashTable<CORINFO_CLASS_HANDLE, JitPtrKeyFuncs<struct CORINFO_CLASS_STRUCT_>, bool> ClassHandleSet;
6421         ClassHandleSet* lpArrayElemTypesModified; // Bits set indicate the set of sz array element types such that
6422                                                   // arrays of that type are modified
6423                                                   // in the loop.
6424
6425         // Adds the variable liveness information for 'blk' to 'this' LoopDsc
6426         void AddVariableLiveness(Compiler* comp, BasicBlock* blk);
6427
6428         inline void AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind);
6429         // This doesn't *always* take a class handle -- it can also take primitive types, encoded as class handles
6430         // (shifted left, with a low-order bit set to distinguish.)
6431         // Use the {Encode/Decode}ElemType methods to construct/destruct these.
6432         inline void AddModifiedElemType(Compiler* comp, CORINFO_CLASS_HANDLE structHnd);
6433
6434         /* The following values are set only for iterator loops, i.e. has the flag LPFLG_ITER set */
6435
6436         GenTree*   lpIterTree;          // The "i = i <op> const" tree
6437         unsigned   lpIterVar() const;   // iterator variable #
6438         int        lpIterConst() const; // the constant with which the iterator is incremented
6439         genTreeOps lpIterOper() const;  // the type of the operation on the iterator (ADD, SUB, etc.)
6440         void       VERIFY_lpIterTree() const;
6441
6442         var_types lpIterOperType() const; // For overflow instructions
6443
6444         // Set to the block where we found the initialization for LPFLG_CONST_INIT loops.
6445         // Initially, this will be 'head', but 'head' might change if we insert a loop pre-header block.
6446         BasicBlock* lpInitBlock;
6447
6448         int lpConstInit; // initial constant value of iterator : Valid if LPFLG_CONST_INIT
6449
6450         // The following is for LPFLG_ITER loops only (i.e. the loop condition is "i RELOP const or var")
6451
6452         GenTree*   lpTestTree;         // pointer to the node containing the loop test
6453         genTreeOps lpTestOper() const; // the type of the comparison between the iterator and the limit (GT_LE, GT_GE,
6454                                        // etc.)
6455
6456         bool lpIsIncreasingLoop() const; // if the loop iterator increases from low to high value.
6457         bool lpIsDecreasingLoop() const; // if the loop iterator decreases from high to low value.
6458
6459         void VERIFY_lpTestTree() const;
6460
6461         bool     lpIsReversed() const; // true if the iterator node is the second operand in the loop condition
6462         GenTree* lpIterator() const;   // the iterator node in the loop test
6463         GenTree* lpLimit() const;      // the limit node in the loop test
6464
6465         // Limit constant value of iterator - loop condition is "i RELOP const"
6466         // : Valid if LPFLG_CONST_LIMIT
6467         int lpConstLimit() const;
6468
6469         // The lclVar # in the loop condition ( "i RELOP lclVar" )
6470         // : Valid if LPFLG_VAR_LIMIT
6471         unsigned lpVarLimit() const;
6472
6473         // The array length in the loop condition ( "i RELOP arr.len" or "i RELOP arr[i][j].len" )
6474         // : Valid if LPFLG_ARRLEN_LIMIT
6475         bool lpArrLenLimit(Compiler* comp, ArrIndex* index) const;
6476
6477         // Returns "true" iff this is a "top entry" loop.
6478         bool lpIsTopEntry() const
6479         {
6480             if (lpHead->bbNext == lpEntry)
6481             {
6482                 assert(lpHead->bbFallsThrough());
6483                 assert(lpTop == lpEntry);
6484                 return true;
6485             }
6486             else
6487             {
6488                 return false;
6489             }
6490         }
6491
6492         // Returns "true" iff this is removed loop.
6493         bool lpIsRemoved() const
6494         {
6495             return (lpFlags & LPFLG_REMOVED) != 0;
6496         }
6497
6498         // Returns "true" iff "*this" contains the blk.
6499         bool lpContains(BasicBlock* blk) const
6500         {
6501             return lpTop->bbNum <= blk->bbNum && blk->bbNum <= lpBottom->bbNum;
6502         }
6503
6504         // Returns "true" iff "*this" (properly) contains the range [top, bottom] (allowing tops
6505         // to be equal, but requiring bottoms to be different.)
6506         bool lpContains(BasicBlock* top, BasicBlock* bottom) const
6507         {
6508             return lpTop->bbNum <= top->bbNum && bottom->bbNum < lpBottom->bbNum;
6509         }
6510
6511         // Returns "true" iff "*this" (properly) contains "lp2" (allowing tops to be equal, but requiring
6512         // bottoms to be different.)
6513         bool lpContains(const LoopDsc& lp2) const
6514         {
6515             return lpContains(lp2.lpTop, lp2.lpBottom);
6516         }
6517
6518         // Returns "true" iff "*this" is (properly) contained by the range [top, bottom]
6519         // (allowing tops to be equal, but requiring bottoms to be different.)
6520         bool lpContainedBy(BasicBlock* top, BasicBlock* bottom) const
6521         {
6522             return top->bbNum <= lpTop->bbNum && lpBottom->bbNum < bottom->bbNum;
6523         }
6524
6525         // Returns "true" iff "*this" is (properly) contained by "lp2"
6526         // (allowing tops to be equal, but requiring bottoms to be different.)
6527         bool lpContainedBy(const LoopDsc& lp2) const
6528         {
6529             return lpContainedBy(lp2.lpTop, lp2.lpBottom);
6530         }
6531
6532         // Returns "true" iff "*this" is disjoint from the range [top, bottom].
6533         bool lpDisjoint(BasicBlock* top, BasicBlock* bottom) const
6534         {
6535             return bottom->bbNum < lpTop->bbNum || lpBottom->bbNum < top->bbNum;
6536         }
6537         // Returns "true" iff "*this" is disjoint from "lp2".
6538         bool lpDisjoint(const LoopDsc& lp2) const
6539         {
6540             return lpDisjoint(lp2.lpTop, lp2.lpBottom);
6541         }
6542
6543         // Returns "true" iff the loop is well-formed (see code for defn).
6544         bool lpWellFormed() const
6545         {
6546             return lpTop->bbNum <= lpEntry->bbNum && lpEntry->bbNum <= lpBottom->bbNum &&
6547                    (lpHead->bbNum < lpTop->bbNum || lpHead->bbNum > lpBottom->bbNum);
6548         }
6549
6550 #ifdef DEBUG
6551         void lpValidatePreHeader() const
6552         {
6553             // If this is called, we expect there to be a pre-header.
6554             assert(lpFlags & LPFLG_HAS_PREHEAD);
6555
6556             // The pre-header must unconditionally enter the loop.
6557             assert(lpHead->GetUniqueSucc() == lpEntry);
6558
6559             // The loop block must be marked as a pre-header.
6560             assert(lpHead->bbFlags & BBF_LOOP_PREHEADER);
6561
6562             // The loop entry must have a single non-loop predecessor, which is the pre-header.
6563             // We can't assume here that the bbNum are properly ordered, so we can't do a simple lpContained()
6564             // check. So, we defer this check, which will be done by `fgDebugCheckLoopTable()`.
6565         }
6566 #endif // DEBUG
6567
6568         // LoopBlocks: convenience method for enabling range-based `for` iteration over all the
6569         // blocks in a loop, e.g.:
6570         //    for (BasicBlock* const block : loop->LoopBlocks()) ...
6571         // Currently, the loop blocks are expected to be in linear, lexical, `bbNext` order
6572         // from `lpTop` through `lpBottom`, inclusive. All blocks in this range are considered
6573         // to be part of the loop.
6574         //
6575         BasicBlockRangeList LoopBlocks() const
6576         {
6577             return BasicBlockRangeList(lpTop, lpBottom);
6578         }
6579     };
6580
6581 protected:
6582     bool fgMightHaveLoop(); // returns true if there are any back edges
6583     bool fgHasLoops;        // True if this method has any loops, set in fgComputeReachability
6584
6585 public:
6586     LoopDsc*      optLoopTable;              // loop descriptor table
6587     bool          optLoopTableValid;         // info in loop table should be valid
6588     bool          optLoopsRequirePreHeaders; // Do we require that all loops (in the loop table) have pre-headers?
6589     unsigned char optLoopCount;              // number of tracked loops
6590     unsigned char loopAlignCandidates;       // number of loops identified for alignment
6591
6592     // Every time we rebuild the loop table, we increase the global "loop epoch". Any loop indices or
6593     // loop table pointers from the previous epoch are invalid.
6594     // TODO: validate this in some way?
6595     unsigned optCurLoopEpoch;
6596
6597     void NewLoopEpoch()
6598     {
6599         ++optCurLoopEpoch;
6600         JITDUMP("New loop epoch %d\n", optCurLoopEpoch);
6601     }
6602
6603 #ifdef DEBUG
6604     unsigned char loopsAligned; // number of loops actually aligned
6605 #endif                          // DEBUG
6606
6607     bool optRecordLoop(BasicBlock*   head,
6608                        BasicBlock*   top,
6609                        BasicBlock*   entry,
6610                        BasicBlock*   bottom,
6611                        BasicBlock*   exit,
6612                        unsigned char exitCnt);
6613
6614     PhaseStatus optClearLoopIterInfo();
6615
6616 #ifdef DEBUG
6617     void optPrintLoopInfo(unsigned lnum, bool printVerbose = false);
6618     void optPrintLoopInfo(const LoopDsc* loop, bool printVerbose = false);
6619     void optPrintLoopTable();
6620 #endif
6621
6622 protected:
6623     unsigned optCallCount;         // number of calls made in the method
6624     unsigned optIndirectCallCount; // number of virtual, interface and indirect calls made in the method
6625     unsigned optNativeCallCount;   // number of Pinvoke/Native calls made in the method
6626     unsigned optLoopsCloned;       // number of loops cloned in the current method.
6627
6628 #ifdef DEBUG
6629     void optCheckPreds();
6630 #endif
6631
6632     void optResetLoopInfo();
6633     void optFindAndScaleGeneralLoopBlocks();
6634
6635     // Determine if there are any potential loops, and set BBF_LOOP_HEAD on potential loop heads.
6636     void optMarkLoopHeads();
6637
6638     void optScaleLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk);
6639
6640     void optUnmarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk);
6641
6642     void optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmarkLoop = false);
6643
6644     bool optIsLoopTestEvalIntoTemp(Statement* testStmt, Statement** newTestStmt);
6645     unsigned optIsLoopIncrTree(GenTree* incr);
6646     bool optCheckIterInLoopTest(unsigned loopInd, GenTree* test, unsigned iterVar);
6647     bool optComputeIterInfo(GenTree* incr, BasicBlock* from, BasicBlock* to, unsigned* pIterVar);
6648     bool optPopulateInitInfo(unsigned loopInd, BasicBlock* initBlock, GenTree* init, unsigned iterVar);
6649     bool optExtractInitTestIncr(
6650         BasicBlock** pInitBlock, BasicBlock* bottom, BasicBlock* exit, GenTree** ppInit, GenTree** ppTest, GenTree** ppIncr);
6651
6652     void optFindNaturalLoops();
6653
6654     void optIdentifyLoopsForAlignment();
6655
6656     // Ensures that all the loops in the loop nest rooted at "loopInd" (an index into the loop table) are 'canonical' --
6657     // each loop has a unique "top."  Returns "true" iff the flowgraph has been modified.
6658     bool optCanonicalizeLoopNest(unsigned char loopInd);
6659
6660     // Ensures that the loop "loopInd" (an index into the loop table) is 'canonical' -- it has a unique "top,"
6661     // unshared with any other loop.  Returns "true" iff the flowgraph has been modified
6662     bool optCanonicalizeLoop(unsigned char loopInd);
6663
6664     enum class LoopCanonicalizationOption
6665     {
6666         Outer,
6667         Current
6668     };
6669
6670     bool optCanonicalizeLoopCore(unsigned char loopInd, LoopCanonicalizationOption option);
6671
6672     // Requires "l1" to be a valid loop table index, and not "BasicBlock::NOT_IN_LOOP".
6673     // Requires "l2" to be a valid loop table index, or else "BasicBlock::NOT_IN_LOOP".
6674     // Returns true iff "l2" is not NOT_IN_LOOP, and "l1" contains "l2".
6675     // A loop contains itself.
6676     bool optLoopContains(unsigned l1, unsigned l2) const;
6677
6678     // Returns the lpEntry for given preheader block of a loop
6679     BasicBlock* optLoopEntry(BasicBlock* preHeader);
6680
6681     // Updates the loop table by changing loop "loopInd", whose head is required
6682     // to be "from", to be "to".  Also performs this transformation for any
6683     // loop nested in "loopInd" that shares the same head as "loopInd".
6684     void optUpdateLoopHead(unsigned loopInd, BasicBlock* from, BasicBlock* to);
6685
6686     enum class RedirectBlockOption
6687     {
6688         DoNotChangePredLists, // do not modify pred lists
6689         UpdatePredLists,      // add/remove to pred lists
6690         AddToPredLists,       // only add to pred lists
6691     };
6692
6693     void optRedirectBlock(BasicBlock*      blk,
6694                           BlockToBlockMap* redirectMap,
6695                           const RedirectBlockOption = RedirectBlockOption::DoNotChangePredLists);
6696
6697     // Marks the containsCall information to "lnum" and any parent loops.
6698     void AddContainsCallAllContainingLoops(unsigned lnum);
6699
6700     // Adds the variable liveness information from 'blk' to "lnum" and any parent loops.
6701     void AddVariableLivenessAllContainingLoops(unsigned lnum, BasicBlock* blk);
6702
6703     // Adds "fldHnd" to the set of modified fields of "lnum" and any parent loops.
6704     void AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind);
6705
6706     // Adds "elemType" to the set of modified array element types of "lnum" and any parent loops.
6707     void AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLASS_HANDLE elemType);
6708
6709     // Requires that "from" and "to" have the same "bbJumpKind" (perhaps because "to" is a clone
6710     // of "from".)  Copies the jump destination from "from" to "to".
6711     void optCopyBlkDest(BasicBlock* from, BasicBlock* to);
6712
6713     // Returns true if 'block' is an entry block for any loop in 'optLoopTable'
6714     bool optIsLoopEntry(BasicBlock* block) const;
6715
6716     // The depth of the loop described by "lnum" (an index into the loop table.) (0 == top level)
6717     unsigned optLoopDepth(unsigned lnum) const
6718     {
6719         assert(lnum < optLoopCount);
6720         unsigned depth = 0;
6721         while ((lnum = optLoopTable[lnum].lpParent) != BasicBlock::NOT_IN_LOOP)
6722         {
6723             ++depth;
6724         }
6725         return depth;
6726     }
6727
6728     // Struct used in optInvertWhileLoop to count interesting constructs to boost the profitability score.
6729     struct OptInvertCountTreeInfoType
6730     {
6731         int sharedStaticHelperCount;
6732         int arrayLengthCount;
6733     };
6734
6735     OptInvertCountTreeInfoType optInvertCountTreeInfo(GenTree* tree);
6736
6737     bool optInvertWhileLoop(BasicBlock* block);
6738     bool optIfConvert(BasicBlock* block);
6739
6740 private:
6741     static bool optIterSmallOverflow(int iterAtExit, var_types incrType);
6742     static bool optIterSmallUnderflow(int iterAtExit, var_types decrType);
6743
6744     bool optComputeLoopRep(int        constInit,
6745                            int        constLimit,
6746                            int        iterInc,
6747                            genTreeOps iterOper,
6748                            var_types  iterType,
6749                            genTreeOps testOper,
6750                            bool       unsignedTest,
6751                            bool       dupCond,
6752                            unsigned*  iterCount);
6753
6754 protected:
6755     struct isVarAssgDsc
6756     {
6757         GenTree*     ivaSkip;
6758         ALLVARSET_TP ivaMaskVal;        // Set of variables assigned to.  This is a set of all vars, not tracked vars.
6759         unsigned     ivaVar;            // Variable we are interested in, or -1
6760         varRefKinds  ivaMaskInd;        // What kind of indirect assignments are there?
6761         callInterf   ivaMaskCall;       // What kind of calls are there?
6762         bool         ivaMaskIncomplete; // Variables not representable in ivaMaskVal were assigned to.
6763     };
6764
6765     bool optIsVarAssignedWithDesc(Statement* stmt, isVarAssgDsc* dsc);
6766
6767     bool optIsVarAssigned(BasicBlock* beg, BasicBlock* end, GenTree* skip, unsigned var);
6768
6769     bool optIsVarAssgLoop(unsigned lnum, unsigned var);
6770
6771     bool optIsSetAssgLoop(unsigned lnum, ALLVARSET_VALARG_TP vars, varRefKinds inds = VR_NONE);
6772
6773     bool optNarrowTree(GenTree* tree, var_types srct, var_types dstt, ValueNumPair vnpNarrow, bool doit);
6774
6775 protected:
6776     //  The following is the upper limit on how many expressions we'll keep track
6777     //  of for the CSE analysis.
6778     //
6779     static const unsigned MAX_CSE_CNT = EXPSET_SZ;
6780
6781     static const int MIN_CSE_COST = 2;
6782
6783     // BitVec trait information only used by the optCSE_canSwap() method, for the  CSE_defMask and CSE_useMask.
6784     // This BitVec uses one bit per CSE candidate
6785     BitVecTraits* cseMaskTraits; // one bit per CSE candidate
6786
6787     // BitVec trait information for computing CSE availability using the CSE_DataFlow algorithm.
6788     // Two bits are allocated per CSE candidate to compute CSE availability
6789     // plus an extra bit to handle the initial unvisited case.
6790     // (See CSE_DataFlow::EndMerge for an explanation of why this is necessary.)
6791     //
6792     // The two bits per CSE candidate have the following meanings:
6793     //     11 - The CSE is available, and is also available when considering calls as killing availability.
6794     //     10 - The CSE is available, but is not available when considering calls as killing availability.
6795     //     00 - The CSE is not available
6796     //     01 - An illegal combination
6797     //
6798     BitVecTraits* cseLivenessTraits;
6799
6800     //-----------------------------------------------------------------------------------------------------------------
6801     // getCSEnum2bit: Return the normalized index to use in the EXPSET_TP for the CSE with the given CSE index.
6802     // Each GenTree has a `gtCSEnum` field. Zero is reserved to mean this node is not a CSE, positive values indicate
6803     // CSE uses, and negative values indicate CSE defs. The caller must pass a non-zero positive value, as from
6804     // GET_CSE_INDEX().
6805     //
6806     static unsigned genCSEnum2bit(unsigned CSEnum)
6807     {
6808         assert((CSEnum > 0) && (CSEnum <= MAX_CSE_CNT));
6809         return CSEnum - 1;
6810     }
6811
6812     //-----------------------------------------------------------------------------------------------------------------
6813     // getCSEAvailBit: Return the bit used by CSE dataflow sets (bbCseGen, etc.) for the availability bit for a CSE.
6814     //
6815     static unsigned getCSEAvailBit(unsigned CSEnum)
6816     {
6817         return genCSEnum2bit(CSEnum) * 2;
6818     }
6819
6820     //-----------------------------------------------------------------------------------------------------------------
6821     // getCSEAvailCrossCallBit: Return the bit used by CSE dataflow sets (bbCseGen, etc.) for the availability bit
6822     // for a CSE considering calls as killing availability bit (see description above).
6823     //
6824     static unsigned getCSEAvailCrossCallBit(unsigned CSEnum)
6825     {
6826         return getCSEAvailBit(CSEnum) + 1;
6827     }
6828
6829     void optPrintCSEDataFlowSet(EXPSET_VALARG_TP cseDataFlowSet, bool includeBits = true);
6830
6831     EXPSET_TP cseCallKillsMask; // Computed once - A mask that is used to kill available CSEs at callsites
6832
6833     /* Generic list of nodes - used by the CSE logic */
6834
6835     struct treeLst
6836     {
6837         treeLst* tlNext;
6838         GenTree* tlTree;
6839     };
6840
6841     struct treeStmtLst
6842     {
6843         treeStmtLst* tslNext;
6844         GenTree*     tslTree;  // tree node
6845         Statement*   tslStmt;  // statement containing the tree
6846         BasicBlock*  tslBlock; // block containing the statement
6847     };
6848
6849     // The following logic keeps track of expressions via a simple hash table.
6850
6851     struct CSEdsc
6852     {
6853         CSEdsc*  csdNextInBucket;  // used by the hash table
6854         size_t   csdHashKey;       // the original hashkey
6855         ssize_t  csdConstDefValue; // When we CSE similar constants, this is the value that we use as the def
6856         ValueNum csdConstDefVN;    // When we CSE similar constants, this is the ValueNumber that we use for the LclVar
6857                                    // assignment
6858         unsigned csdIndex;         // 1..optCSECandidateCount
6859         bool     csdIsSharedConst; // true if this CSE is a shared const
6860         bool     csdLiveAcrossCall;
6861
6862         unsigned short csdDefCount; // definition   count
6863         unsigned short csdUseCount; // use          count  (excluding the implicit uses at defs)
6864
6865         weight_t csdDefWtCnt; // weighted def count
6866         weight_t csdUseWtCnt; // weighted use count  (excluding the implicit uses at defs)
6867
6868         GenTree*    csdTree;  // treenode containing the 1st occurrence
6869         Statement*  csdStmt;  // stmt containing the 1st occurrence
6870         BasicBlock* csdBlock; // block containing the 1st occurrence
6871
6872         treeStmtLst* csdTreeList; // list of matching tree nodes: head
6873         treeStmtLst* csdTreeLast; // list of matching tree nodes: tail
6874
6875         ValueNum defExcSetPromise; // The exception set that is now required for all defs of this CSE.
6876                                    // This will be set to NoVN if we decide to abandon this CSE
6877
6878         ValueNum defExcSetCurrent; // The set of exceptions we currently can use for CSE uses.
6879
6880         ValueNum defConservNormVN; // if all def occurrences share the same conservative normal value
6881                                    // number, this will reflect it; otherwise, NoVN.
6882                                    // not used for shared const CSE's
6883     };
6884
6885     static const size_t s_optCSEhashSizeInitial;
6886     static const size_t s_optCSEhashGrowthFactor;
6887     static const size_t s_optCSEhashBucketSize;
6888     size_t              optCSEhashSize;                 // The current size of hashtable
6889     size_t              optCSEhashCount;                // Number of entries in hashtable
6890     size_t              optCSEhashMaxCountBeforeResize; // Number of entries before resize
6891     CSEdsc**            optCSEhash;
6892     CSEdsc**            optCSEtab;
6893
6894     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, GenTree*> NodeToNodeMap;
6895
6896     NodeToNodeMap* optCseCheckedBoundMap; // Maps bound nodes to ancestor compares that should be
6897                                           // re-numbered with the bound to improve range check elimination
6898
6899     // Given a compare, look for a cse candidate checked bound feeding it and add a map entry if found.
6900     void optCseUpdateCheckedBoundMap(GenTree* compare);
6901
6902     void optCSEstop();
6903
6904     CSEdsc* optCSEfindDsc(unsigned index);
6905     bool optUnmarkCSE(GenTree* tree);
6906
6907     // user defined callback data for the tree walk function optCSE_MaskHelper()
6908     struct optCSE_MaskData
6909     {
6910         EXPSET_TP CSE_defMask;
6911         EXPSET_TP CSE_useMask;
6912     };
6913
6914     // Treewalk helper for optCSE_DefMask and optCSE_UseMask
6915     static fgWalkPreFn optCSE_MaskHelper;
6916
6917     // This function walks all the node for an given tree
6918     // and return the mask of CSE definitions and uses for the tree
6919     //
6920     void optCSE_GetMaskData(GenTree* tree, optCSE_MaskData* pMaskData);
6921
6922     // Given a binary tree node return true if it is safe to swap the order of evaluation for op1 and op2.
6923     bool optCSE_canSwap(GenTree* firstNode, GenTree* secondNode);
6924
6925     struct optCSEcostCmpEx
6926     {
6927         bool operator()(const CSEdsc* op1, const CSEdsc* op2);
6928     };
6929     struct optCSEcostCmpSz
6930     {
6931         bool operator()(const CSEdsc* op1, const CSEdsc* op2);
6932     };
6933
6934     void optCleanupCSEs();
6935
6936 #ifdef DEBUG
6937     void optEnsureClearCSEInfo();
6938 #endif // DEBUG
6939
6940     static bool Is_Shared_Const_CSE(size_t key)
6941     {
6942         return ((key & TARGET_SIGN_BIT) != 0);
6943     }
6944
6945     // returns the encoded key
6946     static size_t Encode_Shared_Const_CSE_Value(size_t key)
6947     {
6948         return TARGET_SIGN_BIT | (key >> CSE_CONST_SHARED_LOW_BITS);
6949     }
6950
6951     // returns the original key
6952     static size_t Decode_Shared_Const_CSE_Value(size_t enckey)
6953     {
6954         assert(Is_Shared_Const_CSE(enckey));
6955         return (enckey & ~TARGET_SIGN_BIT) << CSE_CONST_SHARED_LOW_BITS;
6956     }
6957
6958 /**************************************************************************
6959  *                   Value Number based CSEs
6960  *************************************************************************/
6961
6962 // String to use for formatting CSE numbers. Note that this is the positive number, e.g., from GET_CSE_INDEX().
6963 #define FMT_CSE "CSE #%02u"
6964
6965 public:
6966     PhaseStatus optOptimizeValnumCSEs();
6967
6968 protected:
6969     void     optValnumCSE_Init();
6970     unsigned optValnumCSE_Index(GenTree* tree, Statement* stmt);
6971     bool optValnumCSE_Locate();
6972     void optValnumCSE_InitDataFlow();
6973     void optValnumCSE_DataFlow();
6974     void optValnumCSE_Availability();
6975     bool optValnumCSE_Heuristic();
6976
6977     bool     optDoCSE;             // True when we have found a duplicate CSE tree
6978     bool     optValnumCSE_phase;   // True when we are executing the optOptimizeValnumCSEs() phase
6979     unsigned optCSECandidateCount; // Count of CSE's candidates
6980     unsigned optCSEstart;          // The first local variable number that is a CSE
6981     unsigned optCSEcount;          // The total count of CSE's introduced.
6982     weight_t optCSEweight;         // The weight of the current block when we are doing PerformCSE
6983
6984     bool optIsCSEcandidate(GenTree* tree);
6985
6986     // lclNumIsTrueCSE returns true if the LclVar was introduced by the CSE phase of the compiler
6987     //
6988     bool lclNumIsTrueCSE(unsigned lclNum) const
6989     {
6990         return ((optCSEcount > 0) && (lclNum >= optCSEstart) && (lclNum < optCSEstart + optCSEcount));
6991     }
6992
6993     //  lclNumIsCSE returns true if the LclVar should be treated like a CSE with regards to constant prop.
6994     //
6995     bool lclNumIsCSE(unsigned lclNum) const
6996     {
6997         return lvaGetDesc(lclNum)->lvIsCSE;
6998     }
6999
7000 #ifdef DEBUG
7001     bool optConfigDisableCSE();
7002     bool optConfigDisableCSE2();
7003 #endif
7004
7005     void optOptimizeCSEs();
7006
7007     static callInterf optCallInterf(GenTreeCall* call);
7008
7009 public:
7010     // VN based copy propagation.
7011
7012     // In DEBUG builds, we'd like to know the tree that the SSA definition was pushed for.
7013     // While for ordinary SSA defs it will be available (as a store) in the SSA descriptor,
7014     // for locals which will use "definitions from uses", it will not be, so we store it
7015     // in this class instead.
7016     class CopyPropSsaDef
7017     {
7018         LclSsaVarDsc* m_ssaDef;
7019 #ifdef DEBUG
7020         GenTree* m_defNode;
7021 #endif
7022     public:
7023         CopyPropSsaDef(LclSsaVarDsc* ssaDef, GenTree* defNode)
7024             : m_ssaDef(ssaDef)
7025 #ifdef DEBUG
7026             , m_defNode(defNode)
7027 #endif
7028         {
7029         }
7030
7031         LclSsaVarDsc* GetSsaDef() const
7032         {
7033             return m_ssaDef;
7034         }
7035
7036 #ifdef DEBUG
7037         GenTree* GetDefNode() const
7038         {
7039             return m_defNode;
7040         }
7041 #endif
7042     };
7043
7044     typedef ArrayStack<CopyPropSsaDef> CopyPropSsaDefStack;
7045     typedef JitHashTable<unsigned, JitSmallPrimitiveKeyFuncs<unsigned>, CopyPropSsaDefStack*> LclNumToLiveDefsMap;
7046
7047     // Copy propagation functions.
7048     bool optCopyProp(BasicBlock*          block,
7049                      Statement*           stmt,
7050                      GenTreeLclVarCommon* tree,
7051                      unsigned             lclNum,
7052                      LclNumToLiveDefsMap* curSsaName);
7053     void optBlockCopyPropPopStacks(BasicBlock* block, LclNumToLiveDefsMap* curSsaName);
7054     bool optBlockCopyProp(BasicBlock* block, LclNumToLiveDefsMap* curSsaName);
7055     void optCopyPropPushDef(GenTree* defNode, GenTreeLclVarCommon* lclNode, LclNumToLiveDefsMap* curSsaName);
7056     int optCopyProp_LclVarScore(const LclVarDsc* lclVarDsc, const LclVarDsc* copyVarDsc, bool preferOp2);
7057     PhaseStatus optVnCopyProp();
7058     INDEBUG(void optDumpCopyPropStack(LclNumToLiveDefsMap* curSsaName));
7059
7060     /**************************************************************************
7061      *               Early value propagation
7062      *************************************************************************/
7063     struct SSAName
7064     {
7065         unsigned m_lvNum;
7066         unsigned m_ssaNum;
7067
7068         SSAName(unsigned lvNum, unsigned ssaNum) : m_lvNum(lvNum), m_ssaNum(ssaNum)
7069         {
7070         }
7071
7072         static unsigned GetHashCode(SSAName ssaNm)
7073         {
7074             return (ssaNm.m_lvNum << 16) | (ssaNm.m_ssaNum);
7075         }
7076
7077         static bool Equals(SSAName ssaNm1, SSAName ssaNm2)
7078         {
7079             return (ssaNm1.m_lvNum == ssaNm2.m_lvNum) && (ssaNm1.m_ssaNum == ssaNm2.m_ssaNum);
7080         }
7081     };
7082
7083     PhaseStatus optVNBasedDeadStoreRemoval();
7084
7085 // clang-format off
7086
7087 #define OMF_HAS_NEWARRAY                       0x00000001 // Method contains 'new' of an SD array
7088 #define OMF_HAS_NEWOBJ                         0x00000002 // Method contains 'new' of an object type.
7089 #define OMF_HAS_ARRAYREF                       0x00000004 // Method contains array element loads or stores.
7090 #define OMF_HAS_NULLCHECK                      0x00000008 // Method contains null check.
7091 #define OMF_HAS_FATPOINTER                     0x00000010 // Method contains call, that needs fat pointer transformation.
7092 #define OMF_HAS_OBJSTACKALLOC                  0x00000020 // Method contains an object allocated on the stack.
7093 #define OMF_HAS_GUARDEDDEVIRT                  0x00000040 // Method contains guarded devirtualization candidate
7094 #define OMF_HAS_EXPRUNTIMELOOKUP               0x00000080 // Method contains a runtime lookup to an expandable dictionary.
7095 #define OMF_HAS_PATCHPOINT                     0x00000100 // Method contains patchpoints
7096 #define OMF_NEEDS_GCPOLLS                      0x00000200 // Method needs GC polls
7097 #define OMF_HAS_FROZEN_OBJECTS                 0x00000400 // Method has frozen objects (REF constant int)
7098 #define OMF_HAS_PARTIAL_COMPILATION_PATCHPOINT 0x00000800 // Method contains partial compilation patchpoints
7099 #define OMF_HAS_TAILCALL_SUCCESSOR             0x00001000 // Method has potential tail call in a non BBJ_RETURN block
7100 #define OMF_HAS_MDNEWARRAY                     0x00002000 // Method contains 'new' of an MD array
7101 #define OMF_HAS_MDARRAYREF                     0x00004000 // Method contains multi-dimensional intrinsic array element loads or stores.
7102 #define OMF_HAS_STATIC_INIT                    0x00008000 // Method has static initializations we might want to partially inline
7103 #define OMF_HAS_TLS_FIELD                      0x00010000 // Method contains TLS field access
7104 #define OMF_HAS_SPECIAL_INTRINSICS             0x00020000 // Method contains special intrinsics expanded in late phases
7105
7106     // clang-format on
7107
7108     bool doesMethodHaveFatPointer()
7109     {
7110         return (optMethodFlags & OMF_HAS_FATPOINTER) != 0;
7111     }
7112
7113     void setMethodHasFatPointer()
7114     {
7115         optMethodFlags |= OMF_HAS_FATPOINTER;
7116     }
7117
7118     void clearMethodHasFatPointer()
7119     {
7120         optMethodFlags &= ~OMF_HAS_FATPOINTER;
7121     }
7122
7123     void addFatPointerCandidate(GenTreeCall* call);
7124
7125     bool doesMethodHaveFrozenObjects() const
7126     {
7127         return (optMethodFlags & OMF_HAS_FROZEN_OBJECTS) != 0;
7128     }
7129
7130     void setMethodHasFrozenObjects()
7131     {
7132         optMethodFlags |= OMF_HAS_FROZEN_OBJECTS;
7133     }
7134
7135     bool doesMethodHaveStaticInit()
7136     {
7137         return (optMethodFlags & OMF_HAS_STATIC_INIT) != 0;
7138     }
7139
7140     void setMethodHasStaticInit()
7141     {
7142         optMethodFlags |= OMF_HAS_STATIC_INIT;
7143     }
7144
7145     bool doesMethodHaveGuardedDevirtualization() const
7146     {
7147         return (optMethodFlags & OMF_HAS_GUARDEDDEVIRT) != 0;
7148     }
7149
7150     void setMethodHasGuardedDevirtualization()
7151     {
7152         optMethodFlags |= OMF_HAS_GUARDEDDEVIRT;
7153     }
7154
7155     bool methodHasTlsFieldAccess()
7156     {
7157         return (optMethodFlags & OMF_HAS_TLS_FIELD) != 0;
7158     }
7159
7160     void setMethodHasTlsFieldAccess()
7161     {
7162         optMethodFlags |= OMF_HAS_TLS_FIELD;
7163     }
7164
7165     bool doesMethodHaveSpecialIntrinsics()
7166     {
7167         return (optMethodFlags & OMF_HAS_SPECIAL_INTRINSICS) != 0;
7168     }
7169
7170     void setMethodHasSpecialIntrinsics()
7171     {
7172         optMethodFlags |= OMF_HAS_SPECIAL_INTRINSICS;
7173     }
7174
7175     void pickGDV(GenTreeCall*           call,
7176                  IL_OFFSET              ilOffset,
7177                  bool                   isInterface,
7178                  CORINFO_CLASS_HANDLE*  classGuesses,
7179                  CORINFO_METHOD_HANDLE* methodGuesses,
7180                  int*                   candidatesCount,
7181                  unsigned*              likelihoods);
7182
7183     void considerGuardedDevirtualization(GenTreeCall*            call,
7184                                          IL_OFFSET               ilOffset,
7185                                          bool                    isInterface,
7186                                          CORINFO_METHOD_HANDLE   baseMethod,
7187                                          CORINFO_CLASS_HANDLE    baseClass,
7188                                          CORINFO_CONTEXT_HANDLE* pContextHandle);
7189
7190     bool isCompatibleMethodGDV(GenTreeCall* call, CORINFO_METHOD_HANDLE gdvTarget);
7191
7192     void addGuardedDevirtualizationCandidate(GenTreeCall*           call,
7193                                              CORINFO_METHOD_HANDLE  methodHandle,
7194                                              CORINFO_CLASS_HANDLE   classHandle,
7195                                              CORINFO_CONTEXT_HANDLE contextHandle,
7196                                              unsigned               methodAttr,
7197                                              unsigned               classAttr,
7198                                              unsigned               likelihood);
7199
7200     int getGDVMaxTypeChecks()
7201     {
7202         int typeChecks = JitConfig.JitGuardedDevirtualizationMaxTypeChecks();
7203         if (typeChecks < 0)
7204         {
7205             // Negative value means "it's up to JIT to decide"
7206             if (IsTargetAbi(CORINFO_NATIVEAOT_ABI) && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_SIZE_OPT))
7207             {
7208                 return 3;
7209             }
7210
7211             // We plan to use 3 for CoreCLR too, but we need to make sure it doesn't regress performance
7212             // as CoreCLR heavily relies on Dynamic PGO while for NativeAOT we *usually* don't have it and
7213             // can only perform the "exact" devirtualization.
7214             return 1;
7215         }
7216
7217         // MAX_GDV_TYPE_CHECKS is the upper limit. The constant can be changed, we just suspect that even
7218         // 4 type checks is already too much.
7219         return min(MAX_GDV_TYPE_CHECKS, typeChecks);
7220     }
7221
7222     bool doesMethodHaveExpRuntimeLookup()
7223     {
7224         return (optMethodFlags & OMF_HAS_EXPRUNTIMELOOKUP) != 0;
7225     }
7226
7227     void setMethodHasExpRuntimeLookup()
7228     {
7229         optMethodFlags |= OMF_HAS_EXPRUNTIMELOOKUP;
7230     }
7231
7232     bool doesMethodHavePatchpoints()
7233     {
7234         return (optMethodFlags & OMF_HAS_PATCHPOINT) != 0;
7235     }
7236
7237     void setMethodHasPatchpoint()
7238     {
7239         optMethodFlags |= OMF_HAS_PATCHPOINT;
7240     }
7241
7242     bool doesMethodHavePartialCompilationPatchpoints()
7243     {
7244         return (optMethodFlags & OMF_HAS_PARTIAL_COMPILATION_PATCHPOINT) != 0;
7245     }
7246
7247     void setMethodHasPartialCompilationPatchpoint()
7248     {
7249         optMethodFlags |= OMF_HAS_PARTIAL_COMPILATION_PATCHPOINT;
7250     }
7251
7252     unsigned optMethodFlags;
7253
7254     bool doesMethodHaveNoReturnCalls()
7255     {
7256         return optNoReturnCallCount > 0;
7257     }
7258
7259     void setMethodHasNoReturnCalls()
7260     {
7261         optNoReturnCallCount++;
7262     }
7263
7264     unsigned optNoReturnCallCount;
7265
7266     // Recursion bound controls how far we can go backwards tracking for a SSA value.
7267     // No throughput diff was found with backward walk bound between 3-8.
7268     static const int optEarlyPropRecurBound = 5;
7269
7270     enum class optPropKind
7271     {
7272         OPK_INVALID,
7273         OPK_ARRAYLEN,
7274         OPK_NULLCHECK
7275     };
7276
7277     typedef JitHashTable<unsigned, JitSmallPrimitiveKeyFuncs<unsigned>, GenTree*> LocalNumberToNullCheckTreeMap;
7278
7279     GenTree* getArrayLengthFromAllocation(GenTree* tree DEBUGARG(BasicBlock* block));
7280     GenTree* optPropGetValueRec(unsigned lclNum, unsigned ssaNum, optPropKind valueKind, int walkDepth);
7281     GenTree* optPropGetValue(unsigned lclNum, unsigned ssaNum, optPropKind valueKind);
7282     GenTree* optEarlyPropRewriteTree(GenTree* tree, LocalNumberToNullCheckTreeMap* nullCheckMap);
7283     bool optDoEarlyPropForBlock(BasicBlock* block);
7284     bool        optDoEarlyPropForFunc();
7285     PhaseStatus optEarlyProp();
7286     bool optFoldNullCheck(GenTree* tree, LocalNumberToNullCheckTreeMap* nullCheckMap);
7287     GenTree* optFindNullCheckToFold(GenTree* tree, LocalNumberToNullCheckTreeMap* nullCheckMap);
7288     bool optIsNullCheckFoldingLegal(GenTree*    tree,
7289                                     GenTree*    nullCheckTree,
7290                                     GenTree**   nullCheckParent,
7291                                     Statement** nullCheckStmt);
7292     bool optCanMoveNullCheckPastTree(GenTree* tree,
7293                                      unsigned nullCheckLclNum,
7294                                      bool     isInsideTry,
7295                                      bool     checkSideEffectSummary);
7296 #if DEBUG
7297     void optCheckFlagsAreSet(unsigned    methodFlag,
7298                              const char* methodFlagStr,
7299                              unsigned    bbFlag,
7300                              const char* bbFlagStr,
7301                              GenTree*    tree,
7302                              BasicBlock* basicBlock);
7303 #endif
7304
7305     // Redundant branch opts
7306     //
7307     PhaseStatus optRedundantBranches();
7308     bool optRedundantRelop(BasicBlock* const block);
7309     bool optRedundantBranch(BasicBlock* const block);
7310     bool optJumpThreadDom(BasicBlock* const block, BasicBlock* const domBlock, bool domIsSameRelop);
7311     bool optJumpThreadPhi(BasicBlock* const block, GenTree* tree, ValueNum treeNormVN);
7312     bool optJumpThreadCheck(BasicBlock* const block, BasicBlock* const domBlock);
7313     bool optJumpThreadCore(JumpThreadInfo& jti);
7314     bool optReachable(BasicBlock* const fromBlock, BasicBlock* const toBlock, BasicBlock* const excludedBlock);
7315     BitVecTraits* optReachableBitVecTraits;
7316     BitVec        optReachableBitVec;
7317     void optRelopImpliesRelop(RelopImplicationInfo* rii);
7318
7319     /**************************************************************************
7320      *               Value/Assertion propagation
7321      *************************************************************************/
7322 public:
7323     // Data structures for assertion prop
7324     BitVecTraits* apTraits;
7325     ASSERT_TP     apFull;
7326
7327     enum optAssertionKind
7328     {
7329         OAK_INVALID,
7330         OAK_EQUAL,
7331         OAK_NOT_EQUAL,
7332         OAK_SUBRANGE,
7333         OAK_NO_THROW,
7334         OAK_COUNT
7335     };
7336
7337     enum optOp1Kind
7338     {
7339         O1K_INVALID,
7340         O1K_LCLVAR,
7341         O1K_ARR_BND,
7342         O1K_BOUND_OPER_BND,
7343         O1K_BOUND_LOOP_BND,
7344         O1K_CONSTANT_LOOP_BND,
7345         O1K_CONSTANT_LOOP_BND_UN,
7346         O1K_EXACT_TYPE,
7347         O1K_SUBTYPE,
7348         O1K_VALUE_NUMBER,
7349         O1K_COUNT
7350     };
7351
7352     enum optOp2Kind : uint16_t
7353     {
7354         O2K_INVALID,
7355         O2K_LCLVAR_COPY,
7356         O2K_IND_CNS_INT,
7357         O2K_CONST_INT,
7358         O2K_CONST_LONG,
7359         O2K_CONST_DOUBLE,
7360         O2K_ZEROOBJ,
7361         O2K_SUBRANGE,
7362         O2K_COUNT
7363     };
7364
7365     struct AssertionDsc
7366     {
7367         optAssertionKind assertionKind;
7368         struct SsaVar
7369         {
7370             unsigned lclNum; // assigned to or property of this local var number
7371             unsigned ssaNum;
7372         };
7373         struct ArrBnd
7374         {
7375             ValueNum vnIdx;
7376             ValueNum vnLen;
7377         };
7378         struct AssertionDscOp1
7379         {
7380             optOp1Kind kind; // a normal LclVar, or Exact-type or Subtype
7381             ValueNum   vn;
7382             union {
7383                 SsaVar lcl;
7384                 ArrBnd bnd;
7385             };
7386         } op1;
7387         struct AssertionDscOp2
7388         {
7389             optOp2Kind kind; // a const or copy assignment
7390         private:
7391             uint16_t m_encodedIconFlags; // encoded icon gtFlags, don't use directly
7392         public:
7393             ValueNum vn;
7394             struct IntVal
7395             {
7396                 ssize_t iconVal; // integer
7397 #if !defined(HOST_64BIT)
7398                 unsigned padding; // unused; ensures iconFlags does not overlap lconVal
7399 #endif
7400                 FieldSeq* fieldSeq;
7401             };
7402             union {
7403                 SsaVar        lcl;
7404                 IntVal        u1;
7405                 __int64       lconVal;
7406                 double        dconVal;
7407                 IntegralRange u2;
7408             };
7409
7410             bool HasIconFlag()
7411             {
7412                 assert(m_encodedIconFlags <= 0xFF);
7413                 return m_encodedIconFlags != 0;
7414             }
7415             GenTreeFlags GetIconFlag()
7416             {
7417                 // number of trailing zeros in GTF_ICON_HDL_MASK
7418                 const uint16_t iconMaskTzc = 24;
7419                 static_assert_no_msg((0xFF000000 == GTF_ICON_HDL_MASK) && (GTF_ICON_HDL_MASK >> iconMaskTzc) == 0xFF);
7420
7421                 GenTreeFlags flags = (GenTreeFlags)(m_encodedIconFlags << iconMaskTzc);
7422                 assert((flags & ~GTF_ICON_HDL_MASK) == 0);
7423                 return flags;
7424             }
7425             void SetIconFlag(GenTreeFlags flags, FieldSeq* fieldSeq = nullptr)
7426             {
7427                 const uint16_t iconMaskTzc = 24;
7428                 assert((flags & ~GTF_ICON_HDL_MASK) == 0);
7429                 m_encodedIconFlags = flags >> iconMaskTzc;
7430                 u1.fieldSeq        = fieldSeq;
7431             }
7432         } op2;
7433
7434         bool IsCheckedBoundArithBound()
7435         {
7436             return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_BOUND_OPER_BND);
7437         }
7438         bool IsCheckedBoundBound()
7439         {
7440             return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_BOUND_LOOP_BND);
7441         }
7442         bool IsConstantBound()
7443         {
7444             return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) &&
7445                     (op1.kind == O1K_CONSTANT_LOOP_BND));
7446         }
7447         bool IsConstantBoundUnsigned()
7448         {
7449             return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) &&
7450                     (op1.kind == O1K_CONSTANT_LOOP_BND_UN));
7451         }
7452         bool IsBoundsCheckNoThrow()
7453         {
7454             return ((assertionKind == OAK_NO_THROW) && (op1.kind == O1K_ARR_BND));
7455         }
7456
7457         bool IsCopyAssertion()
7458         {
7459             return ((assertionKind == OAK_EQUAL) && (op1.kind == O1K_LCLVAR) && (op2.kind == O2K_LCLVAR_COPY));
7460         }
7461
7462         bool IsConstantInt32Assertion()
7463         {
7464             return ((assertionKind == OAK_EQUAL) || (assertionKind == OAK_NOT_EQUAL)) && (op2.kind == O2K_CONST_INT);
7465         }
7466
7467         bool CanPropLclVar()
7468         {
7469             return assertionKind == OAK_EQUAL && op1.kind == O1K_LCLVAR;
7470         }
7471
7472         bool CanPropEqualOrNotEqual()
7473         {
7474             return assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL;
7475         }
7476
7477         bool CanPropNonNull()
7478         {
7479             return assertionKind == OAK_NOT_EQUAL && op2.vn == ValueNumStore::VNForNull();
7480         }
7481
7482         bool CanPropBndsCheck()
7483         {
7484             return op1.kind == O1K_ARR_BND;
7485         }
7486
7487         bool CanPropSubRange()
7488         {
7489             return assertionKind == OAK_SUBRANGE && op1.kind == O1K_LCLVAR;
7490         }
7491
7492         static bool SameKind(AssertionDsc* a1, AssertionDsc* a2)
7493         {
7494             return a1->assertionKind == a2->assertionKind && a1->op1.kind == a2->op1.kind &&
7495                    a1->op2.kind == a2->op2.kind;
7496         }
7497
7498         static bool ComplementaryKind(optAssertionKind kind, optAssertionKind kind2)
7499         {
7500             if (kind == OAK_EQUAL)
7501             {
7502                 return kind2 == OAK_NOT_EQUAL;
7503             }
7504             else if (kind == OAK_NOT_EQUAL)
7505             {
7506                 return kind2 == OAK_EQUAL;
7507             }
7508             return false;
7509         }
7510
7511         bool HasSameOp1(AssertionDsc* that, bool vnBased)
7512         {
7513             if (op1.kind != that->op1.kind)
7514             {
7515                 return false;
7516             }
7517             else if (op1.kind == O1K_ARR_BND)
7518             {
7519                 assert(vnBased);
7520                 return (op1.bnd.vnIdx == that->op1.bnd.vnIdx) && (op1.bnd.vnLen == that->op1.bnd.vnLen);
7521             }
7522             else
7523             {
7524                 return ((vnBased && (op1.vn == that->op1.vn)) ||
7525                         (!vnBased && (op1.lcl.lclNum == that->op1.lcl.lclNum)));
7526             }
7527         }
7528
7529         bool HasSameOp2(AssertionDsc* that, bool vnBased)
7530         {
7531             if (op2.kind != that->op2.kind)
7532             {
7533                 return false;
7534             }
7535
7536             switch (op2.kind)
7537             {
7538                 case O2K_IND_CNS_INT:
7539                 case O2K_CONST_INT:
7540                     return ((op2.u1.iconVal == that->op2.u1.iconVal) && (op2.GetIconFlag() == that->op2.GetIconFlag()));
7541
7542                 case O2K_CONST_LONG:
7543                     return (op2.lconVal == that->op2.lconVal);
7544
7545                 case O2K_CONST_DOUBLE:
7546                     // exact match because of positive and negative zero.
7547                     return (memcmp(&op2.dconVal, &that->op2.dconVal, sizeof(double)) == 0);
7548
7549                 case O2K_ZEROOBJ:
7550                     return true;
7551
7552                 case O2K_LCLVAR_COPY:
7553                     return (op2.lcl.lclNum == that->op2.lcl.lclNum) &&
7554                            (!vnBased || (op2.lcl.ssaNum == that->op2.lcl.ssaNum));
7555
7556                 case O2K_SUBRANGE:
7557                     return op2.u2.Equals(that->op2.u2);
7558
7559                 case O2K_INVALID:
7560                     // we will return false
7561                     break;
7562
7563                 default:
7564                     assert(!"Unexpected value for op2.kind in AssertionDsc.");
7565                     break;
7566             }
7567
7568             return false;
7569         }
7570
7571         bool Complementary(AssertionDsc* that, bool vnBased)
7572         {
7573             return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that, vnBased) &&
7574                    HasSameOp2(that, vnBased);
7575         }
7576
7577         bool Equals(AssertionDsc* that, bool vnBased)
7578         {
7579             if (assertionKind != that->assertionKind)
7580             {
7581                 return false;
7582             }
7583             else if (assertionKind == OAK_NO_THROW)
7584             {
7585                 assert(op2.kind == O2K_INVALID);
7586                 return HasSameOp1(that, vnBased);
7587             }
7588             else
7589             {
7590                 return HasSameOp1(that, vnBased) && HasSameOp2(that, vnBased);
7591             }
7592         }
7593     };
7594
7595 protected:
7596     static fgWalkPreFn optVNAssertionPropCurStmtVisitor;
7597
7598     bool optLocalAssertionProp;  // indicates that we are performing local assertion prop
7599     bool optAssertionPropagated; // set to true if we modified the trees
7600     bool optAssertionPropagatedCurrentStmt;
7601 #ifdef DEBUG
7602     GenTree* optAssertionPropCurrentTree;
7603 #endif
7604     AssertionIndex*            optComplementaryAssertionMap;
7605     JitExpandArray<ASSERT_TP>* optAssertionDep; // table that holds dependent assertions (assertions
7606                                                 // using the value of a local var) for each local var
7607     AssertionDsc*  optAssertionTabPrivate;      // table that holds info about value assignments
7608     AssertionIndex optAssertionCount;           // total number of assertions in the assertion table
7609     AssertionIndex optMaxAssertionCount;
7610     bool           optCanPropLclVar;
7611     bool           optCanPropEqual;
7612     bool           optCanPropNonNull;
7613     bool           optCanPropBndsChk;
7614     bool           optCanPropSubRange;
7615
7616 public:
7617     void optVnNonNullPropCurStmt(BasicBlock* block, Statement* stmt, GenTree* tree);
7618     fgWalkResult optVNConstantPropCurStmt(BasicBlock* block, Statement* stmt, GenTree* tree);
7619     GenTree* optVNConstantPropOnJTrue(BasicBlock* block, GenTree* test);
7620     GenTree* optVNConstantPropOnTree(BasicBlock* block, GenTree* tree);
7621     GenTree* optExtractSideEffListFromConst(GenTree* tree);
7622
7623     AssertionIndex GetAssertionCount()
7624     {
7625         return optAssertionCount;
7626     }
7627     ASSERT_TP* bbJtrueAssertionOut;
7628     typedef JitHashTable<ValueNum, JitSmallPrimitiveKeyFuncs<ValueNum>, ASSERT_TP> ValueNumToAssertsMap;
7629     ValueNumToAssertsMap* optValueNumToAsserts;
7630
7631     // Assertion prop helpers.
7632     ASSERT_TP& GetAssertionDep(unsigned lclNum);
7633     AssertionDsc* optGetAssertion(AssertionIndex assertIndex);
7634     void optAssertionInit(bool isLocalProp);
7635     void optAssertionTraitsInit(AssertionIndex assertionCount);
7636     void optAssertionReset(AssertionIndex limit);
7637     void optAssertionRemove(AssertionIndex index);
7638
7639     // Assertion prop data flow functions.
7640     PhaseStatus optAssertionPropMain();
7641     Statement* optVNAssertionPropCurStmt(BasicBlock* block, Statement* stmt);
7642     bool optIsTreeKnownIntValue(bool vnBased, GenTree* tree, ssize_t* pConstant, GenTreeFlags* pIconFlags);
7643     ASSERT_TP* optInitAssertionDataflowFlags();
7644     ASSERT_TP* optComputeAssertionGen();
7645
7646     // Assertion Gen functions.
7647     void optAssertionGen(GenTree* tree);
7648     AssertionIndex optAssertionGenCast(GenTreeCast* cast);
7649     AssertionIndex optAssertionGenPhiDefn(GenTree* tree);
7650     AssertionInfo optCreateJTrueBoundsAssertion(GenTree* tree);
7651     AssertionInfo optAssertionGenJtrue(GenTree* tree);
7652     AssertionIndex optCreateJtrueAssertions(GenTree*                   op1,
7653                                             GenTree*                   op2,
7654                                             Compiler::optAssertionKind assertionKind,
7655                                             bool                       helperCallArgs = false);
7656     AssertionIndex optFindComplementary(AssertionIndex assertionIndex);
7657     void optMapComplementary(AssertionIndex assertionIndex, AssertionIndex index);
7658
7659     ValueNum optConservativeNormalVN(GenTree* tree);
7660
7661     ssize_t optCastConstantSmall(ssize_t iconVal, var_types smallType);
7662
7663     // Assertion creation functions.
7664     AssertionIndex optCreateAssertion(GenTree*         op1,
7665                                       GenTree*         op2,
7666                                       optAssertionKind assertionKind,
7667                                       bool             helperCallArgs = false);
7668
7669     AssertionIndex optFinalizeCreatingAssertion(AssertionDsc* assertion);
7670
7671     bool optTryExtractSubrangeAssertion(GenTree* source, IntegralRange* pRange);
7672
7673     void optCreateComplementaryAssertion(AssertionIndex assertionIndex,
7674                                          GenTree*       op1,
7675                                          GenTree*       op2,
7676                                          bool           helperCallArgs = false);
7677
7678     bool optAssertionVnInvolvesNan(AssertionDsc* assertion);
7679     AssertionIndex optAddAssertion(AssertionDsc* assertion);
7680     void optAddVnAssertionMapping(ValueNum vn, AssertionIndex index);
7681 #ifdef DEBUG
7682     void optPrintVnAssertionMapping();
7683 #endif
7684     ASSERT_TP optGetVnMappedAssertions(ValueNum vn);
7685
7686     // Used for respective assertion propagations.
7687     AssertionIndex optAssertionIsSubrange(GenTree* tree, IntegralRange range, ASSERT_VALARG_TP assertions);
7688     AssertionIndex optAssertionIsSubtype(GenTree* tree, GenTree* methodTableArg, ASSERT_VALARG_TP assertions);
7689     AssertionIndex optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased));
7690     bool optAssertionIsNonNull(GenTree*         op,
7691                                ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased) DEBUGARG(AssertionIndex* pIndex));
7692
7693     AssertionIndex optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP assertions, GenTree* op1, GenTree* op2);
7694     AssertionIndex optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_TP assertions, GenTree* op1);
7695     AssertionIndex optLocalAssertionIsEqualOrNotEqual(
7696         optOp1Kind op1Kind, unsigned lclNum, optOp2Kind op2Kind, ssize_t cnsVal, ASSERT_VALARG_TP assertions);
7697
7698     // Assertion prop for lcl var functions.
7699     bool optAssertionProp_LclVarTypeCheck(GenTree* tree, LclVarDsc* lclVarDsc, LclVarDsc* copyVarDsc);
7700     GenTree* optCopyAssertionProp(AssertionDsc*        curAssertion,
7701                                   GenTreeLclVarCommon* tree,
7702                                   Statement* stmt DEBUGARG(AssertionIndex index));
7703     GenTree* optConstantAssertionProp(AssertionDsc*        curAssertion,
7704                                       GenTreeLclVarCommon* tree,
7705                                       Statement* stmt DEBUGARG(AssertionIndex index));
7706     bool optIsProfitableToSubstitute(GenTree* dest, BasicBlock* destBlock, GenTree* value);
7707     bool optZeroObjAssertionProp(GenTree* tree, ASSERT_VALARG_TP assertions);
7708
7709     // Assertion propagation functions.
7710     GenTree* optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt, BasicBlock* block);
7711     GenTree* optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeLclVarCommon* tree, Statement* stmt);
7712     GenTree* optAssertionProp_LclFld(ASSERT_VALARG_TP assertions, GenTreeLclVarCommon* tree, Statement* stmt);
7713     GenTree* optAssertionProp_LocalStore(ASSERT_VALARG_TP assertions, GenTreeLclVarCommon* store, Statement* stmt);
7714     GenTree* optAssertionProp_BlockStore(ASSERT_VALARG_TP assertions, GenTreeBlk* store, Statement* stmt);
7715     GenTree* optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeUnOp* ret, Statement* stmt);
7716     GenTree* optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
7717     GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTreeCast* cast, Statement* stmt);
7718     GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, Statement* stmt);
7719     GenTree* optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
7720     GenTree* optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
7721     GenTree* optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
7722     GenTree* optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
7723     GenTree* optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
7724     GenTree* optAssertionProp_Update(GenTree* newTree, GenTree* tree, Statement* stmt);
7725     GenTree* optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call);
7726     bool optNonNullAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* indir);
7727
7728     // Implied assertion functions.
7729     void optImpliedAssertions(AssertionIndex assertionIndex, ASSERT_TP& activeAssertions);
7730     void optImpliedByTypeOfAssertions(ASSERT_TP& activeAssertions);
7731     void optImpliedByCopyAssertion(AssertionDsc* copyAssertion, AssertionDsc* depAssertion, ASSERT_TP& result);
7732     void optImpliedByConstAssertion(AssertionDsc* curAssertion, ASSERT_TP& result);
7733
7734 #ifdef DEBUG
7735     void optPrintAssertion(AssertionDsc* newAssertion, AssertionIndex assertionIndex = 0);
7736     void optPrintAssertionIndex(AssertionIndex index);
7737     void optPrintAssertionIndices(ASSERT_TP assertions);
7738     void optDebugCheckAssertion(AssertionDsc* assertion);
7739     void optDebugCheckAssertions(AssertionIndex AssertionIndex);
7740 #endif
7741
7742     static void optDumpAssertionIndices(const char* header, ASSERT_TP assertions, const char* footer = nullptr);
7743     static void optDumpAssertionIndices(ASSERT_TP assertions, const char* footer = nullptr);
7744
7745     /**************************************************************************
7746      *                          Range checks
7747      *************************************************************************/
7748
7749 public:
7750     struct LoopCloneVisitorInfo
7751     {
7752         LoopCloneContext* context;
7753         Statement*        stmt;
7754         const unsigned    loopNum;
7755         const bool        cloneForArrayBounds;
7756         const bool        cloneForGDVTests;
7757         LoopCloneVisitorInfo(LoopCloneContext* context,
7758                              unsigned          loopNum,
7759                              Statement*        stmt,
7760                              bool              cloneForArrayBounds,
7761                              bool              cloneForGDVTests)
7762             : context(context)
7763             , stmt(nullptr)
7764             , loopNum(loopNum)
7765             , cloneForArrayBounds(cloneForArrayBounds)
7766             , cloneForGDVTests(cloneForGDVTests)
7767         {
7768         }
7769     };
7770
7771     bool optIsStackLocalInvariant(unsigned loopNum, unsigned lclNum);
7772     bool optExtractArrIndex(GenTree* tree, ArrIndex* result, unsigned lhsNum, bool* topLevelIsFinal);
7773     bool optReconstructArrIndexHelp(GenTree* tree, ArrIndex* result, unsigned lhsNum, bool* topLevelIsFinal);
7774     bool optReconstructArrIndex(GenTree* tree, ArrIndex* result);
7775     bool optIdentifyLoopOptInfo(unsigned loopNum, LoopCloneContext* context);
7776     static fgWalkPreFn optCanOptimizeByLoopCloningVisitor;
7777     fgWalkResult optCanOptimizeByLoopCloning(GenTree* tree, LoopCloneVisitorInfo* info);
7778     bool optObtainLoopCloningOpts(LoopCloneContext* context);
7779     bool optIsLoopClonable(unsigned loopInd);
7780     bool optCheckLoopCloningGDVTestProfitable(GenTreeOp* guard, LoopCloneVisitorInfo* info);
7781     bool optIsHandleOrIndirOfHandle(GenTree* tree, GenTreeFlags handleType);
7782
7783     static bool optLoopCloningEnabled();
7784
7785 #ifdef DEBUG
7786     void optDebugLogLoopCloning(BasicBlock* block, Statement* insertBefore);
7787 #endif
7788     void optPerformStaticOptimizations(unsigned loopNum, LoopCloneContext* context DEBUGARG(bool fastPath));
7789     bool optComputeDerefConditions(unsigned loopNum, LoopCloneContext* context);
7790     bool optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext* context);
7791     BasicBlock* optInsertLoopChoiceConditions(LoopCloneContext* context,
7792                                               unsigned          loopNum,
7793                                               BasicBlock*       slowHead,
7794                                               BasicBlock*       insertAfter);
7795
7796 protected:
7797     ssize_t optGetArrayRefScaleAndIndex(GenTree* mul, GenTree** pIndex DEBUGARG(bool bRngChk));
7798
7799     bool optReachWithoutCall(BasicBlock* srcBB, BasicBlock* dstBB);
7800
7801     /*
7802     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7803     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7804     XX                                                                           XX
7805     XX                           RegAlloc                                        XX
7806     XX                                                                           XX
7807     XX  Does the register allocation and puts the remaining lclVars on the stack XX
7808     XX                                                                           XX
7809     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7810     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7811     */
7812
7813 public:
7814     regNumber raUpdateRegStateForArg(RegState* regState, LclVarDsc* argDsc);
7815
7816     void raMarkStkVars();
7817
7818 #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE
7819 #if defined(TARGET_AMD64)
7820     static bool varTypeNeedsPartialCalleeSave(var_types type)
7821     {
7822         assert(type != TYP_STRUCT);
7823         assert((type < TYP_SIMD32) || (type == TYP_SIMD32) || (type == TYP_SIMD64));
7824         return type >= TYP_SIMD32;
7825     }
7826 #elif defined(TARGET_ARM64)
7827     static bool varTypeNeedsPartialCalleeSave(var_types type)
7828     {
7829         assert(type != TYP_STRUCT);
7830         // ARM64 ABI FP Callee save registers only require Callee to save lower 8 Bytes
7831         // For SIMD types longer than 8 bytes Caller is responsible for saving and restoring Upper bytes.
7832         return ((type == TYP_SIMD16) || (type == TYP_SIMD12));
7833     }
7834 #else // !defined(TARGET_AMD64) && !defined(TARGET_ARM64)
7835 #error("Unknown target architecture for FEATURE_PARTIAL_SIMD_CALLEE_SAVE")
7836 #endif // !defined(TARGET_AMD64) && !defined(TARGET_ARM64)
7837 #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE
7838
7839 protected:
7840     // Some things are used by both LSRA and regpredict allocators.
7841
7842     FrameType rpFrameType;
7843     bool      rpMustCreateEBPCalled; // Set to true after we have called rpMustCreateEBPFrame once
7844
7845     bool rpMustCreateEBPFrame(INDEBUG(const char** wbReason));
7846
7847 private:
7848     Lowering*            m_pLowering;   // Lowering; needed to Lower IR that's added or modified after Lowering.
7849     LinearScanInterface* m_pLinearScan; // Linear Scan allocator
7850
7851     /* raIsVarargsStackArg is called by raMaskStkVars and by
7852        lvaComputeRefCounts.  It identifies the special case
7853        where a varargs function has a parameter passed on the
7854        stack, other than the special varargs handle.  Such parameters
7855        require special treatment, because they cannot be tracked
7856        by the GC (their offsets in the stack are not known
7857        at compile time).
7858     */
7859
7860     bool raIsVarargsStackArg(unsigned lclNum)
7861     {
7862 #ifdef TARGET_X86
7863
7864         LclVarDsc* varDsc = lvaGetDesc(lclNum);
7865
7866         assert(varDsc->lvIsParam);
7867
7868         return (info.compIsVarArgs && !varDsc->lvIsRegArg && (lclNum != lvaVarargsHandleArg));
7869
7870 #else // TARGET_X86
7871
7872         return false;
7873
7874 #endif // TARGET_X86
7875     }
7876
7877     /*
7878     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7879     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7880     XX                                                                           XX
7881     XX                           EEInterface                                     XX
7882     XX                                                                           XX
7883     XX   Get to the class and method info from the Execution Engine given        XX
7884     XX   tokens for the class and method                                         XX
7885     XX                                                                           XX
7886     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7887     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7888     */
7889
7890 public:
7891     // Get handles
7892
7893     void eeGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
7894                        CORINFO_RESOLVED_TOKEN* pConstrainedToken,
7895                        CORINFO_CALLINFO_FLAGS  flags,
7896                        CORINFO_CALL_INFO*      pResult);
7897
7898     void eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
7899                         CORINFO_ACCESS_FLAGS    flags,
7900                         CORINFO_FIELD_INFO*     pResult);
7901
7902     // Get the flags
7903
7904     bool eeIsValueClass(CORINFO_CLASS_HANDLE clsHnd);
7905     bool eeIsIntrinsic(CORINFO_METHOD_HANDLE ftn);
7906     bool eeIsFieldStatic(CORINFO_FIELD_HANDLE fldHnd);
7907
7908     var_types eeGetFieldType(CORINFO_FIELD_HANDLE fldHnd, CORINFO_CLASS_HANDLE* pStructHnd = nullptr);
7909
7910     template <typename TPrint>
7911     void eeAppendPrint(class StringPrinter* printer, TPrint print);
7912     // Conventions: the "base" primitive printing functions take StringPrinter*
7913     // and do not do any SPMI handling. There are then convenience printing
7914     // functions exposed on top that have SPMI handling and additional buffer
7915     // handling. Note that the strings returned are never truncated here.
7916     void eePrintJitType(class StringPrinter* printer, var_types jitType);
7917     void eePrintType(class StringPrinter* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation);
7918     void eePrintTypeOrJitAlias(class StringPrinter* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation);
7919     void eePrintMethod(class StringPrinter*  printer,
7920                        CORINFO_CLASS_HANDLE  clsHnd,
7921                        CORINFO_METHOD_HANDLE methodHnd,
7922                        CORINFO_SIG_INFO*     sig,
7923                        bool                  includeClassInstantiation,
7924                        bool                  includeMethodInstantiation,
7925                        bool                  includeSignature,
7926                        bool                  includeReturnType,
7927                        bool                  includeThisSpecifier);
7928
7929     void eePrintField(class StringPrinter* printer, CORINFO_FIELD_HANDLE fldHnd, bool includeType);
7930
7931     const char* eeGetMethodFullName(CORINFO_METHOD_HANDLE hnd,
7932                                     bool                  includeReturnType    = true,
7933                                     bool                  includeThisSpecifier = true,
7934                                     char*                 buffer               = nullptr,
7935                                     size_t                bufferSize           = 0);
7936
7937     const char* eeGetMethodName(CORINFO_METHOD_HANDLE methHnd, char* buffer = nullptr, size_t bufferSize = 0);
7938
7939     const char* eeGetFieldName(CORINFO_FIELD_HANDLE fldHnd,
7940                                bool                 includeType,
7941                                char*                buffer     = nullptr,
7942                                size_t               bufferSize = 0);
7943
7944     const char* eeGetClassName(CORINFO_CLASS_HANDLE clsHnd, char* buffer = nullptr, size_t bufferSize = 0);
7945
7946     void eePrintObjectDescription(const char* prefix, CORINFO_OBJECT_HANDLE handle);
7947     const char* eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd);
7948
7949 #if defined(DEBUG)
7950     unsigned eeTryGetClassSize(CORINFO_CLASS_HANDLE clsHnd);
7951 #endif
7952
7953     unsigned compMethodHash(CORINFO_METHOD_HANDLE methodHandle);
7954
7955     var_types eeGetArgType(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig);
7956     var_types eeGetArgType(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig, bool* isPinned);
7957     CORINFO_CLASS_HANDLE eeGetArgClass(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE list);
7958     CORINFO_CLASS_HANDLE eeGetClassFromContext(CORINFO_CONTEXT_HANDLE context);
7959     unsigned eeGetArgSize(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig);
7960     static unsigned eeGetArgSizeAlignment(var_types type, bool isFloatHfa);
7961
7962     // VOM info, method sigs
7963
7964     void eeGetSig(unsigned               sigTok,
7965                   CORINFO_MODULE_HANDLE  scope,
7966                   CORINFO_CONTEXT_HANDLE context,
7967                   CORINFO_SIG_INFO*      retSig);
7968
7969     void eeGetCallSiteSig(unsigned               sigTok,
7970                           CORINFO_MODULE_HANDLE  scope,
7971                           CORINFO_CONTEXT_HANDLE context,
7972                           CORINFO_SIG_INFO*      retSig);
7973
7974     void eeGetMethodSig(CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* retSig, CORINFO_CLASS_HANDLE owner = nullptr);
7975
7976     CORINFO_EE_INFO eeInfo;
7977     bool            eeInfoInitialized;
7978
7979     CORINFO_EE_INFO* eeGetEEInfo();
7980
7981     // Gets the offset of a SDArray's first element
7982     static unsigned eeGetArrayDataOffset();
7983
7984     // Get the offset of a MDArray's first element
7985     static unsigned eeGetMDArrayDataOffset(unsigned rank);
7986
7987     // Get the offset of a MDArray's dimension length for a given dimension.
7988     static unsigned eeGetMDArrayLengthOffset(unsigned rank, unsigned dimension);
7989
7990     // Get the offset of a MDArray's lower bound for a given dimension.
7991     static unsigned eeGetMDArrayLowerBoundOffset(unsigned rank, unsigned dimension);
7992
7993     GenTree* eeGetPInvokeCookie(CORINFO_SIG_INFO* szMetaSig);
7994
7995     // Returns the page size for the target machine as reported by the EE.
7996     target_size_t eeGetPageSize()
7997     {
7998         return (target_size_t)eeGetEEInfo()->osPageSize;
7999     }
8000
8001     //------------------------------------------------------------------------
8002     // VirtualStubParam: virtual stub dispatch extra parameter (slot address).
8003     //
8004     // It represents Abi and target specific registers for the parameter.
8005     //
8006     class VirtualStubParamInfo
8007     {
8008     public:
8009         VirtualStubParamInfo(bool isNativeAOT)
8010         {
8011 #if defined(TARGET_X86)
8012             reg     = REG_EAX;
8013             regMask = RBM_EAX;
8014 #elif defined(TARGET_AMD64)
8015             if (isNativeAOT)
8016             {
8017                 reg     = REG_R10;
8018                 regMask = RBM_R10;
8019             }
8020             else
8021             {
8022                 reg     = REG_R11;
8023                 regMask = RBM_R11;
8024             }
8025 #elif defined(TARGET_ARM)
8026             if (isNativeAOT)
8027             {
8028                 reg     = REG_R12;
8029                 regMask = RBM_R12;
8030             }
8031             else
8032             {
8033                 reg     = REG_R4;
8034                 regMask = RBM_R4;
8035             }
8036 #elif defined(TARGET_ARM64)
8037             reg     = REG_R11;
8038             regMask = RBM_R11;
8039 #elif defined(TARGET_LOONGARCH64)
8040             reg     = REG_T8;
8041             regMask = RBM_T8;
8042 #elif defined(TARGET_RISCV64)
8043             reg     = REG_T5;
8044             regMask = RBM_T5;
8045 #else
8046 #error Unsupported or unset target architecture
8047 #endif
8048         }
8049
8050         regNumber GetReg() const
8051         {
8052             return reg;
8053         }
8054
8055         _regMask_enum GetRegMask() const
8056         {
8057             return regMask;
8058         }
8059
8060     private:
8061         regNumber     reg;
8062         _regMask_enum regMask;
8063     };
8064
8065     VirtualStubParamInfo* virtualStubParamInfo;
8066
8067     bool IsTargetAbi(CORINFO_RUNTIME_ABI abi)
8068     {
8069         return eeGetEEInfo()->targetAbi == abi;
8070     }
8071
8072     bool generateCFIUnwindCodes()
8073     {
8074 #if defined(FEATURE_CFI_SUPPORT)
8075         return TargetOS::IsUnix && IsTargetAbi(CORINFO_NATIVEAOT_ABI);
8076 #else
8077         return false;
8078 #endif
8079     }
8080
8081     // Debugging support - Line number info
8082
8083     void eeGetStmtOffsets();
8084
8085     unsigned eeBoundariesCount;
8086
8087     ICorDebugInfo::OffsetMapping* eeBoundaries; // Boundaries to report to the EE
8088     void eeSetLIcount(unsigned count);
8089     void eeSetLIinfo(unsigned which, UNATIVE_OFFSET offs, IPmappingDscKind kind, const ILLocation& loc);
8090     void eeSetLIdone();
8091
8092 #ifdef DEBUG
8093     static void eeDispILOffs(IL_OFFSET offs);
8094     static void eeDispSourceMappingOffs(uint32_t offs);
8095     static void eeDispLineInfo(const ICorDebugInfo::OffsetMapping* line);
8096     void eeDispLineInfos();
8097 #endif // DEBUG
8098
8099     // Debugging support - Local var info
8100
8101     void eeGetVars();
8102
8103     unsigned eeVarsCount;
8104
8105     struct VarResultInfo
8106     {
8107         UNATIVE_OFFSET             startOffset;
8108         UNATIVE_OFFSET             endOffset;
8109         DWORD                      varNumber;
8110         CodeGenInterface::siVarLoc loc;
8111     } * eeVars;
8112     void eeSetLVcount(unsigned count);
8113     void eeSetLVinfo(unsigned                          which,
8114                      UNATIVE_OFFSET                    startOffs,
8115                      UNATIVE_OFFSET                    length,
8116                      unsigned                          varNum,
8117                      const CodeGenInterface::siVarLoc& loc);
8118     void eeSetLVdone();
8119
8120 #ifdef DEBUG
8121     void eeDispVar(ICorDebugInfo::NativeVarInfo* var);
8122     void eeDispVars(CORINFO_METHOD_HANDLE ftn, ULONG32 cVars, ICorDebugInfo::NativeVarInfo* vars);
8123 #endif // DEBUG
8124
8125     // ICorJitInfo wrappers
8126
8127     void eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSectionAlignment);
8128
8129     void eeReserveUnwindInfo(bool isFunclet, bool isColdCode, ULONG unwindSize);
8130
8131     void eeAllocUnwindInfo(BYTE*          pHotCode,
8132                            BYTE*          pColdCode,
8133                            ULONG          startOffset,
8134                            ULONG          endOffset,
8135                            ULONG          unwindSize,
8136                            BYTE*          pUnwindBlock,
8137                            CorJitFuncKind funcKind);
8138
8139     void eeSetEHcount(unsigned cEH);
8140
8141     void eeSetEHinfo(unsigned EHnumber, const CORINFO_EH_CLAUSE* clause);
8142
8143     WORD eeGetRelocTypeHint(void* target);
8144
8145 // ICorStaticInfo wrapper functions
8146
8147 #if defined(UNIX_AMD64_ABI)
8148 #ifdef DEBUG
8149     static void dumpSystemVClassificationType(SystemVClassificationType ct);
8150 #endif // DEBUG
8151
8152     void eeGetSystemVAmd64PassStructInRegisterDescriptor(
8153         /*IN*/ CORINFO_CLASS_HANDLE                                  structHnd,
8154         /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr);
8155 #endif // UNIX_AMD64_ABI
8156
8157     template <typename ParamType>
8158     bool eeRunWithErrorTrap(void (*function)(ParamType*), ParamType* param)
8159     {
8160         return eeRunWithErrorTrapImp(reinterpret_cast<void (*)(void*)>(function), reinterpret_cast<void*>(param));
8161     }
8162
8163     bool eeRunWithErrorTrapImp(void (*function)(void*), void* param);
8164
8165     template <typename ParamType>
8166     bool eeRunWithSPMIErrorTrap(void (*function)(ParamType*), ParamType* param)
8167     {
8168         return eeRunWithSPMIErrorTrapImp(reinterpret_cast<void (*)(void*)>(function), reinterpret_cast<void*>(param));
8169     }
8170
8171     template <typename Functor>
8172     bool eeRunFunctorWithSPMIErrorTrap(Functor f)
8173     {
8174         return eeRunWithSPMIErrorTrap<Functor>([](Functor* pf) { (*pf)(); }, &f);
8175     }
8176
8177     bool eeRunWithSPMIErrorTrapImp(void (*function)(void*), void* param);
8178
8179     // Utility functions
8180
8181     static CORINFO_METHOD_HANDLE eeFindHelper(unsigned helper);
8182     static CorInfoHelpFunc eeGetHelperNum(CORINFO_METHOD_HANDLE method);
8183
8184     enum StaticHelperReturnValue
8185     {
8186         SHRV_STATIC_BASE_PTR,
8187         SHRV_VOID,
8188     };
8189     static bool IsStaticHelperEligibleForExpansion(GenTree*                 tree,
8190                                                    bool*                    isGc       = nullptr,
8191                                                    StaticHelperReturnValue* retValKind = nullptr);
8192     static bool IsSharedStaticHelper(GenTree* tree);
8193     static bool IsGcSafePoint(GenTreeCall* call);
8194
8195     static CORINFO_FIELD_HANDLE eeFindJitDataOffs(unsigned jitDataOffs);
8196     // returns true/false if 'field' is a Jit Data offset
8197     static bool eeIsJitDataOffs(CORINFO_FIELD_HANDLE field);
8198     // returns a number < 0 if 'field' is not a Jit Data offset, otherwise the data offset (limited to 2GB)
8199     static int eeGetJitDataOffs(CORINFO_FIELD_HANDLE field);
8200
8201     /*****************************************************************************/
8202
8203     /*
8204     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8205     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8206     XX                                                                           XX
8207     XX                           CodeGenerator                                   XX
8208     XX                                                                           XX
8209     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8210     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8211     */
8212
8213 public:
8214     CodeGenInterface* codeGen;
8215
8216     // Record the instr offset mapping to the generated code
8217
8218     jitstd::list<IPmappingDsc>  genIPmappings;
8219     jitstd::list<RichIPMapping> genRichIPmappings;
8220
8221     // Managed RetVal - A side hash table meant to record the mapping from a
8222     // GT_CALL node to its debug info.  This info is used to emit sequence points
8223     // that can be used by debugger to determine the native offset at which the
8224     // managed RetVal will be available.
8225     //
8226     // In fact we can store debug info in a GT_CALL node.  This was ruled out in
8227     // favor of a side table for two reasons: 1) We need debug info for only those
8228     // GT_CALL nodes (created during importation) that correspond to an IL call and
8229     // whose return type is other than TYP_VOID. 2) GT_CALL node is a frequently used
8230     // structure and IL offset is needed only when generating debuggable code. Therefore
8231     // it is desirable to avoid memory size penalty in retail scenarios.
8232     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, DebugInfo> CallSiteDebugInfoTable;
8233     CallSiteDebugInfoTable* genCallSite2DebugInfoMap;
8234
8235     unsigned    genReturnLocal; // Local number for the return value when applicable.
8236     BasicBlock* genReturnBB;    // jumped to when not optimizing for speed.
8237
8238     // The following properties are part of CodeGenContext.  Getters are provided here for
8239     // convenience and backward compatibility, but the properties can only be set by invoking
8240     // the setter on CodeGenContext directly.
8241
8242     emitter* GetEmitter() const
8243     {
8244         return codeGen->GetEmitter();
8245     }
8246
8247     bool isFramePointerUsed() const
8248     {
8249         return codeGen->isFramePointerUsed();
8250     }
8251
8252     bool GetInterruptible()
8253     {
8254         return codeGen->GetInterruptible();
8255     }
8256     void SetInterruptible(bool value)
8257     {
8258         codeGen->SetInterruptible(value);
8259     }
8260
8261 #if DOUBLE_ALIGN
8262     const bool genDoubleAlign()
8263     {
8264         return codeGen->doDoubleAlign();
8265     }
8266     DWORD getCanDoubleAlign();
8267     bool shouldDoubleAlign(unsigned refCntStk,
8268                            unsigned refCntReg,
8269                            weight_t refCntWtdReg,
8270                            unsigned refCntStkParam,
8271                            weight_t refCntWtdStkDbl);
8272 #endif // DOUBLE_ALIGN
8273
8274     bool IsFullPtrRegMapRequired()
8275     {
8276         return codeGen->IsFullPtrRegMapRequired();
8277     }
8278     void SetFullPtrRegMapRequired(bool value)
8279     {
8280         codeGen->SetFullPtrRegMapRequired(value);
8281     }
8282
8283 // Things that MAY belong either in CodeGen or CodeGenContext
8284
8285 #if defined(FEATURE_EH_FUNCLETS)
8286     FuncInfoDsc*   compFuncInfos;
8287     unsigned short compCurrFuncIdx;
8288     unsigned short compFuncInfoCount;
8289
8290     unsigned short compFuncCount()
8291     {
8292         assert(fgFuncletsCreated);
8293         return compFuncInfoCount;
8294     }
8295
8296 #else // !FEATURE_EH_FUNCLETS
8297
8298     // This is a no-op when there are no funclets!
8299     void genUpdateCurrentFunclet(BasicBlock* block)
8300     {
8301         return;
8302     }
8303
8304     FuncInfoDsc compFuncInfoRoot;
8305
8306     static const unsigned compCurrFuncIdx = 0;
8307
8308     unsigned short compFuncCount()
8309     {
8310         return 1;
8311     }
8312
8313 #endif // !FEATURE_EH_FUNCLETS
8314
8315     FuncInfoDsc* funCurrentFunc();
8316     void funSetCurrentFunc(unsigned funcIdx);
8317     FuncInfoDsc* funGetFunc(unsigned funcIdx);
8318     unsigned int funGetFuncIdx(BasicBlock* block);
8319
8320     // LIVENESS
8321
8322     VARSET_TP compCurLife;     // current live variables
8323     GenTree*  compCurLifeTree; // node after which compCurLife has been computed
8324
8325     // Compare the given "newLife" with last set of live variables and update
8326     // codeGen "gcInfo", siScopes, "regSet" with the new variable's homes/liveness.
8327     template <bool ForCodeGen>
8328     void compChangeLife(VARSET_VALARG_TP newLife);
8329
8330     // Update the GC's masks, register's masks and reports change on variable's homes given a set of
8331     // current live variables if changes have happened since "compCurLife".
8332     template <bool ForCodeGen>
8333     inline void compUpdateLife(VARSET_VALARG_TP newLife);
8334
8335     // Gets a register mask that represent the kill set for a helper call since
8336     // not all JIT Helper calls follow the standard ABI on the target architecture.
8337     regMaskTP compHelperCallKillSet(CorInfoHelpFunc helper);
8338
8339 /*
8340 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8341 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8342 XX                                                                           XX
8343 XX                           UnwindInfo                                      XX
8344 XX                                                                           XX
8345 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8346 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8347 */
8348
8349 #if !defined(__GNUC__)
8350 #pragma region Unwind information
8351 #endif
8352
8353 public:
8354     //
8355     // Infrastructure functions: start/stop/reserve/emit.
8356     //
8357
8358     void unwindBegProlog();
8359     void unwindEndProlog();
8360     void unwindBegEpilog();
8361     void unwindEndEpilog();
8362     void unwindReserve();
8363     void unwindEmit(void* pHotCode, void* pColdCode);
8364
8365     //
8366     // Specific unwind information functions: called by code generation to indicate a particular
8367     // prolog or epilog unwindable instruction has been generated.
8368     //
8369
8370     void unwindPush(regNumber reg);
8371     void unwindAllocStack(unsigned size);
8372     void unwindSetFrameReg(regNumber reg, unsigned offset);
8373     void unwindSaveReg(regNumber reg, unsigned offset);
8374
8375 #if defined(TARGET_ARM)
8376     void unwindPushMaskInt(regMaskTP mask);
8377     void unwindPushMaskFloat(regMaskTP mask);
8378     void unwindPopMaskInt(regMaskTP mask);
8379     void unwindPopMaskFloat(regMaskTP mask);
8380     void unwindBranch16();                    // The epilog terminates with a 16-bit branch (e.g., "bx lr")
8381     void unwindNop(unsigned codeSizeInBytes); // Generate unwind NOP code. 'codeSizeInBytes' is 2 or 4 bytes. Only
8382                                               // called via unwindPadding().
8383     void unwindPadding(); // Generate a sequence of unwind NOP codes representing instructions between the last
8384                           // instruction and the current location.
8385 #endif                    // TARGET_ARM
8386
8387 #if defined(TARGET_ARM64)
8388     void unwindNop();
8389     void unwindPadding(); // Generate a sequence of unwind NOP codes representing instructions between the last
8390                           // instruction and the current location.
8391     void unwindSaveReg(regNumber reg, int offset);                                // str reg, [sp, #offset]
8392     void unwindSaveRegPreindexed(regNumber reg, int offset);                      // str reg, [sp, #offset]!
8393     void unwindSaveRegPair(regNumber reg1, regNumber reg2, int offset);           // stp reg1, reg2, [sp, #offset]
8394     void unwindSaveRegPairPreindexed(regNumber reg1, regNumber reg2, int offset); // stp reg1, reg2, [sp, #offset]!
8395     void unwindSaveNext();                                                        // unwind code: save_next
8396     void unwindReturn(regNumber reg);                                             // ret lr
8397 #endif                                                                            // defined(TARGET_ARM64)
8398
8399 #if defined(TARGET_LOONGARCH64)
8400     void unwindNop();
8401     void unwindPadding(); // Generate a sequence of unwind NOP codes representing instructions between the last
8402                           // instruction and the current location.
8403     void unwindSaveReg(regNumber reg, int offset);
8404     void unwindSaveRegPair(regNumber reg1, regNumber reg2, int offset);
8405     void unwindReturn(regNumber reg);
8406 #endif // defined(TARGET_LOONGARCH64)
8407
8408 #if defined(TARGET_RISCV64)
8409     void unwindNop();
8410     void unwindPadding(); // Generate a sequence of unwind NOP codes representing instructions between the last
8411                           // instruction and the current location.
8412     void unwindSaveReg(regNumber reg, int offset);
8413     void unwindSaveRegPair(regNumber reg1, regNumber reg2, int offset);
8414     void unwindReturn(regNumber reg);
8415 #endif // defined(TARGET_RISCV64)
8416
8417     //
8418     // Private "helper" functions for the unwind implementation.
8419     //
8420
8421 private:
8422 #if defined(FEATURE_EH_FUNCLETS)
8423     void unwindGetFuncLocations(FuncInfoDsc*             func,
8424                                 bool                     getHotSectionData,
8425                                 /* OUT */ emitLocation** ppStartLoc,
8426                                 /* OUT */ emitLocation** ppEndLoc);
8427 #endif // FEATURE_EH_FUNCLETS
8428
8429     void unwindReserveFunc(FuncInfoDsc* func);
8430     void unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode);
8431
8432 #if defined(TARGET_AMD64) || (defined(TARGET_X86) && defined(FEATURE_EH_FUNCLETS))
8433
8434     void unwindReserveFuncHelper(FuncInfoDsc* func, bool isHotCode);
8435     void unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode);
8436
8437 #endif // TARGET_AMD64 || (TARGET_X86 && FEATURE_EH_FUNCLETS)
8438
8439     UNATIVE_OFFSET unwindGetCurrentOffset(FuncInfoDsc* func);
8440
8441 #if defined(TARGET_AMD64)
8442
8443     void unwindBegPrologWindows();
8444     void unwindPushWindows(regNumber reg);
8445     void unwindAllocStackWindows(unsigned size);
8446     void unwindSetFrameRegWindows(regNumber reg, unsigned offset);
8447     void unwindSaveRegWindows(regNumber reg, unsigned offset);
8448
8449 #ifdef UNIX_AMD64_ABI
8450     void unwindSaveRegCFI(regNumber reg, unsigned offset);
8451 #endif // UNIX_AMD64_ABI
8452 #elif defined(TARGET_ARM)
8453
8454     void unwindPushPopMaskInt(regMaskTP mask, bool useOpsize16);
8455     void unwindPushPopMaskFloat(regMaskTP mask);
8456
8457 #endif // TARGET_ARM
8458
8459 #if defined(FEATURE_CFI_SUPPORT)
8460     short mapRegNumToDwarfReg(regNumber reg);
8461     void createCfiCode(FuncInfoDsc* func, UNATIVE_OFFSET codeOffset, UCHAR opcode, short dwarfReg, INT offset = 0);
8462     void unwindPushPopCFI(regNumber reg);
8463     void unwindBegPrologCFI();
8464     void unwindPushPopMaskCFI(regMaskTP regMask, bool isFloat);
8465     void unwindAllocStackCFI(unsigned size);
8466     void unwindSetFrameRegCFI(regNumber reg, unsigned offset);
8467     void unwindEmitFuncCFI(FuncInfoDsc* func, void* pHotCode, void* pColdCode);
8468 #ifdef DEBUG
8469     void DumpCfiInfo(bool                  isHotCode,
8470                      UNATIVE_OFFSET        startOffset,
8471                      UNATIVE_OFFSET        endOffset,
8472                      DWORD                 cfiCodeBytes,
8473                      const CFI_CODE* const pCfiCode);
8474 #endif
8475
8476 #endif // FEATURE_CFI_SUPPORT
8477
8478 #if !defined(__GNUC__)
8479 #pragma endregion // Note: region is NOT under !defined(__GNUC__)
8480 #endif
8481
8482     /*
8483     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8484     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8485     XX                                                                           XX
8486     XX                               SIMD                                        XX
8487     XX                                                                           XX
8488     XX   Info about SIMD types, methods and the SIMD assembly (i.e. the assembly XX
8489     XX   that contains the distinguished, well-known SIMD type definitions).     XX
8490     XX                                                                           XX
8491     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8492     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8493     */
8494
8495     bool IsBaselineSimdIsaSupported()
8496     {
8497 #ifdef FEATURE_SIMD
8498 #if defined(TARGET_XARCH)
8499         CORINFO_InstructionSet minimumIsa = InstructionSet_SSE2;
8500 #elif defined(TARGET_ARM64)
8501         CORINFO_InstructionSet minimumIsa = InstructionSet_AdvSimd;
8502 #elif defined(TARGET_LOONGARCH64)
8503         // TODO: supporting SIMD feature for LoongArch64.
8504         assert(!"unimplemented yet on LA");
8505         CORINFO_InstructionSet minimumIsa = 0;
8506 #else
8507 #error Unsupported platform
8508 #endif // !TARGET_XARCH && !TARGET_ARM64 && !TARGET_LOONGARCH64
8509
8510         return compOpportunisticallyDependsOn(minimumIsa);
8511 #else
8512         return false;
8513 #endif
8514     }
8515
8516 #if defined(DEBUG)
8517     bool IsBaselineSimdIsaSupportedDebugOnly()
8518     {
8519 #ifdef FEATURE_SIMD
8520 #if defined(TARGET_XARCH)
8521         CORINFO_InstructionSet minimumIsa = InstructionSet_SSE2;
8522 #elif defined(TARGET_ARM64)
8523         CORINFO_InstructionSet minimumIsa = InstructionSet_AdvSimd;
8524 #else
8525 #error Unsupported platform
8526 #endif // !TARGET_XARCH && !TARGET_ARM64
8527
8528         return compIsaSupportedDebugOnly(minimumIsa);
8529 #else
8530         return false;
8531 #endif // FEATURE_SIMD
8532     }
8533 #endif // DEBUG
8534
8535     bool isIntrinsicType(CORINFO_CLASS_HANDLE clsHnd)
8536     {
8537         return info.compCompHnd->isIntrinsicType(clsHnd);
8538     }
8539
8540     const char* getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName)
8541     {
8542         return info.compCompHnd->getClassNameFromMetadata(cls, namespaceName);
8543     }
8544
8545     CORINFO_CLASS_HANDLE getTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index)
8546     {
8547         return info.compCompHnd->getTypeInstantiationArgument(cls, index);
8548     }
8549
8550     bool isNumericsNamespace(const char* ns)
8551     {
8552         return strcmp(ns, "System.Numerics") == 0;
8553     }
8554
8555     bool isRuntimeIntrinsicsNamespace(const char* ns)
8556     {
8557         return strcmp(ns, "System.Runtime.Intrinsics") == 0;
8558     }
8559
8560 #ifdef FEATURE_SIMD
8561     // Have we identified any SIMD types?
8562     // This is currently used by struct promotion to avoid getting type information for a struct
8563     // field to see if it is a SIMD type, if we haven't seen any SIMD types or operations in
8564     // the method.
8565     bool _usesSIMDTypes;
8566     bool usesSIMDTypes()
8567     {
8568         return _usesSIMDTypes;
8569     }
8570     void setUsesSIMDTypes(bool value)
8571     {
8572         _usesSIMDTypes = value;
8573     }
8574
8575     // This is a temp lclVar allocated on the stack as TYP_SIMD.  It is used to implement intrinsics
8576     // that require indexed access to the individual fields of the vector, which is not well supported
8577     // by the hardware.  It is allocated when/if such situations are encountered during Lowering.
8578     unsigned lvaSIMDInitTempVarNum;
8579
8580     struct SIMDHandlesCache
8581     {
8582         CORINFO_CLASS_HANDLE PlaneHandle;
8583         CORINFO_CLASS_HANDLE QuaternionHandle;
8584         CORINFO_CLASS_HANDLE Vector2Handle;
8585         CORINFO_CLASS_HANDLE Vector3Handle;
8586         CORINFO_CLASS_HANDLE Vector4Handle;
8587         CORINFO_CLASS_HANDLE VectorHandle;
8588
8589         SIMDHandlesCache()
8590         {
8591             memset(this, 0, sizeof(*this));
8592         }
8593     };
8594
8595     SIMDHandlesCache* m_simdHandleCache;
8596
8597     // Returns true if this is a SIMD type that should be considered an opaque
8598     // vector type (i.e. do not analyze or promote its fields).
8599     // Note that all but the fixed vector types are opaque, even though they may
8600     // actually be declared as having fields.
8601     bool isOpaqueSIMDType(CORINFO_CLASS_HANDLE structHandle) const
8602     {
8603         // We order the checks roughly by expected hit count so early exits are possible
8604
8605         if (m_simdHandleCache == nullptr)
8606         {
8607             return false;
8608         }
8609
8610         if (structHandle == m_simdHandleCache->Vector4Handle)
8611         {
8612             return false;
8613         }
8614
8615         if (structHandle == m_simdHandleCache->Vector3Handle)
8616         {
8617             return false;
8618         }
8619
8620         if (structHandle == m_simdHandleCache->Vector2Handle)
8621         {
8622             return false;
8623         }
8624
8625         if (structHandle == m_simdHandleCache->QuaternionHandle)
8626         {
8627             return false;
8628         }
8629
8630         if (structHandle == m_simdHandleCache->PlaneHandle)
8631         {
8632             return false;
8633         }
8634
8635         return true;
8636     }
8637
8638     bool isOpaqueSIMDType(ClassLayout* layout) const
8639     {
8640         if (layout->IsBlockLayout())
8641         {
8642             return true;
8643         }
8644
8645         return isOpaqueSIMDType(layout->GetClassHandle());
8646     }
8647
8648     // Returns true if the lclVar is an opaque SIMD type.
8649     bool isOpaqueSIMDLclVar(const LclVarDsc* varDsc) const
8650     {
8651         if (!varTypeIsSIMD(varDsc))
8652         {
8653             return false;
8654         }
8655
8656         if (varDsc->GetLayout() == nullptr)
8657         {
8658             return true;
8659         }
8660
8661         return isOpaqueSIMDType(varDsc->GetLayout());
8662     }
8663
8664     bool isSIMDClass(CORINFO_CLASS_HANDLE clsHnd)
8665     {
8666         if (isIntrinsicType(clsHnd))
8667         {
8668             const char* namespaceName = nullptr;
8669             (void)getClassNameFromMetadata(clsHnd, &namespaceName);
8670             return isNumericsNamespace(namespaceName);
8671         }
8672         return false;
8673     }
8674
8675     bool isHWSIMDClass(CORINFO_CLASS_HANDLE clsHnd)
8676     {
8677 #ifdef FEATURE_HW_INTRINSICS
8678         if (isIntrinsicType(clsHnd))
8679         {
8680             const char* namespaceName = nullptr;
8681             (void)getClassNameFromMetadata(clsHnd, &namespaceName);
8682             return isRuntimeIntrinsicsNamespace(namespaceName);
8683         }
8684 #endif // FEATURE_HW_INTRINSICS
8685         return false;
8686     }
8687
8688     bool isSIMDorHWSIMDClass(CORINFO_CLASS_HANDLE clsHnd)
8689     {
8690         return isSIMDClass(clsHnd) || isHWSIMDClass(clsHnd);
8691     }
8692
8693     // Get the base (element) type and size in bytes for a SIMD type. Returns CORINFO_TYPE_UNDEF
8694     // if it is not a SIMD type or is an unsupported base JIT type.
8695     CorInfoType getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd, unsigned* sizeBytes = nullptr);
8696
8697     CorInfoType getBaseJitTypeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd)
8698     {
8699         return getBaseJitTypeAndSizeOfSIMDType(typeHnd, nullptr);
8700     }
8701
8702     GenTree* impSIMDPopStack();
8703
8704     void setLclRelatedToSIMDIntrinsic(GenTree* tree);
8705     bool areFieldsContiguous(GenTreeIndir* op1, GenTreeIndir* op2);
8706     bool areLocalFieldsContiguous(GenTreeLclFld* first, GenTreeLclFld* second);
8707     bool areArrayElementsContiguous(GenTree* op1, GenTree* op2);
8708     bool areArgumentsContiguous(GenTree* op1, GenTree* op2);
8709     GenTree* CreateAddressNodeForSimdHWIntrinsicCreate(GenTree* tree, var_types simdBaseType, unsigned simdSize);
8710
8711     // Get the size of the SIMD type in bytes
8712     int getSIMDTypeSizeInBytes(CORINFO_CLASS_HANDLE typeHnd)
8713     {
8714         unsigned sizeBytes = 0;
8715         (void)getBaseJitTypeAndSizeOfSIMDType(typeHnd, &sizeBytes);
8716         return sizeBytes;
8717     }
8718
8719     // Get the number of elements of baseType of SIMD vector given by its size and baseType
8720     static int getSIMDVectorLength(unsigned simdSize, var_types baseType);
8721
8722     // Get the number of elements of baseType of SIMD vector given by its type handle
8723     int getSIMDVectorLength(CORINFO_CLASS_HANDLE typeHnd);
8724
8725     // Get preferred alignment of SIMD type.
8726     int getSIMDTypeAlignment(var_types simdType);
8727
8728     // Get the number of bytes in a System.Numeric.Vector<T> for the current compilation.
8729     // Note - cannot be used for System.Runtime.Intrinsic
8730     uint32_t getVectorTByteLength()
8731     {
8732         // We need to report the ISA dependency to the VM so that scenarios
8733         // such as R2R work correctly for larger vector sizes, so we always
8734         // do `compExactlyDependsOn` for such cases.
8735         CLANG_FORMAT_COMMENT_ANCHOR;
8736
8737 #if defined(TARGET_XARCH)
8738         // TODO-XArch: Add support for 512-bit Vector<T>
8739         assert(!compIsaSupportedDebugOnly(InstructionSet_VectorT512));
8740
8741         if (compExactlyDependsOn(InstructionSet_VectorT256))
8742         {
8743             assert(!compIsaSupportedDebugOnly(InstructionSet_VectorT128));
8744             return YMM_REGSIZE_BYTES;
8745         }
8746         else if (compExactlyDependsOn(InstructionSet_VectorT128))
8747         {
8748             return XMM_REGSIZE_BYTES;
8749         }
8750         else
8751         {
8752             // TODO: We should be returning 0 here, but there are a number of
8753             // places that don't quite get handled correctly in that scenario
8754
8755             return XMM_REGSIZE_BYTES;
8756         }
8757 #elif defined(TARGET_ARM64)
8758         if (compExactlyDependsOn(InstructionSet_VectorT128))
8759         {
8760             return FP_REGSIZE_BYTES;
8761         }
8762         else
8763         {
8764             // TODO: We should be returning 0 here, but there are a number of
8765             // places that don't quite get handled correctly in that scenario
8766
8767             return FP_REGSIZE_BYTES;
8768         }
8769 #else
8770         assert(!"getVectorTByteLength() unimplemented on target arch");
8771         unreached();
8772 #endif
8773     }
8774
8775     // The minimum and maximum possible number of bytes in a SIMD vector.
8776
8777     // getMaxVectorByteLength
8778     // The minimum SIMD size supported by System.Numeric.Vectors or System.Runtime.Intrinsic
8779     // Arm.AdvSimd:  16-byte Vector<T> and Vector128<T>
8780     // X86.SSE:      16-byte Vector<T> and Vector128<T>
8781     // X86.AVX:      16-byte Vector<T> and Vector256<T>
8782     // X86.AVX2:     32-byte Vector<T> and Vector256<T>
8783     // X86.AVX512F:  32-byte Vector<T> and Vector512<T>
8784     uint32_t getMaxVectorByteLength() const
8785     {
8786 #if defined(FEATURE_HW_INTRINSICS) && defined(TARGET_XARCH)
8787         if (compOpportunisticallyDependsOn(InstructionSet_AVX512F))
8788         {
8789             return ZMM_REGSIZE_BYTES;
8790         }
8791         else if (compOpportunisticallyDependsOn(InstructionSet_AVX))
8792         {
8793             return YMM_REGSIZE_BYTES;
8794         }
8795         else if (compOpportunisticallyDependsOn(InstructionSet_SSE))
8796         {
8797             return XMM_REGSIZE_BYTES;
8798         }
8799         else
8800         {
8801             // TODO: We should be returning 0 here, but there are a number of
8802             // places that don't quite get handled correctly in that scenario
8803
8804             return XMM_REGSIZE_BYTES;
8805         }
8806 #elif defined(TARGET_ARM64)
8807         if (compOpportunisticallyDependsOn(InstructionSet_AdvSimd))
8808         {
8809             return FP_REGSIZE_BYTES;
8810         }
8811         else
8812         {
8813             // TODO: We should be returning 0 here, but there are a number of
8814             // places that don't quite get handled correctly in that scenario
8815
8816             return FP_REGSIZE_BYTES;
8817         }
8818 #else
8819         assert(!"getMaxVectorByteLength() unimplemented on target arch");
8820         unreached();
8821 #endif
8822     }
8823
8824     //------------------------------------------------------------------------
8825     // getPreferredVectorByteLength: Gets the preferred length, in bytes, to use for vectorization
8826     //
8827     uint32_t getPreferredVectorByteLength() const
8828     {
8829 #if defined(FEATURE_HW_INTRINSICS) && defined(TARGET_XARCH)
8830         uint32_t preferredVectorByteLength = opts.preferredVectorByteLength;
8831
8832         if (preferredVectorByteLength != 0)
8833         {
8834             return min(getMaxVectorByteLength(), preferredVectorByteLength);
8835         }
8836 #endif // FEATURE_HW_INTRINSICS && TARGET_XARCH
8837
8838         return getMaxVectorByteLength();
8839     }
8840
8841     //------------------------------------------------------------------------
8842     // roundUpSIMDSize: rounds the given size up to the nearest SIMD size
8843     //                  available on the target. Examples on XARCH:
8844     //
8845     //    size: 7 -> XMM
8846     //    size: 30 -> YMM (or XMM if target doesn't support AVX)
8847     //    size: 70 -> ZMM (or YMM or XMM depending on target)
8848     //
8849     // Arguments:
8850     //    size   - size of the data to process with SIMD
8851     //
8852     // Notes:
8853     //    It's only supposed to be used for scenarios where we can
8854     //    perform an overlapped load/store.
8855     //
8856     uint32_t roundUpSIMDSize(unsigned size)
8857     {
8858 #if defined(FEATURE_HW_INTRINSICS) && defined(TARGET_XARCH)
8859         uint32_t maxSize = getPreferredVectorByteLength();
8860         assert(maxSize <= ZMM_REGSIZE_BYTES);
8861
8862         if ((size <= XMM_REGSIZE_BYTES) && (maxSize > XMM_REGSIZE_BYTES))
8863         {
8864             return XMM_REGSIZE_BYTES;
8865         }
8866
8867         if ((size <= YMM_REGSIZE_BYTES) && (maxSize > YMM_REGSIZE_BYTES))
8868         {
8869             return YMM_REGSIZE_BYTES;
8870         }
8871
8872         return maxSize;
8873 #elif defined(TARGET_ARM64)
8874         assert(getMaxVectorByteLength() == FP_REGSIZE_BYTES);
8875         return FP_REGSIZE_BYTES;
8876 #else
8877         assert(!"roundUpSIMDSize() unimplemented on target arch");
8878         unreached();
8879 #endif
8880     }
8881
8882     //------------------------------------------------------------------------
8883     // roundDownSIMDSize: rounds the given size down to the nearest SIMD size
8884     //                    available on the target. Examples on XARCH:
8885     //
8886     //    size: 7 -> 0
8887     //    size: 30 -> XMM (not enough for AVX)
8888     //    size: 60 -> YMM (or XMM if target doesn't support AVX)
8889     //    size: 70 -> ZMM/YMM/XMM whatever the current system can offer
8890     //
8891     // Arguments:
8892     //    size   - size of the data to process with SIMD
8893     //
8894     uint32_t roundDownSIMDSize(unsigned size)
8895     {
8896 #if defined(FEATURE_HW_INTRINSICS) && defined(TARGET_XARCH)
8897         uint32_t maxSize = getPreferredVectorByteLength();
8898         assert(maxSize <= ZMM_REGSIZE_BYTES);
8899
8900         if (size >= maxSize)
8901         {
8902             // Size is bigger than max SIMD size the current target supports
8903             return maxSize;
8904         }
8905
8906         if ((size >= YMM_REGSIZE_BYTES) && (maxSize >= YMM_REGSIZE_BYTES))
8907         {
8908             // Size is >= YMM but not enough for ZMM -> YMM
8909             return YMM_REGSIZE_BYTES;
8910         }
8911
8912         // Return 0 if size is even less than XMM, otherwise - XMM
8913         return (size >= XMM_REGSIZE_BYTES) ? XMM_REGSIZE_BYTES : 0;
8914 #elif defined(TARGET_ARM64)
8915         assert(getMaxVectorByteLength() == FP_REGSIZE_BYTES);
8916         return (size >= FP_REGSIZE_BYTES) ? FP_REGSIZE_BYTES : 0;
8917 #else
8918         assert(!"roundDownSIMDSize() unimplemented on target arch");
8919         unreached();
8920 #endif
8921     }
8922
8923     uint32_t getMinVectorByteLength()
8924     {
8925         return emitTypeSize(TYP_SIMD8);
8926     }
8927
8928 public:
8929     // Returns the codegen type for a given SIMD size.
8930     static var_types getSIMDTypeForSize(unsigned size)
8931     {
8932         var_types simdType = TYP_UNDEF;
8933         if (size == 8)
8934         {
8935             simdType = TYP_SIMD8;
8936         }
8937         else if (size == 12)
8938         {
8939             simdType = TYP_SIMD12;
8940         }
8941         else if (size == 16)
8942         {
8943             simdType = TYP_SIMD16;
8944         }
8945 #if defined(TARGET_XARCH)
8946         else if (size == 32)
8947         {
8948             simdType = TYP_SIMD32;
8949         }
8950         else if (size == 64)
8951         {
8952             simdType = TYP_SIMD64;
8953         }
8954 #endif // TARGET_XARCH
8955         else
8956         {
8957             noway_assert(!"Unexpected size for SIMD type");
8958         }
8959         return simdType;
8960     }
8961
8962 private:
8963     unsigned getSIMDInitTempVarNum(var_types simdType);
8964
8965 #else  // !FEATURE_SIMD
8966     bool isOpaqueSIMDLclVar(LclVarDsc* varDsc)
8967     {
8968         return false;
8969     }
8970     unsigned int roundUpSIMDSize(unsigned size)
8971     {
8972         return 0;
8973     }
8974     unsigned int roundDownSIMDSize(unsigned size)
8975     {
8976         return 0;
8977     }
8978 #endif // FEATURE_SIMD
8979
8980 public:
8981     // Similar to roundUpSIMDSize, but for General Purpose Registers (GPR)
8982     unsigned roundUpGPRSize(unsigned size)
8983     {
8984         if (size > 4 && (REGSIZE_BYTES == 8))
8985         {
8986             return 8;
8987         }
8988         else if (size > 2)
8989         {
8990             return 4;
8991         }
8992         return size; // 2, 1, 0
8993     }
8994
8995     var_types roundDownMaxType(unsigned size)
8996     {
8997         assert(size > 0);
8998         var_types result = TYP_UNDEF;
8999 #ifdef FEATURE_SIMD
9000         if (IsBaselineSimdIsaSupported() && (roundDownSIMDSize(size) > 0))
9001         {
9002             return getSIMDTypeForSize(roundDownSIMDSize(size));
9003         }
9004 #endif
9005         int nearestPow2 = 1 << BitOperations::Log2((unsigned)size);
9006         switch (min(nearestPow2, REGSIZE_BYTES))
9007         {
9008             case 1:
9009                 return TYP_UBYTE;
9010             case 2:
9011                 return TYP_USHORT;
9012             case 4:
9013                 return TYP_INT;
9014             case 8:
9015                 assert(REGSIZE_BYTES == 8);
9016                 return TYP_LONG;
9017             default:
9018                 unreached();
9019         }
9020     }
9021
9022     enum UnrollKind
9023     {
9024         Memset,
9025         Memcpy,
9026         Memmove
9027     };
9028
9029     //------------------------------------------------------------------------
9030     // getUnrollThreshold: Calculates the unrolling threshold for the given operation
9031     //
9032     // Arguments:
9033     //    type       - kind of the operation (memset/memcpy)
9034     //    canUseSimd - whether it is allowed to use SIMD or not
9035     //
9036     // Return Value:
9037     //    The unrolling threshold for the given operation in bytes
9038     //
9039     unsigned int getUnrollThreshold(UnrollKind type, bool canUseSimd = true)
9040     {
9041         unsigned maxRegSize = REGSIZE_BYTES;
9042         unsigned threshold  = maxRegSize;
9043
9044 #if defined(FEATURE_SIMD)
9045         if (canUseSimd)
9046         {
9047             maxRegSize = getPreferredVectorByteLength();
9048
9049 #if defined(TARGET_XARCH)
9050             assert(maxRegSize <= ZMM_REGSIZE_BYTES);
9051             threshold = maxRegSize;
9052 #elif defined(TARGET_ARM64)
9053             // ldp/stp instructions can load/store two 16-byte vectors at once, e.g.:
9054             //
9055             //   ldp q0, q1, [x1]
9056             //   stp q0, q1, [x0]
9057             //
9058             threshold = maxRegSize * 2;
9059 #endif
9060         }
9061 #if defined(TARGET_XARCH)
9062         else
9063         {
9064             // Compatibility with previous logic: we used to allow memset:128/memcpy:64
9065             // on AMD64 (and 64/32 on x86) for cases where we don't use SIMD
9066             // see https://github.com/dotnet/runtime/issues/83297
9067             threshold *= 2;
9068         }
9069 #endif
9070 #endif
9071
9072         if (type == UnrollKind::Memset)
9073         {
9074             // Typically, memset-like operations require less instructions than memcpy
9075             threshold *= 2;
9076         }
9077
9078         // Use 4 as a multiplier by default, thus, the final threshold will be:
9079         //
9080         // | arch        | memset | memcpy |
9081         // |-------------|--------|--------|
9082         // | x86 avx512  |   512  |   256  |
9083         // | x86 avx     |   256  |   128  |
9084         // | x86 sse     |   128  |    64  |
9085         // | arm64       |   256  |   128  | ldp/stp (2x128bit)
9086         // | arm         |    32  |    16  | no SIMD support
9087         // | loongarch64 |    64  |    32  | no SIMD support
9088         // | riscv64     |    64  |    32  | no SIMD support
9089         //
9090         // We might want to use a different multiplier for truly hot/cold blocks based on PGO data
9091         //
9092         threshold *= 4;
9093
9094         if (type == UnrollKind::Memmove)
9095         {
9096             // NOTE: Memmove's unrolling is currently limited with LSRA -
9097             // up to LinearScan::MaxInternalCount number of temp regs, e.g. 5*16=80 bytes on arm64
9098             threshold = maxRegSize * 4;
9099         }
9100
9101         return threshold;
9102     }
9103
9104     // Use to determine if a struct *might* be a SIMD type. As this function only takes a size, many
9105     // structs will fit the criteria.
9106     bool structSizeMightRepresentSIMDType(size_t structSize)
9107     {
9108 #ifdef FEATURE_SIMD
9109         return (structSize >= getMinVectorByteLength()) && (structSize <= getMaxVectorByteLength());
9110 #else
9111         return false;
9112 #endif // FEATURE_SIMD
9113     }
9114
9115 #ifdef FEATURE_HW_INTRINSICS
9116     static bool vnEncodesResultTypeForHWIntrinsic(NamedIntrinsic hwIntrinsicID);
9117 #endif // FEATURE_HW_INTRINSICS
9118
9119 private:
9120     // Returns true if the TYP_SIMD locals on stack are aligned at their
9121     // preferred byte boundary specified by getSIMDTypeAlignment().
9122     //
9123     // As per the Intel manual, the preferred alignment for AVX vectors is
9124     // 32-bytes. It is not clear whether additional stack space used in
9125     // aligning stack is worth the benefit and for now will use 16-byte
9126     // alignment for AVX 256-bit vectors with unaligned load/stores to/from
9127     // memory. On x86, the stack frame is aligned to 4 bytes. We need to extend
9128     // existing support for double (8-byte) alignment to 16 or 32 byte
9129     // alignment for frames with local SIMD vars, if that is determined to be
9130     // profitable.
9131     //
9132     // On Amd64 and SysV, RSP+8 is aligned on entry to the function (before
9133     // prolog has run). This means that in RBP-based frames RBP will be 16-byte
9134     // aligned. For RSP-based frames these are only sometimes aligned, depending
9135     // on the frame size.
9136     //
9137     bool isSIMDTypeLocalAligned(unsigned varNum)
9138     {
9139 #if defined(FEATURE_SIMD) && ALIGN_SIMD_TYPES
9140         LclVarDsc* lcl = lvaGetDesc(varNum);
9141         if (varTypeIsSIMD(lcl))
9142         {
9143             // TODO-Cleanup: Can't this use the lvExactSize on the varDsc?
9144             int alignment = getSIMDTypeAlignment(lcl->TypeGet());
9145             if (alignment <= STACK_ALIGN)
9146             {
9147                 bool rbpBased;
9148                 int  off = lvaFrameAddress(varNum, &rbpBased);
9149                 // On SysV and Winx64 ABIs RSP+8 will be 16-byte aligned at the
9150                 // first instruction of a function. If our frame is RBP based
9151                 // then RBP will always be 16 bytes aligned, so we can simply
9152                 // check the offset.
9153                 if (rbpBased)
9154                 {
9155                     return (off % alignment) == 0;
9156                 }
9157
9158                 // For RSP-based frame the alignment of RSP depends on our
9159                 // locals. rsp+8 is aligned on entry and we just subtract frame
9160                 // size so it is not hard to compute. Note that the compiler
9161                 // tries hard to make sure the frame size means RSP will be
9162                 // 16-byte aligned, but for leaf functions without locals (i.e.
9163                 // frameSize = 0) it will not be.
9164                 int frameSize = codeGen->genTotalFrameSize();
9165                 return ((8 - frameSize + off) % alignment) == 0;
9166             }
9167         }
9168 #endif // FEATURE_SIMD
9169
9170         return false;
9171     }
9172
9173 #ifdef DEBUG
9174     // Answer the question: Is a particular ISA supported?
9175     // Use this api when asking the question so that future
9176     // ISA questions can be asked correctly or when asserting
9177     // support/nonsupport for an instruction set
9178     bool compIsaSupportedDebugOnly(CORINFO_InstructionSet isa) const
9179     {
9180 #if defined(TARGET_XARCH) || defined(TARGET_ARM64)
9181         return opts.compSupportsISA.HasInstructionSet(isa);
9182 #else
9183         return false;
9184 #endif
9185     }
9186 #endif // DEBUG
9187
9188     bool notifyInstructionSetUsage(CORINFO_InstructionSet isa, bool supported) const;
9189
9190     // Answer the question: Is a particular ISA allowed to be used implicitly by optimizations?
9191     // The result of this api call will exactly match the target machine
9192     // on which the function is executed (except for CoreLib, where there are special rules)
9193     bool compExactlyDependsOn(CORINFO_InstructionSet isa) const
9194     {
9195 #if defined(TARGET_XARCH) || defined(TARGET_ARM64)
9196         if ((opts.compSupportsISAReported.HasInstructionSet(isa)) == false)
9197         {
9198             if (notifyInstructionSetUsage(isa, (opts.compSupportsISA.HasInstructionSet(isa))))
9199                 ((Compiler*)this)->opts.compSupportsISAExactly.AddInstructionSet(isa);
9200             ((Compiler*)this)->opts.compSupportsISAReported.AddInstructionSet(isa);
9201         }
9202         return (opts.compSupportsISAExactly.HasInstructionSet(isa));
9203 #else
9204         return false;
9205 #endif
9206     }
9207
9208     // Answer the question: Is a particular ISA allowed to be used implicitly by optimizations?
9209     // The result of this api call will match the target machine if the result is true.
9210     // If the result is false, then the target machine may have support for the instruction.
9211     bool compOpportunisticallyDependsOn(CORINFO_InstructionSet isa) const
9212     {
9213         if (opts.compSupportsISA.HasInstructionSet(isa))
9214         {
9215             return compExactlyDependsOn(isa);
9216         }
9217         else
9218         {
9219             return false;
9220         }
9221     }
9222
9223     // Answer the question: Is a particular ISA supported for explicit hardware intrinsics?
9224     bool compHWIntrinsicDependsOn(CORINFO_InstructionSet isa) const
9225     {
9226         // Report intent to use the ISA to the EE
9227         compExactlyDependsOn(isa);
9228         return opts.compSupportsISA.HasInstructionSet(isa);
9229     }
9230
9231 #ifdef DEBUG
9232     //------------------------------------------------------------------------
9233     // IsBaselineVector512IsaSupportedDebugOnly - Does isa support exist for Vector512.
9234     //
9235     // Returns:
9236     //    `true` if AVX512F, AVX512BW, AVX512CD, AVX512DQ, and AVX512VL are supported.
9237     //
9238     bool IsBaselineVector512IsaSupportedDebugOnly() const
9239     {
9240 #ifdef TARGET_XARCH
9241         return compIsaSupportedDebugOnly(InstructionSet_AVX512F);
9242 #else
9243         return false;
9244 #endif
9245     }
9246 #endif // DEBUG
9247
9248     //------------------------------------------------------------------------
9249     // IsBaselineVector512IsaSupportedOpportunistically - Does opportunistic isa support exist for Vector512.
9250     //
9251     // Returns:
9252     //    `true` if AVX512F, AVX512BW, AVX512CD, AVX512DQ, and AVX512VL are supported.
9253     //
9254     bool IsBaselineVector512IsaSupportedOpportunistically() const
9255     {
9256 #ifdef TARGET_XARCH
9257         return compOpportunisticallyDependsOn(InstructionSet_AVX512F);
9258 #else
9259         return false;
9260 #endif
9261     }
9262
9263 #ifdef TARGET_XARCH
9264     bool canUseVexEncoding() const
9265     {
9266         return compOpportunisticallyDependsOn(InstructionSet_AVX);
9267     }
9268
9269     //------------------------------------------------------------------------
9270     // canUseEvexEncoding - Answer the question: Is Evex encoding supported on this target.
9271     //
9272     // Returns:
9273     //    `true` if Evex encoding is supported, `false` if not.
9274     //
9275     bool canUseEvexEncoding() const
9276     {
9277         return compOpportunisticallyDependsOn(InstructionSet_AVX512F);
9278     }
9279
9280     //------------------------------------------------------------------------
9281     // DoJitStressEvexEncoding- Answer the question: Do we force EVEX encoding.
9282     //
9283     // Returns:
9284     //    `true` if user requests EVEX encoding and it's safe, `false` if not.
9285     //
9286     bool DoJitStressEvexEncoding() const
9287     {
9288 #ifdef DEBUG
9289         // Using JitStressEVEXEncoding flag will force instructions which would
9290         // otherwise use VEX encoding but can be EVEX encoded to use EVEX encoding
9291         // This requires AVX512F, AVX512BW, AVX512CD, AVX512DQ, and AVX512VL support
9292
9293         if (JitConfig.JitStressEvexEncoding() && IsBaselineVector512IsaSupportedOpportunistically())
9294         {
9295             assert(compIsaSupportedDebugOnly(InstructionSet_AVX512F));
9296             assert(compIsaSupportedDebugOnly(InstructionSet_AVX512F_VL));
9297             assert(compIsaSupportedDebugOnly(InstructionSet_AVX512BW));
9298             assert(compIsaSupportedDebugOnly(InstructionSet_AVX512BW_VL));
9299             assert(compIsaSupportedDebugOnly(InstructionSet_AVX512CD));
9300             assert(compIsaSupportedDebugOnly(InstructionSet_AVX512CD_VL));
9301             assert(compIsaSupportedDebugOnly(InstructionSet_AVX512DQ));
9302             assert(compIsaSupportedDebugOnly(InstructionSet_AVX512DQ_VL));
9303
9304             return true;
9305         }
9306 #endif // DEBUG
9307
9308         return false;
9309     }
9310 #endif // TARGET_XARCH
9311
9312     /*
9313     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9314     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9315     XX                                                                           XX
9316     XX                           Compiler                                        XX
9317     XX                                                                           XX
9318     XX   Generic info about the compilation and the method being compiled.       XX
9319     XX   It is responsible for driving the other phases.                         XX
9320     XX   It is also responsible for all the memory management.                   XX
9321     XX                                                                           XX
9322     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9323     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9324     */
9325
9326 public:
9327     Compiler* InlineeCompiler; // The Compiler instance for the inlinee
9328
9329     InlineResult* compInlineResult; // The result of importing the inlinee method.
9330
9331     bool compDoAggressiveInlining;     // If true, mark every method as CORINFO_FLG_FORCEINLINE
9332     bool compJmpOpUsed;                // Does the method do a JMP
9333     bool compLongUsed;                 // Does the method use TYP_LONG
9334     bool compFloatingPointUsed;        // Does the method use TYP_FLOAT or TYP_DOUBLE
9335     bool compTailCallUsed;             // Does the method do a tailcall
9336     bool compTailPrefixSeen;           // Does the method IL have tail. prefix
9337     bool compMayConvertTailCallToLoop; // Does the method have a recursive tail call that we may convert to a loop?
9338     bool compLocallocSeen;             // Does the method IL have localloc opcode
9339     bool compLocallocUsed;             // Does the method use localloc.
9340     bool compLocallocOptimized;        // Does the method have an optimized localloc
9341     bool compQmarkUsed;                // Does the method use GT_QMARK/GT_COLON
9342     bool compQmarkRationalized;        // Is it allowed to use a GT_QMARK/GT_COLON node.
9343     bool compHasBackwardJump;          // Does the method (or some inlinee) have a lexically backwards jump?
9344     bool compHasBackwardJumpInHandler; // Does the method have a lexically backwards jump in a handler?
9345     bool compSwitchedToOptimized;      // Codegen initially was Tier0 but jit switched to FullOpts
9346     bool compSwitchedToMinOpts;        // Codegen initially was Tier1/FullOpts but jit switched to MinOpts
9347     bool compSuppressedZeroInit;       // There are vars with lvSuppressedZeroInit set
9348
9349 // NOTE: These values are only reliable after
9350 //       the importing is completely finished.
9351
9352 #ifdef DEBUG
9353     // State information - which phases have completed?
9354     // These are kept together for easy discoverability
9355
9356     bool    bRangeAllowStress;
9357     bool    compCodeGenDone;
9358     int64_t compNumStatementLinksTraversed; // # of links traversed while doing debug checks
9359     bool    fgNormalizeEHDone;              // Has the flowgraph EH normalization phase been done?
9360     size_t  compSizeEstimate;               // The estimated size of the method as per `gtSetEvalOrder`.
9361     size_t  compCycleEstimate;              // The estimated cycle count of the method as per `gtSetEvalOrder`
9362     bool    compPoisoningAnyImplicitByrefs; // Importer inserted IR before returns to poison implicit byrefs
9363
9364 #endif // DEBUG
9365
9366     bool fgLocalVarLivenessDone; // Note that this one is used outside of debug.
9367     bool fgLocalVarLivenessChanged;
9368     bool fgIsDoingEarlyLiveness;
9369     bool fgDidEarlyLiveness;
9370     bool compPostImportationCleanupDone;
9371     bool compLSRADone;
9372     bool compRationalIRForm;
9373
9374     bool compUsesThrowHelper; // There is a call to a THROW_HELPER for the compiled method.
9375
9376     bool compGeneratingProlog;
9377     bool compGeneratingEpilog;
9378     bool compGeneratingUnwindProlog;
9379     bool compGeneratingUnwindEpilog;
9380     bool compNeedsGSSecurityCookie; // There is an unsafe buffer (or localloc) on the stack.
9381                                     // Insert cookie on frame and code to check the cookie, like VC++ -GS.
9382     bool compGSReorderStackLayout;  // There is an unsafe buffer on the stack, reorder locals and make local
9383     // copies of susceptible parameters to avoid buffer overrun attacks through locals/params
9384     bool getNeedsGSSecurityCookie() const
9385     {
9386         return compNeedsGSSecurityCookie;
9387     }
9388     void setNeedsGSSecurityCookie()
9389     {
9390         compNeedsGSSecurityCookie = true;
9391     }
9392
9393     FrameLayoutState lvaDoneFrameLayout; // The highest frame layout state that we've completed. During
9394                                          // frame layout calculations, this is the level we are currently
9395                                          // computing.
9396
9397     //---------------------------- JITing options -----------------------------
9398
9399     enum codeOptimize
9400     {
9401         BLENDED_CODE,
9402         SMALL_CODE,
9403         FAST_CODE,
9404
9405         COUNT_OPT_CODE
9406     };
9407
9408     struct Options
9409     {
9410         JitFlags* jitFlags; // all flags passed from the EE
9411
9412         // The instruction sets that the compiler is allowed to emit.
9413         CORINFO_InstructionSetFlags compSupportsISA;
9414         // The instruction sets that were reported to the VM as being used by the current method. Subset of
9415         // compSupportsISA.
9416         CORINFO_InstructionSetFlags compSupportsISAReported;
9417         // The instruction sets that the compiler is allowed to take advantage of implicitly during optimizations.
9418         // Subset of compSupportsISA.
9419         // The instruction sets available in compSupportsISA and not available in compSupportsISAExactly can be only
9420         // used via explicit hardware intrinsics.
9421         CORINFO_InstructionSetFlags compSupportsISAExactly;
9422
9423         void setSupportedISAs(CORINFO_InstructionSetFlags isas)
9424         {
9425             compSupportsISA = isas;
9426         }
9427
9428         unsigned compFlags; // method attributes
9429         unsigned instrCount;
9430         unsigned lvRefCount;
9431
9432         codeOptimize compCodeOpt; // what type of code optimizations
9433
9434 #if defined(TARGET_XARCH)
9435         uint32_t preferredVectorByteLength;
9436 #endif // TARGET_XARCH
9437
9438 // optimize maximally and/or favor speed over size?
9439
9440 #define DEFAULT_MIN_OPTS_CODE_SIZE 60000
9441 #define DEFAULT_MIN_OPTS_INSTR_COUNT 20000
9442 #define DEFAULT_MIN_OPTS_BB_COUNT 2000
9443 #define DEFAULT_MIN_OPTS_LV_NUM_COUNT 2000
9444 #define DEFAULT_MIN_OPTS_LV_REF_COUNT 8000
9445
9446 // Maximum number of locals before turning off the inlining
9447 #define MAX_LV_NUM_COUNT_FOR_INLINING 512
9448
9449         bool compMinOpts;
9450         bool compMinOptsIsSet;
9451 #ifdef DEBUG
9452         mutable bool compMinOptsIsUsed;
9453
9454         bool MinOpts() const
9455         {
9456             assert(compMinOptsIsSet);
9457             compMinOptsIsUsed = true;
9458             return compMinOpts;
9459         }
9460         bool IsMinOptsSet() const
9461         {
9462             return compMinOptsIsSet;
9463         }
9464 #else  // !DEBUG
9465         bool MinOpts() const
9466         {
9467             return compMinOpts;
9468         }
9469         bool IsMinOptsSet() const
9470         {
9471             return compMinOptsIsSet;
9472         }
9473 #endif // !DEBUG
9474
9475         bool OptimizationDisabled() const
9476         {
9477             return MinOpts() || compDbgCode;
9478         }
9479         bool OptimizationEnabled() const
9480         {
9481             return !OptimizationDisabled();
9482         }
9483
9484         void SetMinOpts(bool val)
9485         {
9486             assert(!compMinOptsIsUsed);
9487             assert(!compMinOptsIsSet || (compMinOpts == val));
9488             compMinOpts      = val;
9489             compMinOptsIsSet = true;
9490         }
9491
9492         // true if the CLFLG_* for an optimization is set.
9493         bool OptEnabled(unsigned optFlag) const
9494         {
9495             return !!(compFlags & optFlag);
9496         }
9497
9498 #ifdef FEATURE_READYTORUN
9499         bool IsReadyToRun() const
9500         {
9501             return jitFlags->IsSet(JitFlags::JIT_FLAG_READYTORUN);
9502         }
9503 #else
9504         bool IsReadyToRun() const
9505         {
9506             return false;
9507         }
9508 #endif
9509
9510         // Check if the compilation is control-flow guard enabled.
9511         bool IsCFGEnabled() const
9512         {
9513 #if defined(TARGET_ARM64) || defined(TARGET_AMD64)
9514             // On these platforms we assume the register that the target is
9515             // passed in is preserved by the validator and take care to get the
9516             // target from the register for the call (even in debug mode).
9517             static_assert_no_msg((RBM_VALIDATE_INDIRECT_CALL_TRASH & (1 << REG_VALIDATE_INDIRECT_CALL_ADDR)) == 0);
9518             if (JitConfig.JitForceControlFlowGuard())
9519                 return true;
9520
9521             return jitFlags->IsSet(JitFlags::JIT_FLAG_ENABLE_CFG);
9522 #else
9523             // The remaining platforms are not supported and would require some
9524             // work to support.
9525             //
9526             // ARM32:
9527             //   The ARM32 validator does not preserve any volatile registers
9528             //   which means we have to take special care to allocate and use a
9529             //   callee-saved register (reloading the target from memory is a
9530             //   security issue).
9531             //
9532             // x86:
9533             //   On x86 some VSD calls disassemble the call site and expect an
9534             //   indirect call which is fundamentally incompatible with CFG.
9535             //   This would require a different way to pass this information
9536             //   through.
9537             //
9538             return false;
9539 #endif
9540         }
9541
9542 #ifdef FEATURE_ON_STACK_REPLACEMENT
9543         bool IsOSR() const
9544         {
9545             return jitFlags->IsSet(JitFlags::JIT_FLAG_OSR);
9546         }
9547 #else
9548         bool IsOSR() const
9549         {
9550             return false;
9551         }
9552 #endif
9553
9554         bool IsTier0() const
9555         {
9556             return jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0);
9557         }
9558
9559         bool IsInstrumented() const
9560         {
9561             return jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR);
9562         }
9563
9564         bool IsInstrumentedAndOptimized() const
9565         {
9566             return IsInstrumented() && jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT);
9567         }
9568
9569         bool DoEarlyBlockMerging() const
9570         {
9571             if (jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_EnC) || jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_CODE))
9572             {
9573                 return false;
9574             }
9575
9576             if (jitFlags->IsSet(JitFlags::JIT_FLAG_MIN_OPT) && !jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0))
9577             {
9578                 return false;
9579             }
9580
9581             return true;
9582         }
9583
9584         // true if we should use the PINVOKE_{BEGIN,END} helpers instead of generating
9585         // PInvoke transitions inline. Normally used by R2R, but also used when generating a reverse pinvoke frame, as
9586         // the current logic for frame setup initializes and pushes
9587         // the InlinedCallFrame before performing the Reverse PInvoke transition, which is invalid (as frames cannot
9588         // safely be pushed/popped while the thread is in a preemptive state.).
9589         bool ShouldUsePInvokeHelpers()
9590         {
9591             return jitFlags->IsSet(JitFlags::JIT_FLAG_USE_PINVOKE_HELPERS) ||
9592                    jitFlags->IsSet(JitFlags::JIT_FLAG_REVERSE_PINVOKE);
9593         }
9594
9595         // true if we should use insert the REVERSE_PINVOKE_{ENTER,EXIT} helpers in the method
9596         // prolog/epilog
9597         bool IsReversePInvoke()
9598         {
9599             return jitFlags->IsSet(JitFlags::JIT_FLAG_REVERSE_PINVOKE);
9600         }
9601
9602         bool compScopeInfo; // Generate the LocalVar info ?
9603         bool compDbgCode;   // Generate debugger-friendly code?
9604         bool compDbgInfo;   // Gather debugging info?
9605         bool compDbgEnC;
9606
9607 #ifdef PROFILING_SUPPORTED
9608         bool compNoPInvokeInlineCB;
9609 #else
9610         static const bool compNoPInvokeInlineCB;
9611 #endif
9612
9613 #ifdef DEBUG
9614         bool compGcChecks; // Check arguments and return values to ensure they are sane
9615 #endif
9616
9617 #if defined(DEBUG) && defined(TARGET_XARCH)
9618
9619         bool compStackCheckOnRet; // Check stack pointer on return to ensure it is correct.
9620
9621 #endif // defined(DEBUG) && defined(TARGET_XARCH)
9622
9623 #if defined(DEBUG) && defined(TARGET_X86)
9624
9625         bool compStackCheckOnCall; // Check stack pointer after call to ensure it is correct. Only for x86.
9626
9627 #endif // defined(DEBUG) && defined(TARGET_X86)
9628
9629         bool compReloc; // Generate relocs for pointers in code, true for all ngen/prejit codegen
9630
9631 #ifdef DEBUG
9632 #if defined(TARGET_XARCH)
9633         bool compEnablePCRelAddr; // Whether absolute addr be encoded as PC-rel offset by RyuJIT where possible
9634 #endif
9635 #endif // DEBUG
9636
9637 #ifdef UNIX_AMD64_ABI
9638         // This flag  is indicating if there is a need to align the frame.
9639         // On AMD64-Windows, if there are calls, 4 slots for the outgoing ars are allocated, except for
9640         // FastTailCall. This slots makes the frame size non-zero, so alignment logic will be called.
9641         // On AMD64-Unix, there are no such slots. There is a possibility to have calls in the method with frame size of
9642         // 0. The frame alignment logic won't kick in. This flags takes care of the AMD64-Unix case by remembering that
9643         // there are calls and making sure the frame alignment logic is executed.
9644         bool compNeedToAlignFrame;
9645 #endif // UNIX_AMD64_ABI
9646
9647         bool compProcedureSplitting; // Separate cold code from hot code
9648
9649         bool genFPorder; // Preserve FP order (operations are non-commutative)
9650         bool genFPopt;   // Can we do frame-pointer-omission optimization?
9651         bool altJit;     // True if we are an altjit and are compiling this method
9652
9653 #ifdef OPT_CONFIG
9654         bool optRepeat; // Repeat optimizer phases k times
9655 #endif
9656
9657         bool disAsm;       // Display native code as it is generated
9658         bool disTesting;   // Display BEGIN METHOD/END METHOD anchors for disasm testing
9659         bool dspDiffable;  // Makes the Jit Dump 'diff-able' (currently uses same DOTNET_* flag as disDiffable)
9660         bool disDiffable;  // Makes the Disassembly code 'diff-able'
9661         bool disAlignment; // Display alignment boundaries in disassembly code
9662         bool disCodeBytes; // Display instruction code bytes in disassembly code
9663 #ifdef DEBUG
9664         bool compProcedureSplittingEH; // Separate cold code from hot code for functions with EH
9665         bool dspCode;                  // Display native code generated
9666         bool dspEHTable;               // Display the EH table reported to the VM
9667         bool dspDebugInfo;             // Display the Debug info reported to the VM
9668         bool dspInstrs;                // Display the IL instructions intermixed with the native code output
9669         bool dspLines;                 // Display source-code lines intermixed with native code output
9670         bool dmpHex;                   // Display raw bytes in hex of native code output
9671         bool varNames;                 // Display variables names in native code output
9672         bool disAsmSpilled;            // Display native code when any register spilling occurs
9673         bool disasmWithGC;             // Display GC info interleaved with disassembly.
9674         bool disAddr;                  // Display process address next to each instruction in disassembly code
9675         bool disAsm2;                  // Display native code after it is generated using external disassembler
9676         bool dspOrder;                 // Display names of each of the methods that we ngen/jit
9677         bool dspUnwind;                // Display the unwind info output
9678         bool compLongAddress;          // Force using large pseudo instructions for long address
9679                                        // (IF_LARGEJMP/IF_LARGEADR/IF_LARGLDC)
9680         bool dspGCtbls;                // Display the GC tables
9681 #endif
9682
9683 // Default numbers used to perform loop alignment. All the numbers are chosen
9684 // based on experimenting with various benchmarks.
9685
9686 // Default minimum loop block weight required to enable loop alignment.
9687 #define DEFAULT_ALIGN_LOOP_MIN_BLOCK_WEIGHT 4
9688
9689 // By default a loop will be aligned at 32B address boundary to get better
9690 // performance as per architecture manuals.
9691 #define DEFAULT_ALIGN_LOOP_BOUNDARY 0x20
9692
9693 // For non-adaptive loop alignment, by default, only align a loop whose size is
9694 // at most 3 times the alignment block size. If the loop is bigger than that, it is most
9695 // likely complicated enough that loop alignment will not impact performance.
9696 #define DEFAULT_MAX_LOOPSIZE_FOR_ALIGN DEFAULT_ALIGN_LOOP_BOUNDARY * 3
9697
9698 // By default only loops with a constant iteration count less than or equal to this will be unrolled
9699 #define DEFAULT_UNROLL_LOOP_MAX_ITERATION_COUNT 4
9700
9701 #ifdef DEBUG
9702         // Loop alignment variables
9703
9704         // If set, for non-adaptive alignment, ensure loop jmps are not on or cross alignment boundary.
9705         bool compJitAlignLoopForJcc;
9706 #endif
9707         // For non-adaptive alignment, minimum loop size (in bytes) for which alignment will be done.
9708         unsigned short compJitAlignLoopMaxCodeSize;
9709
9710         // Minimum weight needed for the first block of a loop to make it a candidate for alignment.
9711         unsigned short compJitAlignLoopMinBlockWeight;
9712
9713         // For non-adaptive alignment, address boundary (power of 2) at which loop alignment should
9714         // be done. By default, 32B.
9715         unsigned short compJitAlignLoopBoundary;
9716
9717         // Padding limit to align a loop.
9718         unsigned short compJitAlignPaddingLimit;
9719
9720         // If set, perform adaptive loop alignment that limits number of padding based on loop size.
9721         bool compJitAlignLoopAdaptive;
9722
9723         // If set, tries to hide alignment instructions behind unconditional jumps.
9724         bool compJitHideAlignBehindJmp;
9725
9726         // If set, tracks the hidden return buffer for struct arg.
9727         bool compJitOptimizeStructHiddenBuffer;
9728
9729         // Iteration limit to unroll a loop.
9730         unsigned short compJitUnrollLoopMaxIterationCount;
9731
9732 #ifdef LATE_DISASM
9733         bool doLateDisasm; // Run the late disassembler
9734 #endif                     // LATE_DISASM
9735
9736 #if DUMP_GC_TABLES && !defined(DEBUG)
9737 #pragma message("NOTE: this non-debug build has GC ptr table dumping always enabled!")
9738         static const bool dspGCtbls = true;
9739 #endif
9740
9741 #ifdef PROFILING_SUPPORTED
9742         // Whether to emit Enter/Leave/TailCall hooks using a dummy stub (DummyProfilerELTStub()).
9743         // This option helps make the JIT behave as if it is running under a profiler.
9744         bool compJitELTHookEnabled;
9745 #endif // PROFILING_SUPPORTED
9746
9747 #if FEATURE_TAILCALL_OPT
9748         // Whether opportunistic or implicit tail call optimization is enabled.
9749         bool compTailCallOpt;
9750         // Whether optimization of transforming a recursive tail call into a loop is enabled.
9751         bool compTailCallLoopOpt;
9752 #endif
9753
9754 #if FEATURE_FASTTAILCALL
9755         // Whether fast tail calls are allowed.
9756         bool compFastTailCalls;
9757 #endif // FEATURE_FASTTAILCALL
9758
9759 #if defined(TARGET_ARM64)
9760         // Decision about whether to save FP/LR registers with callee-saved registers (see
9761         // DOTNET_JitSaveFpLrWithCalleSavedRegisters).
9762         int compJitSaveFpLrWithCalleeSavedRegisters;
9763 #endif // defined(TARGET_ARM64)
9764
9765 #ifdef CONFIGURABLE_ARM_ABI
9766         bool compUseSoftFP = false;
9767 #else
9768 #ifdef ARM_SOFTFP
9769         static const bool compUseSoftFP = true;
9770 #else  // !ARM_SOFTFP
9771         static const bool compUseSoftFP = false;
9772 #endif // ARM_SOFTFP
9773 #endif // CONFIGURABLE_ARM_ABI
9774
9775         // Collect 64 bit counts for PGO data.
9776         bool compCollect64BitCounts;
9777
9778     } opts;
9779
9780     static bool                s_pAltJitExcludeAssembliesListInitialized;
9781     static AssemblyNamesList2* s_pAltJitExcludeAssembliesList;
9782
9783 #ifdef DEBUG
9784     static bool                s_pJitDisasmIncludeAssembliesListInitialized;
9785     static AssemblyNamesList2* s_pJitDisasmIncludeAssembliesList;
9786
9787     static bool       s_pJitFunctionFileInitialized;
9788     static MethodSet* s_pJitMethodSet;
9789
9790 // silence warning of cast to greater size. It is easier to silence than construct code the compiler is happy with, and
9791 // it is safe in this case
9792 #pragma warning(push)
9793 #pragma warning(disable : 4312)
9794
9795     template <typename T>
9796     T dspPtr(T p)
9797     {
9798         return (p == ZERO) ? ZERO : (opts.dspDiffable ? T(0xD1FFAB1E) : p);
9799     }
9800
9801     template <typename T>
9802     T dspOffset(T o)
9803     {
9804         return (o == ZERO) ? ZERO : (opts.dspDiffable ? T(0xD1FFAB1E) : o);
9805     }
9806 #pragma warning(pop)
9807 #else
9808 #pragma warning(push)
9809 #pragma warning(disable : 4312)
9810     template <typename T>
9811     T dspPtr(T p)
9812     {
9813         return p;
9814     }
9815
9816     template <typename T>
9817     T dspOffset(T o)
9818     {
9819         return o;
9820     }
9821 #pragma warning(pop)
9822 #endif
9823
9824 #ifdef DEBUG
9825
9826     static int dspTreeID(GenTree* tree)
9827     {
9828         return tree->gtTreeID;
9829     }
9830
9831     static void printStmtID(Statement* stmt)
9832     {
9833         assert(stmt != nullptr);
9834         printf(FMT_STMT, stmt->GetID());
9835     }
9836
9837     static void printTreeID(GenTree* tree)
9838     {
9839         if (tree == nullptr)
9840         {
9841             printf("[------]");
9842         }
9843         else
9844         {
9845             printf("[%06d]", dspTreeID(tree));
9846         }
9847     }
9848
9849     const char* devirtualizationDetailToString(CORINFO_DEVIRTUALIZATION_DETAIL detail);
9850
9851 #endif // DEBUG
9852
9853 // clang-format off
9854 #define STRESS_MODES                                                                            \
9855                                                                                                 \
9856         STRESS_MODE(NONE)                                                                       \
9857                                                                                                 \
9858         /* "Variations" stress areas which we try to mix up with each other. */                 \
9859         /* These should not be exhaustively used as they might */                               \
9860         /* hide/trivialize other areas */                                                       \
9861                                                                                                 \
9862         STRESS_MODE(REGS)                                                                       \
9863         STRESS_MODE(DBL_ALN)                                                                    \
9864         STRESS_MODE(LCL_FLDS)                                                                   \
9865         STRESS_MODE(UNROLL_LOOPS)                                                               \
9866         STRESS_MODE(MAKE_CSE)                                                                   \
9867         STRESS_MODE(LEGACY_INLINE)                                                              \
9868         STRESS_MODE(CLONE_EXPR)                                                                 \
9869         STRESS_MODE(FOLD)                                                                       \
9870         STRESS_MODE(MERGED_RETURNS)                                                             \
9871         STRESS_MODE(BB_PROFILE)                                                                 \
9872         STRESS_MODE(OPT_BOOLS_GC)                                                               \
9873         STRESS_MODE(OPT_BOOLS_COMPARE_CHAIN_COST)                                               \
9874         STRESS_MODE(REMORPH_TREES)                                                              \
9875         STRESS_MODE(64RSLT_MUL)                                                                 \
9876         STRESS_MODE(DO_WHILE_LOOPS)                                                             \
9877         STRESS_MODE(MIN_OPTS)                                                                   \
9878         STRESS_MODE(REVERSE_FLAG)     /* Will set GTF_REVERSE_OPS whenever we can */            \
9879         STRESS_MODE(TAILCALL)         /* Will make the call as a tailcall whenever legal */     \
9880         STRESS_MODE(CATCH_ARG)        /* Will spill catch arg */                                \
9881         STRESS_MODE(UNSAFE_BUFFER_CHECKS)                                                       \
9882         STRESS_MODE(NULL_OBJECT_CHECK)                                                          \
9883         STRESS_MODE(RANDOM_INLINE)                                                              \
9884         STRESS_MODE(SWITCH_CMP_BR_EXPANSION)                                                    \
9885         STRESS_MODE(GENERIC_VARN)                                                               \
9886         STRESS_MODE(PROFILER_CALLBACKS) /* Will generate profiler hooks for ELT callbacks */    \
9887         STRESS_MODE(BYREF_PROMOTION) /* Change undoPromotion decisions for byrefs */            \
9888         STRESS_MODE(PROMOTE_FEWER_STRUCTS)/* Don't promote some structs that can be promoted */ \
9889         STRESS_MODE(VN_BUDGET)/* Randomize the VN budget */                                     \
9890         STRESS_MODE(SSA_INFO) /* Select lower thresholds for "complex" SSA num encoding */      \
9891         STRESS_MODE(SPLIT_TREES_RANDOMLY) /* Split all statements at a random tree */           \
9892         STRESS_MODE(SPLIT_TREES_REMOVE_COMMAS) /* Remove all GT_COMMA nodes */                  \
9893         STRESS_MODE(NO_OLD_PROMOTION) /* Do not use old promotion */                            \
9894         STRESS_MODE(PHYSICAL_PROMOTION) /* Use physical promotion */                            \
9895         STRESS_MODE(PHYSICAL_PROMOTION_COST)                                                    \
9896                                                                                                 \
9897         /* After COUNT_VARN, stress level 2 does all of these all the time */                   \
9898                                                                                                 \
9899         STRESS_MODE(COUNT_VARN)                                                                 \
9900                                                                                                 \
9901         /* "Check" stress areas that can be exhaustively used if we */                          \
9902         /*  dont care about performance at all */                                               \
9903                                                                                                 \
9904         STRESS_MODE(FORCE_INLINE) /* Treat every method as AggressiveInlining */                \
9905         STRESS_MODE(CHK_FLOW_UPDATE)                                                            \
9906         STRESS_MODE(EMITTER)                                                                    \
9907         STRESS_MODE(CHK_REIMPORT)                                                               \
9908         STRESS_MODE(GENERIC_CHECK)                                                              \
9909         STRESS_MODE(IF_CONVERSION_COST)                                                         \
9910         STRESS_MODE(IF_CONVERSION_INNER_LOOPS)                                                  \
9911         STRESS_MODE(POISON_IMPLICIT_BYREFS)                                                     \
9912         STRESS_MODE(COUNT)
9913
9914     enum                compStressArea
9915     {
9916 #define STRESS_MODE(mode) STRESS_##mode,
9917         STRESS_MODES
9918 #undef STRESS_MODE
9919     };
9920 // clang-format on
9921
9922 #ifdef DEBUG
9923     static const LPCWSTR s_compStressModeNamesW[STRESS_COUNT + 1];
9924     static const char*   s_compStressModeNames[STRESS_COUNT + 1];
9925     BYTE                 compActiveStressModes[STRESS_COUNT];
9926 #endif // DEBUG
9927
9928 #define MAX_STRESS_WEIGHT 100
9929
9930     bool compStressCompile(compStressArea stressArea, unsigned weightPercentage);
9931     bool compStressCompileHelper(compStressArea stressArea, unsigned weightPercentage);
9932     static unsigned compStressAreaHash(compStressArea area);
9933
9934 #ifdef DEBUG
9935
9936     bool compInlineStress()
9937     {
9938         return compStressCompile(STRESS_LEGACY_INLINE, 50);
9939     }
9940
9941     bool compRandomInlineStress()
9942     {
9943         return compStressCompile(STRESS_RANDOM_INLINE, 50);
9944     }
9945
9946     bool compPromoteFewerStructs(unsigned lclNum);
9947
9948 #endif // DEBUG
9949
9950     bool compTailCallStress()
9951     {
9952 #ifdef DEBUG
9953         // Do not stress tailcalls in IL stubs as the runtime creates several IL
9954         // stubs to implement the tailcall mechanism, which would then
9955         // recursively create more IL stubs.
9956         return !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB) &&
9957                (JitConfig.TailcallStress() != 0 || compStressCompile(STRESS_TAILCALL, 5));
9958 #else
9959         return false;
9960 #endif
9961     }
9962
9963     const char* compGetTieringName(bool wantShortName = false) const;
9964     const char* compGetPgoSourceName() const;
9965     const char* compGetStressMessage() const;
9966
9967     codeOptimize compCodeOpt() const
9968     {
9969 #if 0
9970         // Switching between size & speed has measurable throughput impact
9971         // (3.5% on NGen CoreLib when measured). It used to be enabled for
9972         // DEBUG, but should generate identical code between CHK & RET builds,
9973         // so that's not acceptable.
9974         // TODO-Throughput: Figure out what to do about size vs. speed & throughput.
9975         //                  Investigate the cause of the throughput regression.
9976
9977         return opts.compCodeOpt;
9978 #else
9979         return BLENDED_CODE;
9980 #endif
9981     }
9982
9983     //--------------------- Info about the procedure --------------------------
9984
9985     struct Info
9986     {
9987         COMP_HANDLE           compCompHnd;
9988         CORINFO_MODULE_HANDLE compScopeHnd;
9989         CORINFO_CLASS_HANDLE  compClassHnd;
9990         CORINFO_METHOD_HANDLE compMethodHnd;
9991         CORINFO_METHOD_INFO*  compMethodInfo;
9992
9993         bool hasCircularClassConstraints;
9994         bool hasCircularMethodConstraints;
9995
9996 #if defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS || DUMP_GC_TABLES
9997
9998         const char* compMethodName;
9999         const char* compClassName;
10000         const char* compFullName;
10001         double      compPerfScore;
10002         int         compMethodSuperPMIIndex; // useful when debugging under SuperPMI
10003
10004 #endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS
10005
10006 #if defined(DEBUG) || defined(INLINE_DATA)
10007         // Method hash is logically const, but computed
10008         // on first demand.
10009         mutable unsigned compMethodHashPrivate;
10010         unsigned         compMethodHash() const;
10011 #endif // defined(DEBUG) || defined(INLINE_DATA)
10012
10013 #ifdef PSEUDORANDOM_NOP_INSERTION
10014         // things for pseudorandom nop insertion
10015         unsigned  compChecksum;
10016         CLRRandom compRNG;
10017 #endif
10018
10019         // The following holds the FLG_xxxx flags for the method we're compiling.
10020         unsigned compFlags;
10021
10022         // The following holds the class attributes for the method we're compiling.
10023         unsigned compClassAttr;
10024
10025         const BYTE*     compCode;
10026         IL_OFFSET       compILCodeSize;     // The IL code size
10027         IL_OFFSET       compILImportSize;   // Estimated amount of IL actually imported
10028         IL_OFFSET       compILEntry;        // The IL entry point (normally 0)
10029         PatchpointInfo* compPatchpointInfo; // Patchpoint data for OSR (normally nullptr)
10030         UNATIVE_OFFSET  compNativeCodeSize; // The native code size, after instructions are issued. This
10031         // is less than (compTotalHotCodeSize + compTotalColdCodeSize) only if:
10032         // (1) the code is not hot/cold split, and we issued less code than we expected, or
10033         // (2) the code is hot/cold split, and we issued less code than we expected
10034         // in the cold section (the hot section will always be padded out to compTotalHotCodeSize).
10035
10036         bool compIsStatic : 1;           // Is the method static (no 'this' pointer)?
10037         bool compIsVarArgs : 1;          // Does the method have varargs parameters?
10038         bool compInitMem : 1;            // Is the CORINFO_OPT_INIT_LOCALS bit set in the method info options?
10039         bool compProfilerCallback : 1;   // JIT inserted a profiler Enter callback
10040         bool compPublishStubParam : 1;   // EAX captured in prolog will be available through an intrinsic
10041         bool compHasNextCallRetAddr : 1; // The NextCallReturnAddress intrinsic is used.
10042
10043         var_types compRetType;       // Return type of the method as declared in IL (including SIMD normalization)
10044         var_types compRetNativeType; // Normalized return type as per target arch ABI
10045         unsigned  compILargsCount;   // Number of arguments (incl. implicit but not hidden)
10046         unsigned  compArgsCount;     // Number of arguments (incl. implicit and     hidden)
10047
10048 #if FEATURE_FASTTAILCALL
10049         unsigned compArgStackSize; // Incoming argument stack size in bytes
10050 #endif                             // FEATURE_FASTTAILCALL
10051
10052         unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present);
10053         int compTypeCtxtArg; // position of hidden param for type context for generic code (CORINFO_CALLCONV_PARAMTYPE)
10054         unsigned       compThisArg; // position of implicit this pointer param (not to be confused with lvaArg0Var)
10055         unsigned       compILlocalsCount; // Number of vars : args + locals (incl. implicit but not hidden)
10056         unsigned       compLocalsCount;   // Number of vars : args + locals (incl. implicit and     hidden)
10057         unsigned       compMaxStack;
10058         UNATIVE_OFFSET compTotalHotCodeSize;  // Total number of bytes of Hot Code in the method
10059         UNATIVE_OFFSET compTotalColdCodeSize; // Total number of bytes of Cold Code in the method
10060
10061         unsigned compUnmanagedCallCountWithGCTransition; // count of unmanaged calls with GC transition.
10062
10063         CorInfoCallConvExtension compCallConv; // The entry-point calling convention for this method.
10064
10065         unsigned compLvFrameListRoot; // lclNum for the Frame root
10066         unsigned compXcptnsCount;     // Number of exception-handling clauses read in the method's IL.
10067                                       // You should generally use compHndBBtabCount instead: it is the
10068                                       // current number of EH clauses (after additions like synchronized
10069         // methods and funclets, and removals like unreachable code deletion).
10070
10071         Target::ArgOrder compArgOrder;
10072
10073         bool compMatchedVM; // true if the VM is "matched": either the JIT is a cross-compiler
10074                             // and the VM expects that, or the JIT is a "self-host" compiler
10075                             // (e.g., x86 hosted targeting x86) and the VM expects that.
10076
10077         /*  The following holds IL scope information about local variables.
10078          */
10079
10080         unsigned     compVarScopesCount;
10081         VarScopeDsc* compVarScopes;
10082
10083         /* The following holds information about instr offsets for
10084          * which we need to report IP-mappings
10085          */
10086
10087         IL_OFFSET*                   compStmtOffsets; // sorted
10088         unsigned                     compStmtOffsetsCount;
10089         ICorDebugInfo::BoundaryTypes compStmtOffsetsImplicit;
10090
10091         // Number of class profile probes in this method
10092         unsigned compHandleHistogramProbeCount;
10093
10094 #ifdef TARGET_ARM64
10095         bool compNeedsConsecutiveRegisters;
10096 #endif
10097
10098     } info;
10099
10100 #if defined(DEBUG)
10101     // Are we running a replay under SuperPMI?
10102     bool RunningSuperPmiReplay() const
10103     {
10104         return info.compMethodSuperPMIIndex != -1;
10105     }
10106 #endif // DEBUG
10107
10108     ReturnTypeDesc compRetTypeDesc; // ABI return type descriptor for the method
10109
10110     //------------------------------------------------------------------------
10111     // compMethodHasRetVal: Does this method return some kind of value?
10112     //
10113     // Return Value:
10114     //    If this method returns a struct via a return buffer, whether that
10115     //    buffer's address needs to be returned, otherwise whether signature
10116     //    return type is not "TYP_VOID".
10117     //
10118     bool compMethodHasRetVal() const
10119     {
10120         return (info.compRetBuffArg != BAD_VAR_NUM) ? compMethodReturnsRetBufAddr() : (info.compRetType != TYP_VOID);
10121     }
10122
10123     // Returns true if the method being compiled returns RetBuf addr as its return value
10124     bool compMethodReturnsRetBufAddr() const
10125     {
10126         // There are cases where implicit RetBuf argument should be explicitly returned in a register.
10127         // In such cases the return type is changed to TYP_BYREF and appropriate IR is generated.
10128         // These cases are:
10129         CLANG_FORMAT_COMMENT_ANCHOR;
10130 #ifdef TARGET_AMD64
10131         // 1. on x64 Windows and Unix the address of RetBuf needs to be returned by
10132         //    methods with hidden RetBufArg in RAX. In such case GT_RETURN is of TYP_BYREF,
10133         //    returning the address of RetBuf.
10134         return (info.compRetBuffArg != BAD_VAR_NUM);
10135 #else // TARGET_AMD64
10136 #ifdef PROFILING_SUPPORTED
10137         // 2.  Profiler Leave callback expects the address of retbuf as return value for
10138         //    methods with hidden RetBuf argument.  impReturnInstruction() when profiler
10139         //    callbacks are needed creates GT_RETURN(TYP_BYREF, op1 = Addr of RetBuf) for
10140         //    methods with hidden RetBufArg.
10141         if (compIsProfilerHookNeeded())
10142         {
10143             return (info.compRetBuffArg != BAD_VAR_NUM);
10144         }
10145 #endif
10146         // 3. Windows ARM64 native instance calling convention requires the address of RetBuff
10147         //    to be returned in x0.
10148         CLANG_FORMAT_COMMENT_ANCHOR;
10149 #if defined(TARGET_ARM64)
10150         if (TargetOS::IsWindows)
10151         {
10152             auto callConv = info.compCallConv;
10153             if (callConvIsInstanceMethodCallConv(callConv))
10154             {
10155                 return (info.compRetBuffArg != BAD_VAR_NUM);
10156             }
10157         }
10158 #endif // TARGET_ARM64
10159         // 4. x86 unmanaged calling conventions require the address of RetBuff to be returned in eax.
10160         CLANG_FORMAT_COMMENT_ANCHOR;
10161 #if defined(TARGET_X86)
10162         if (info.compCallConv != CorInfoCallConvExtension::Managed)
10163         {
10164             return (info.compRetBuffArg != BAD_VAR_NUM);
10165         }
10166 #endif
10167
10168         return false;
10169 #endif // TARGET_AMD64
10170     }
10171
10172     //------------------------------------------------------------------------
10173     // compMethodReturnsMultiRegRetType: Does this method return a multi-reg value?
10174     //
10175     // Return Value:
10176     //    If this method returns a value in multiple registers, "true", "false"
10177     //    otherwise.
10178     //
10179     bool compMethodReturnsMultiRegRetType() const
10180     {
10181         return compRetTypeDesc.IsMultiRegRetType();
10182     }
10183
10184     bool compEnregLocals()
10185     {
10186         return ((opts.compFlags & CLFLG_REGVAR) != 0);
10187     }
10188
10189     bool compEnregStructLocals()
10190     {
10191         return (JitConfig.JitEnregStructLocals() != 0);
10192     }
10193
10194     bool compObjectStackAllocation()
10195     {
10196         return (JitConfig.JitObjectStackAllocation() != 0);
10197     }
10198
10199     // Returns true if the method requires a PInvoke prolog and epilog
10200     bool compMethodRequiresPInvokeFrame()
10201     {
10202         return (info.compUnmanagedCallCountWithGCTransition > 0);
10203     }
10204
10205     // Returns true if address-exposed user variables should be poisoned with a recognizable value
10206     bool compShouldPoisonFrame()
10207     {
10208 #ifdef FEATURE_ON_STACK_REPLACEMENT
10209         if (opts.IsOSR())
10210             return false;
10211 #endif
10212         return !info.compInitMem && opts.compDbgCode;
10213     }
10214
10215     // Returns true if the jit supports having patchpoints in this method.
10216     // Optionally, get the reason why not.
10217     bool compCanHavePatchpoints(const char** reason = nullptr);
10218
10219 #if defined(DEBUG)
10220
10221     void compDispLocalVars();
10222
10223 #endif // DEBUG
10224
10225 private:
10226     class ClassLayoutTable* m_classLayoutTable;
10227
10228     class ClassLayoutTable* typCreateClassLayoutTable();
10229     class ClassLayoutTable* typGetClassLayoutTable();
10230
10231 public:
10232     // Get the layout having the specified layout number.
10233     ClassLayout* typGetLayoutByNum(unsigned layoutNum);
10234     // Get the layout number of the specified layout.
10235     unsigned typGetLayoutNum(ClassLayout* layout);
10236     // Get the layout having the specified size but no class handle.
10237     ClassLayout* typGetBlkLayout(unsigned blockSize);
10238     // Get the number of a layout having the specified size but no class handle.
10239     unsigned typGetBlkLayoutNum(unsigned blockSize);
10240     // Get the layout for the specified class handle.
10241     ClassLayout* typGetObjLayout(CORINFO_CLASS_HANDLE classHandle);
10242     // Get the number of a layout for the specified class handle.
10243     unsigned typGetObjLayoutNum(CORINFO_CLASS_HANDLE classHandle);
10244
10245     var_types TypeHandleToVarType(CORINFO_CLASS_HANDLE handle, ClassLayout** pLayout = nullptr);
10246     var_types TypeHandleToVarType(CorInfoType jitType, CORINFO_CLASS_HANDLE handle, ClassLayout** pLayout = nullptr);
10247
10248 //-------------------------- Global Compiler Data ------------------------------------
10249
10250 #ifdef DEBUG
10251 private:
10252     static LONG s_compMethodsCount; // to produce unique label names
10253 #endif
10254
10255 public:
10256 #ifdef DEBUG
10257     unsigned compGenTreeID;
10258     unsigned compStatementID;
10259     unsigned compBasicBlockID;
10260 #endif
10261     LONG compMethodID;
10262
10263     BasicBlock* compCurBB;   // the current basic block in process
10264     Statement*  compCurStmt; // the current statement in process
10265     GenTree*    compCurTree; // the current tree in process
10266
10267     //  The following is used to create the 'method JIT info' block.
10268     size_t compInfoBlkSize;
10269     BYTE*  compInfoBlkAddr;
10270
10271     EHblkDsc* compHndBBtab;           // array of EH data
10272     unsigned  compHndBBtabCount;      // element count of used elements in EH data array
10273     unsigned  compHndBBtabAllocCount; // element count of allocated elements in EH data array
10274
10275 #if defined(TARGET_X86)
10276
10277     //-------------------------------------------------------------------------
10278     //  Tracking of region covered by the monitor in synchronized methods
10279     void* syncStartEmitCookie; // the emitter cookie for first instruction after the call to MON_ENTER
10280     void* syncEndEmitCookie;   // the emitter cookie for first instruction after the call to MON_EXIT
10281
10282 #endif // !TARGET_X86
10283
10284     Phases      mostRecentlyActivePhase; // the most recently active phase
10285     PhaseChecks activePhaseChecks;       // the currently active phase checks
10286     PhaseDumps  activePhaseDumps;        // the currently active phase dumps
10287
10288     //-------------------------------------------------------------------------
10289     //  The following keeps track of how many bytes of local frame space we've
10290     //  grabbed so far in the current function, and how many argument bytes we
10291     //  need to pop when we return.
10292     //
10293
10294     unsigned compLclFrameSize; // secObject+lclBlk+locals+temps
10295
10296     // Count of callee-saved regs we pushed in the prolog.
10297     // Does not include EBP for isFramePointerUsed() and double-aligned frames.
10298     // In case of Amd64 this doesn't include float regs saved on stack.
10299     unsigned compCalleeRegsPushed;
10300
10301 #if defined(TARGET_XARCH)
10302     // Mask of callee saved float regs on stack.
10303     regMaskTP compCalleeFPRegsSavedMask;
10304 #endif
10305 #ifdef TARGET_AMD64
10306 // Quirk for VS debug-launch scenario to work:
10307 // Bytes of padding between save-reg area and locals.
10308 #define VSQUIRK_STACK_PAD (2 * REGSIZE_BYTES)
10309     unsigned compVSQuirkStackPaddingNeeded;
10310 #endif
10311
10312     unsigned compArgSize; // total size of arguments in bytes (including register args (lvIsRegArg))
10313
10314 #if defined(TARGET_ARM) || defined(TARGET_RISCV64)
10315     bool compHasSplitParam;
10316 #endif
10317
10318     unsigned compMapILargNum(unsigned ILargNum);      // map accounting for hidden args
10319     unsigned compMapILvarNum(unsigned ILvarNum);      // map accounting for hidden args
10320     unsigned compMap2ILvarNum(unsigned varNum) const; // map accounting for hidden args
10321
10322 #if defined(TARGET_ARM64)
10323     struct FrameInfo
10324     {
10325         // Frame type (1-5)
10326         int frameType;
10327
10328         // Distance from established (method body) SP to base of callee save area
10329         int calleeSaveSpOffset;
10330
10331         // Amount to subtract from SP before saving (prolog) OR
10332         // to add to SP after restoring (epilog) callee saves
10333         int calleeSaveSpDelta;
10334
10335         // Distance from established SP to where caller's FP was saved
10336         int offsetSpToSavedFp;
10337     } compFrameInfo;
10338 #endif
10339
10340     //-------------------------------------------------------------------------
10341
10342     static void compStartup();  // One-time initialization
10343     static void compShutdown(); // One-time finalization
10344
10345     void compInit(ArenaAllocator*       pAlloc,
10346                   CORINFO_METHOD_HANDLE methodHnd,
10347                   COMP_HANDLE           compHnd,
10348                   CORINFO_METHOD_INFO*  methodInfo,
10349                   InlineInfo*           inlineInfo);
10350     void compDone();
10351
10352     static void compDisplayStaticSizes();
10353
10354     //------------ Some utility functions --------------
10355
10356     void* compGetHelperFtn(CorInfoHelpFunc ftnNum,         /* IN  */
10357                            void**          ppIndirection); /* OUT */
10358
10359     // Several JIT/EE interface functions return a CorInfoType, and also return a
10360     // class handle as an out parameter if the type is a value class.  Returns the
10361     // size of the type these describe.
10362     unsigned compGetTypeSize(CorInfoType cit, CORINFO_CLASS_HANDLE clsHnd);
10363
10364 #ifdef DEBUG
10365     // Components used by the compiler may write unit test suites, and
10366     // have them run within this method.  They will be run only once per process, and only
10367     // in debug.  (Perhaps should be under the control of a DOTNET_ flag.)
10368     // These should fail by asserting.
10369     void compDoComponentUnitTestsOnce();
10370 #endif // DEBUG
10371
10372     int compCompile(CORINFO_MODULE_HANDLE classPtr,
10373                     void**                methodCodePtr,
10374                     uint32_t*             methodCodeSize,
10375                     JitFlags*             compileFlags);
10376     void compCompileFinish();
10377     int compCompileHelper(CORINFO_MODULE_HANDLE classPtr,
10378                           COMP_HANDLE           compHnd,
10379                           CORINFO_METHOD_INFO*  methodInfo,
10380                           void**                methodCodePtr,
10381                           uint32_t*             methodCodeSize,
10382                           JitFlags*             compileFlag);
10383
10384     ArenaAllocator* compGetArenaAllocator();
10385
10386     void generatePatchpointInfo();
10387
10388 #if MEASURE_MEM_ALLOC
10389     static bool s_dspMemStats; // Display per-phase memory statistics for every function
10390 #endif                         // MEASURE_MEM_ALLOC
10391
10392 #if LOOP_HOIST_STATS
10393     unsigned m_loopsConsidered;
10394     bool     m_curLoopHasHoistedExpression;
10395     unsigned m_loopsWithHoistedExpressions;
10396     unsigned m_totalHoistedExpressions;
10397
10398     void AddLoopHoistStats();
10399     void PrintPerMethodLoopHoistStats();
10400
10401     static CritSecObject s_loopHoistStatsLock; // This lock protects the data structures below.
10402     static unsigned      s_loopsConsidered;
10403     static unsigned      s_loopsWithHoistedExpressions;
10404     static unsigned      s_totalHoistedExpressions;
10405
10406     static void PrintAggregateLoopHoistStats(FILE* f);
10407 #endif // LOOP_HOIST_STATS
10408
10409 #if TRACK_ENREG_STATS
10410     class EnregisterStats
10411     {
10412     private:
10413         unsigned m_totalNumberOfVars;
10414         unsigned m_totalNumberOfStructVars;
10415         unsigned m_totalNumberOfEnregVars;
10416         unsigned m_totalNumberOfStructEnregVars;
10417
10418         unsigned m_addrExposed;
10419         unsigned m_hiddenStructArg;
10420         unsigned m_VMNeedsStackAddr;
10421         unsigned m_localField;
10422         unsigned m_blockOp;
10423         unsigned m_dontEnregStructs;
10424         unsigned m_notRegSizeStruct;
10425         unsigned m_structArg;
10426         unsigned m_lclAddrNode;
10427         unsigned m_castTakesAddr;
10428         unsigned m_storeBlkSrc;
10429         unsigned m_swizzleArg;
10430         unsigned m_blockOpRet;
10431         unsigned m_returnSpCheck;
10432         unsigned m_callSpCheck;
10433         unsigned m_simdUserForcesDep;
10434         unsigned m_liveInOutHndlr;
10435         unsigned m_depField;
10436         unsigned m_noRegVars;
10437         unsigned m_minOptsGC;
10438 #ifdef JIT32_GCENCODER
10439         unsigned m_PinningRef;
10440 #endif // JIT32_GCENCODER
10441 #if !defined(TARGET_64BIT)
10442         unsigned m_longParamField;
10443 #endif // !TARGET_64BIT
10444         unsigned m_parentExposed;
10445         unsigned m_tooConservative;
10446         unsigned m_escapeAddress;
10447         unsigned m_osrExposed;
10448         unsigned m_stressLclFld;
10449         unsigned m_dispatchRetBuf;
10450         unsigned m_wideIndir;
10451         unsigned m_stressPoisonImplicitByrefs;
10452         unsigned m_externallyVisibleImplicitly;
10453
10454     public:
10455         void RecordLocal(const LclVarDsc* varDsc);
10456         void Dump(FILE* fout) const;
10457     };
10458
10459     static EnregisterStats s_enregisterStats;
10460 #endif // TRACK_ENREG_STATS
10461
10462     bool compIsForInlining() const;
10463     bool compDonotInline();
10464
10465 #ifdef DEBUG
10466     // Get the default fill char value we randomize this value when JitStress is enabled.
10467     static unsigned char compGetJitDefaultFill(Compiler* comp);
10468
10469     const char* compLocalVarName(unsigned varNum, unsigned offs);
10470     VarName compVarName(regNumber reg, bool isFloatReg = false);
10471     const char* compFPregVarName(unsigned fpReg, bool displayVar = false);
10472     void compDspSrcLinesByNativeIP(UNATIVE_OFFSET curIP);
10473     void compDspSrcLinesByLineNum(unsigned line, bool seek = false);
10474 #endif // DEBUG
10475     const char* compRegNameForSize(regNumber reg, size_t size);
10476     const char* compRegVarName(regNumber reg, bool displayVar = false, bool isFloatReg = false);
10477
10478     //-------------------------------------------------------------------------
10479
10480     struct VarScopeListNode
10481     {
10482         VarScopeDsc*             data;
10483         VarScopeListNode*        next;
10484         static VarScopeListNode* Create(VarScopeDsc* value, CompAllocator alloc)
10485         {
10486             VarScopeListNode* node = new (alloc) VarScopeListNode;
10487             node->data             = value;
10488             node->next             = nullptr;
10489             return node;
10490         }
10491     };
10492
10493     struct VarScopeMapInfo
10494     {
10495         VarScopeListNode*       head;
10496         VarScopeListNode*       tail;
10497         static VarScopeMapInfo* Create(VarScopeListNode* node, CompAllocator alloc)
10498         {
10499             VarScopeMapInfo* info = new (alloc) VarScopeMapInfo;
10500             info->head            = node;
10501             info->tail            = node;
10502             return info;
10503         }
10504     };
10505
10506     // Max value of scope count for which we would use linear search; for larger values we would use hashtable lookup.
10507     static const unsigned MAX_LINEAR_FIND_LCL_SCOPELIST = 32;
10508
10509     typedef JitHashTable<unsigned, JitSmallPrimitiveKeyFuncs<unsigned>, VarScopeMapInfo*> VarNumToScopeDscMap;
10510
10511     // Map to keep variables' scope indexed by varNum containing it's scope dscs at the index.
10512     VarNumToScopeDscMap* compVarScopeMap;
10513
10514     VarScopeDsc* compFindLocalVar(unsigned varNum, unsigned lifeBeg, unsigned lifeEnd);
10515
10516     VarScopeDsc* compFindLocalVar(unsigned varNum, unsigned offs);
10517
10518     VarScopeDsc* compFindLocalVarLinear(unsigned varNum, unsigned offs);
10519
10520     void compInitVarScopeMap();
10521
10522     VarScopeDsc** compEnterScopeList; // List has the offsets where variables
10523                                       // enter scope, sorted by instr offset
10524     unsigned compNextEnterScope;
10525
10526     VarScopeDsc** compExitScopeList; // List has the offsets where variables
10527                                      // go out of scope, sorted by instr offset
10528     unsigned compNextExitScope;
10529
10530     void compInitScopeLists();
10531
10532     void compResetScopeLists();
10533
10534     VarScopeDsc* compGetNextEnterScope(unsigned offs, bool scan = false);
10535
10536     VarScopeDsc* compGetNextExitScope(unsigned offs, bool scan = false);
10537
10538     void compProcessScopesUntil(unsigned   offset,
10539                                 VARSET_TP* inScope,
10540                                 void (Compiler::*enterScopeFn)(VARSET_TP* inScope, VarScopeDsc*),
10541                                 void (Compiler::*exitScopeFn)(VARSET_TP* inScope, VarScopeDsc*));
10542
10543 #ifdef DEBUG
10544     void compDispScopeLists();
10545 #endif // DEBUG
10546
10547     bool compIsProfilerHookNeeded() const;
10548
10549     //-------------------------------------------------------------------------
10550     /*               Statistical Data Gathering                               */
10551
10552     void compJitStats(); // call this function and enable
10553                          // various ifdef's below for statistical data
10554
10555 #if CALL_ARG_STATS
10556     void        compCallArgStats();
10557     static void compDispCallArgStats(FILE* fout);
10558 #endif
10559
10560     //-------------------------------------------------------------------------
10561
10562 protected:
10563 #ifdef DEBUG
10564     bool skipMethod();
10565 #endif
10566
10567     ArenaAllocator* compArenaAllocator;
10568
10569 public:
10570     void compFunctionTraceStart();
10571     void compFunctionTraceEnd(void* methodCodePtr, ULONG methodCodeSize, bool isNYI);
10572
10573 protected:
10574     size_t compMaxUncheckedOffsetForNullObject;
10575
10576     void compInitOptions(JitFlags* compileFlags);
10577
10578     void compSetProcessor();
10579     void compInitDebuggingInfo();
10580     void compSetOptimizationLevel();
10581 #if defined(TARGET_ARMARCH) || defined(TARGET_RISCV64)
10582     bool compRsvdRegCheck(FrameLayoutState curState);
10583 #endif
10584     void compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFlags* compileFlags);
10585
10586     // Clear annotations produced during optimizations; to be used between iterations when repeating opts.
10587     void ResetOptAnnotations();
10588
10589     // Regenerate loop descriptors; to be used between iterations when repeating opts.
10590     void RecomputeLoopInfo();
10591
10592 #ifdef PROFILING_SUPPORTED
10593     // Data required for generating profiler Enter/Leave/TailCall hooks
10594
10595     bool  compProfilerHookNeeded; // Whether profiler Enter/Leave/TailCall hook needs to be generated for the method
10596     void* compProfilerMethHnd;    // Profiler handle of the method being compiled. Passed as param to ELT callbacks
10597     bool  compProfilerMethHndIndirected; // Whether compProfilerHandle is pointer to the handle or is an actual handle
10598 #endif
10599
10600 public:
10601     // Assumes called as part of process shutdown; does any compiler-specific work associated with that.
10602     static void ProcessShutdownWork(ICorStaticInfo* statInfo);
10603
10604     CompAllocator getAllocator(CompMemKind cmk = CMK_Generic)
10605     {
10606         return CompAllocator(compArenaAllocator, cmk);
10607     }
10608
10609     CompAllocator getAllocatorGC()
10610     {
10611         return getAllocator(CMK_GC);
10612     }
10613
10614     CompAllocator getAllocatorLoopHoist()
10615     {
10616         return getAllocator(CMK_LoopHoist);
10617     }
10618
10619 #ifdef DEBUG
10620     CompAllocator getAllocatorDebugOnly()
10621     {
10622         return getAllocator(CMK_DebugOnly);
10623     }
10624 #endif // DEBUG
10625
10626     /*
10627     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10628     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10629     XX                                                                           XX
10630     XX                           IL verification stuff                           XX
10631     XX                                                                           XX
10632     XX                                                                           XX
10633     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10634     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10635     */
10636
10637 public:
10638     EntryState verCurrentState;
10639
10640     void verInitBBEntryState(BasicBlock* block, EntryState* currentState);
10641
10642     void verInitCurrentState();
10643     void verResetCurrentState(BasicBlock* block, EntryState* currentState);
10644
10645     void verConvertBBToThrowVerificationException(BasicBlock* block DEBUGARG(bool logMsg));
10646     void verHandleVerificationFailure(BasicBlock* block DEBUGARG(bool logMsg));
10647     typeInfo verMakeTypeInfoForLocal(unsigned lclNum);
10648     typeInfo verMakeTypeInfo(CORINFO_CLASS_HANDLE clsHnd); // converts from jit type representation to typeInfo
10649     typeInfo verMakeTypeInfo(CorInfoType          ciType,
10650                              CORINFO_CLASS_HANDLE clsHnd); // converts from jit type representation to typeInfo
10651
10652     typeInfo verParseArgSigToTypeInfo(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args);
10653
10654     bool verCheckTailCallConstraint(OPCODE                  opcode,
10655                                     CORINFO_RESOLVED_TOKEN* pResolvedToken,
10656                                     CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken);
10657
10658 #ifdef DEBUG
10659
10660     // One line log function. Default level is 0. Increasing it gives you
10661     // more log information
10662
10663     // levels are currently unused: #define JITDUMP(level,...)                     ();
10664     void JitLogEE(unsigned level, const char* fmt, ...);
10665
10666     bool compDebugBreak;
10667
10668     bool compJitHaltMethod();
10669
10670     void dumpRegMask(regMaskTP regs) const;
10671
10672 #endif
10673
10674     /*
10675     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10676     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10677     XX                                                                           XX
10678     XX                   GS Security checks for unsafe buffers                   XX
10679     XX                                                                           XX
10680     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10681     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10682     */
10683 public:
10684     struct ShadowParamVarInfo
10685     {
10686         FixedBitVect* assignGroup; // the closure set of variables whose values depend on each other
10687         unsigned      shadowCopy;  // Lcl var num, if not valid set to BAD_VAR_NUM
10688
10689         static bool mayNeedShadowCopy(LclVarDsc* varDsc)
10690         {
10691 #if defined(TARGET_AMD64)
10692             // GS cookie logic to create shadow slots, create trees to copy reg args to shadow
10693             // slots and update all trees to refer to shadow slots is done immediately after
10694             // fgMorph().  Lsra could potentially mark a param as DoNotEnregister after JIT determines
10695             // not to shadow a parameter.  Also, LSRA could potentially spill a param which is passed
10696             // in register. Therefore, conservatively all params may need a shadow copy.  Note that
10697             // GS cookie logic further checks whether the param is a ptr or an unsafe buffer before
10698             // creating a shadow slot even though this routine returns true.
10699             //
10700             // TODO-AMD64-CQ: Revisit this conservative approach as it could create more shadow slots than
10701             // required. There are two cases under which a reg arg could potentially be used from its
10702             // home location:
10703             //   a) LSRA marks it as DoNotEnregister (see LinearScan::identifyCandidates())
10704             //   b) LSRA spills it
10705             //
10706             // Possible solution to address case (a)
10707             //   - The conditions under which LSRA marks a varDsc as DoNotEnregister could be checked
10708             //     in this routine.  Note that live out of exception handler is something we may not be
10709             //     able to do it here since GS cookie logic is invoked ahead of liveness computation.
10710             //     Therefore, for methods with exception handling and need GS cookie check we might have
10711             //     to take conservative approach.
10712             //
10713             // Possible solution to address case (b)
10714             //   - Whenever a parameter passed in an argument register needs to be spilled by LSRA, we
10715             //     create a new spill temp if the method needs GS cookie check.
10716             return varDsc->lvIsParam;
10717 #else // !defined(TARGET_AMD64)
10718             return varDsc->lvIsParam && !varDsc->lvIsRegArg;
10719 #endif
10720         }
10721
10722 #ifdef DEBUG
10723         void Print()
10724         {
10725             printf("assignGroup [%p]; shadowCopy: [%d];\n", assignGroup, shadowCopy);
10726         }
10727 #endif
10728     };
10729
10730     GSCookie*           gsGlobalSecurityCookieAddr; // Address of global cookie for unsafe buffer checks
10731     GSCookie            gsGlobalSecurityCookieVal;  // Value of global cookie if addr is NULL
10732     ShadowParamVarInfo* gsShadowVarInfo;            // Table used by shadow param analysis code
10733
10734     PhaseStatus gsPhase();
10735     void        gsGSChecksInitCookie();   // Grabs cookie variable
10736     void        gsCopyShadowParams();     // Identify vulnerable params and create dhadow copies
10737     bool        gsFindVulnerableParams(); // Shadow param analysis code
10738     void        gsParamsToShadows();      // Insert copy code and replave param uses by shadow
10739
10740     static fgWalkPreFn gsMarkPtrsAndAssignGroups; // Shadow param analysis tree-walk
10741     static fgWalkPreFn gsReplaceShadowParams;     // Shadow param replacement tree-walk
10742
10743 #define DEFAULT_MAX_INLINE_SIZE 100 // Methods with >  DEFAULT_MAX_INLINE_SIZE IL bytes will never be inlined.
10744                                     // This can be overwritten by setting DOTNET_JITInlineSize env variable.
10745
10746 #define DEFAULT_MAX_INLINE_DEPTH 20 // Methods at more than this level deep will not be inlined
10747
10748 #define DEFAULT_MAX_FORCE_INLINE_DEPTH 1 // Methods at more than this level deep will not be force inlined
10749
10750 #define DEFAULT_MAX_LOCALLOC_TO_LOCAL_SIZE 32 // fixed locallocs of this size or smaller will convert to local buffers
10751
10752 private:
10753 #ifdef FEATURE_JIT_METHOD_PERF
10754     JitTimer*                  pCompJitTimer;         // Timer data structure (by phases) for current compilation.
10755     static CompTimeSummaryInfo s_compJitTimerSummary; // Summary of the Timer information for the whole run.
10756
10757     static LPCWSTR JitTimeLogCsv();        // Retrieve the file name for CSV from ConfigDWORD.
10758     static LPCWSTR compJitTimeLogFilename; // If a log file for JIT time is desired, filename to write it to.
10759 #endif
10760     void BeginPhase(Phases phase); // Indicate the start of the given phase.
10761     void EndPhase(Phases phase);   // Indicate the end of the given phase.
10762
10763 #if MEASURE_CLRAPI_CALLS
10764     // Thin wrappers that call into JitTimer (if present).
10765     inline void CLRApiCallEnter(unsigned apix);
10766     inline void CLRApiCallLeave(unsigned apix);
10767
10768 public:
10769     inline void CLR_API_Enter(API_ICorJitInfo_Names ename);
10770     inline void CLR_API_Leave(API_ICorJitInfo_Names ename);
10771
10772 private:
10773 #endif
10774
10775 #if defined(DEBUG) || defined(INLINE_DATA)
10776     // These variables are associated with maintaining SQM data about compile time.
10777     unsigned __int64 m_compCyclesAtEndOfInlining; // The thread-virtualized cycle count at the end of the inlining phase
10778                                                   // in the current compilation.
10779     unsigned __int64 m_compCycles;                // Net cycle count for current compilation
10780     DWORD m_compTickCountAtEndOfInlining; // The result of GetTickCount() (# ms since some epoch marker) at the end of
10781                                           // the inlining phase in the current compilation.
10782 #endif                                    // defined(DEBUG) || defined(INLINE_DATA)
10783
10784     // Records the SQM-relevant (cycles and tick count).  Should be called after inlining is complete.
10785     // (We do this after inlining because this marks the last point at which the JIT is likely to cause
10786     // type-loading and class initialization).
10787     void RecordStateAtEndOfInlining();
10788     // Assumes being called at the end of compilation.  Update the SQM state.
10789     void RecordStateAtEndOfCompilation();
10790
10791 public:
10792 #if FUNC_INFO_LOGGING
10793     static LPCWSTR compJitFuncInfoFilename; // If a log file for per-function information is required, this is the
10794                                             // filename to write it to.
10795     static FILE* compJitFuncInfoFile;       // And this is the actual FILE* to write to.
10796 #endif                                      // FUNC_INFO_LOGGING
10797
10798     Compiler* prevCompiler; // Previous compiler on stack for TLS Compiler* linked list for reentrant compilers.
10799
10800 #if MEASURE_NOWAY
10801     void RecordNowayAssert(const char* filename, unsigned line, const char* condStr);
10802 #endif // MEASURE_NOWAY
10803
10804 #ifndef FEATURE_TRACELOGGING
10805     // Should we actually fire the noway assert body and the exception handler?
10806     bool compShouldThrowOnNoway();
10807 #else  // FEATURE_TRACELOGGING
10808     // Should we actually fire the noway assert body and the exception handler?
10809     bool compShouldThrowOnNoway(const char* filename, unsigned line);
10810
10811     // Telemetry instance to use per method compilation.
10812     JitTelemetry compJitTelemetry;
10813
10814     // Get common parameters that have to be logged with most telemetry data.
10815     void compGetTelemetryDefaults(const char** assemblyName,
10816                                   const char** scopeName,
10817                                   const char** methodName,
10818                                   unsigned*    methodHash);
10819 #endif // !FEATURE_TRACELOGGING
10820
10821 #ifdef DEBUG
10822 private:
10823     NodeToTestDataMap* m_nodeTestData;
10824
10825     static const unsigned FIRST_LOOP_HOIST_CSE_CLASS = 1000;
10826     unsigned              m_loopHoistCSEClass; // LoopHoist test annotations turn into CSE requirements; we
10827                                                // label them with CSE Class #'s starting at FIRST_LOOP_HOIST_CSE_CLASS.
10828                                                // Current kept in this.
10829 public:
10830     NodeToTestDataMap* GetNodeTestData()
10831     {
10832         Compiler* compRoot = impInlineRoot();
10833         if (compRoot->m_nodeTestData == nullptr)
10834         {
10835             compRoot->m_nodeTestData = new (getAllocatorDebugOnly()) NodeToTestDataMap(getAllocatorDebugOnly());
10836         }
10837         return compRoot->m_nodeTestData;
10838     }
10839
10840     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, int> NodeToIntMap;
10841
10842     // Returns the set (i.e., the domain of the result map) of nodes that are keys in m_nodeTestData, and
10843     // currently occur in the AST graph.
10844     NodeToIntMap* FindReachableNodesInNodeTestData();
10845
10846     // Node "from" is being eliminated, and being replaced by node "to".  If "from" had any associated
10847     // test data, associate that data with "to".
10848     void TransferTestDataToNode(GenTree* from, GenTree* to);
10849
10850     // These are the methods that test that the various conditions implied by the
10851     // test attributes are satisfied.
10852     void JitTestCheckSSA(); // SSA builder tests.
10853     void JitTestCheckVN();  // Value numbering tests.
10854 #endif                      // DEBUG
10855
10856     FieldSeqStore* m_fieldSeqStore;
10857
10858     FieldSeqStore* GetFieldSeqStore()
10859     {
10860         Compiler* compRoot = impInlineRoot();
10861         if (compRoot->m_fieldSeqStore == nullptr)
10862         {
10863             CompAllocator alloc       = getAllocator(CMK_FieldSeqStore);
10864             compRoot->m_fieldSeqStore = new (alloc) FieldSeqStore(alloc);
10865         }
10866         return compRoot->m_fieldSeqStore;
10867     }
10868
10869     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, unsigned> NodeToUnsignedMap;
10870
10871     NodeToUnsignedMap* m_memorySsaMap[MemoryKindCount];
10872
10873     // In some cases, we want to assign intermediate SSA #'s to memory states, and know what nodes create those memory
10874     // states. (We do this for try blocks, where, if the try block doesn't do a call that loses track of the memory
10875     // state, all the possible memory states are possible initial states of the corresponding catch block(s).)
10876     NodeToUnsignedMap* GetMemorySsaMap(MemoryKind memoryKind)
10877     {
10878         if (memoryKind == GcHeap && byrefStatesMatchGcHeapStates)
10879         {
10880             // Use the same map for GCHeap and ByrefExposed when their states match.
10881             memoryKind = ByrefExposed;
10882         }
10883
10884         assert(memoryKind < MemoryKindCount);
10885         Compiler* compRoot = impInlineRoot();
10886         if (compRoot->m_memorySsaMap[memoryKind] == nullptr)
10887         {
10888             // Create a CompAllocator that labels sub-structure with CMK_MemorySsaMap, and use that for allocation.
10889             CompAllocator ialloc(getAllocator(CMK_MemorySsaMap));
10890             compRoot->m_memorySsaMap[memoryKind] = new (ialloc) NodeToUnsignedMap(ialloc);
10891         }
10892         return compRoot->m_memorySsaMap[memoryKind];
10893     }
10894
10895     // The Refany type is the only struct type whose structure is implicitly assumed by IL.  We need its fields.
10896     CORINFO_CLASS_HANDLE m_refAnyClass;
10897     CORINFO_FIELD_HANDLE GetRefanyDataField()
10898     {
10899         if (m_refAnyClass == nullptr)
10900         {
10901             m_refAnyClass = info.compCompHnd->getBuiltinClass(CLASSID_TYPED_BYREF);
10902         }
10903         return info.compCompHnd->getFieldInClass(m_refAnyClass, 0);
10904     }
10905     CORINFO_FIELD_HANDLE GetRefanyTypeField()
10906     {
10907         if (m_refAnyClass == nullptr)
10908         {
10909             m_refAnyClass = info.compCompHnd->getBuiltinClass(CLASSID_TYPED_BYREF);
10910         }
10911         return info.compCompHnd->getFieldInClass(m_refAnyClass, 1);
10912     }
10913
10914 #if VARSET_COUNTOPS
10915     static BitSetSupport::BitSetOpCounter m_varsetOpCounter;
10916 #endif
10917 #if ALLVARSET_COUNTOPS
10918     static BitSetSupport::BitSetOpCounter m_allvarsetOpCounter;
10919 #endif
10920
10921     static HelperCallProperties s_helperCallProperties;
10922
10923 #ifdef UNIX_AMD64_ABI
10924     static var_types GetTypeFromClassificationAndSizes(SystemVClassificationType classType, int size);
10925     static var_types GetEightByteType(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc,
10926                                       unsigned                                                   slotNum);
10927
10928     static void GetStructTypeOffset(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc,
10929                                     var_types*                                                 type0,
10930                                     var_types*                                                 type1,
10931                                     unsigned __int8*                                           offset0,
10932                                     unsigned __int8*                                           offset1);
10933
10934     void GetStructTypeOffset(CORINFO_CLASS_HANDLE typeHnd,
10935                              var_types*           type0,
10936                              var_types*           type1,
10937                              unsigned __int8*     offset0,
10938                              unsigned __int8*     offset1);
10939
10940 #endif // defined(UNIX_AMD64_ABI)
10941
10942     void fgMorphMultiregStructArgs(GenTreeCall* call);
10943     GenTree* fgMorphMultiregStructArg(CallArg* arg);
10944
10945     bool killGCRefs(GenTree* tree);
10946
10947 #if defined(TARGET_AMD64)
10948 private:
10949     // The following are for initializing register allocator "constants" defined in targetamd64.h
10950     // that now depend upon runtime ISA information, e.g., the presence of AVX512F/VL, which increases
10951     // the number of SIMD (xmm, ymm, and zmm) registers from 16 to 32.
10952     // As only 64-bit xarch has the capability to have the additional registers, we limit the changes
10953     // to TARGET_AMD64 only.
10954     //
10955     // Users of these values need to define four accessor functions:
10956     //
10957     //    regMaskTP get_RBM_ALLFLOAT();
10958     //    regMaskTP get_RBM_FLT_CALLEE_TRASH();
10959     //    unsigned get_CNT_CALLEE_TRASH_FLOAT();
10960     //    unsigned get_AVAILABLE_REG_COUNT();
10961     //
10962     // which return the values of these variables.
10963     //
10964     // This was done to avoid polluting all `targetXXX.h` macro definitions with a compiler parameter, where only
10965     // TARGET_AMD64 requires one.
10966     //
10967     regMaskTP rbmAllFloat;
10968     regMaskTP rbmFltCalleeTrash;
10969     unsigned  cntCalleeTrashFloat;
10970
10971 public:
10972     FORCEINLINE regMaskTP get_RBM_ALLFLOAT() const
10973     {
10974         return this->rbmAllFloat;
10975     }
10976     FORCEINLINE regMaskTP get_RBM_FLT_CALLEE_TRASH() const
10977     {
10978         return this->rbmFltCalleeTrash;
10979     }
10980     FORCEINLINE unsigned get_CNT_CALLEE_TRASH_FLOAT() const
10981     {
10982         return this->cntCalleeTrashFloat;
10983     }
10984
10985 #endif // TARGET_AMD64
10986
10987 #if defined(TARGET_XARCH)
10988 private:
10989     // The following are for initializing register allocator "constants" defined in targetamd64.h
10990     // that now depend upon runtime ISA information, e.g., the presence of AVX512F/VL, which adds
10991     // 8 mask registers for use.
10992     //
10993     // Users of these values need to define four accessor functions:
10994     //
10995     //    regMaskTP get_RBM_ALLMASK();
10996     //    regMaskTP get_RBM_MSK_CALLEE_TRASH();
10997     //    unsigned get_CNT_CALLEE_TRASH_MASK();
10998     //    unsigned get_AVAILABLE_REG_COUNT();
10999     //
11000     // which return the values of these variables.
11001     //
11002     // This was done to avoid polluting all `targetXXX.h` macro definitions with a compiler parameter, where only
11003     // TARGET_XARCH requires one.
11004     //
11005     regMaskTP rbmAllMask;
11006     regMaskTP rbmMskCalleeTrash;
11007     unsigned  cntCalleeTrashMask;
11008     regMaskTP varTypeCalleeTrashRegs[TYP_COUNT];
11009
11010 public:
11011     FORCEINLINE regMaskTP get_RBM_ALLMASK() const
11012     {
11013         return this->rbmAllMask;
11014     }
11015     FORCEINLINE regMaskTP get_RBM_MSK_CALLEE_TRASH() const
11016     {
11017         return this->rbmMskCalleeTrash;
11018     }
11019     FORCEINLINE unsigned get_CNT_CALLEE_TRASH_MASK() const
11020     {
11021         return this->cntCalleeTrashMask;
11022     }
11023 #endif // TARGET_XARCH
11024
11025 }; // end of class Compiler
11026
11027 //---------------------------------------------------------------------------------------------------------------------
11028 // GenTreeVisitor: a flexible tree walker implemented using the curiously-recurring-template pattern.
11029 //
11030 // This class implements a configurable walker for IR trees. There are five configuration options (defaults values are
11031 // shown in parentheses):
11032 //
11033 // - ComputeStack (false): when true, the walker will push each node onto the `m_ancestors` stack. "Ancestors" is a bit
11034 //                         of a misnomer, as the first entry will always be the current node.
11035 //
11036 // - DoPreOrder (false): when true, the walker will invoke `TVisitor::PreOrderVisit` with the current node as an
11037 //                       argument before visiting the node's operands.
11038 //
11039 // - DoPostOrder (false): when true, the walker will invoke `TVisitor::PostOrderVisit` with the current node as an
11040 //                        argument after visiting the node's operands.
11041 //
11042 // - DoLclVarsOnly (false): when true, the walker will only invoke `TVisitor::PreOrderVisit` for lclVar nodes.
11043 //                          `DoPreOrder` must be true if this option is true.
11044 //
11045 // - UseExecutionOrder (false): when true, then walker will visit a node's operands in execution order (e.g. if a
11046 //                              binary operator has the `GTF_REVERSE_OPS` flag set, the second operand will be
11047 //                              visited before the first).
11048 //
11049 // At least one of `DoPreOrder` and `DoPostOrder` must be specified.
11050 //
11051 // A simple pre-order visitor might look something like the following:
11052 //
11053 //     class CountingVisitor final : public GenTreeVisitor<CountingVisitor>
11054 //     {
11055 //     public:
11056 //         enum
11057 //         {
11058 //             DoPreOrder = true
11059 //         };
11060 //
11061 //         unsigned m_count;
11062 //
11063 //         CountingVisitor(Compiler* compiler)
11064 //             : GenTreeVisitor<CountingVisitor>(compiler), m_count(0)
11065 //         {
11066 //         }
11067 //
11068 //         Compiler::fgWalkResult PreOrderVisit(GenTree* node)
11069 //         {
11070 //             m_count++;
11071 //         }
11072 //     };
11073 //
11074 // This visitor would then be used like so:
11075 //
11076 //     CountingVisitor countingVisitor(compiler);
11077 //     countingVisitor.WalkTree(root);
11078 //
11079 template <typename TVisitor>
11080 class GenTreeVisitor
11081 {
11082 protected:
11083     typedef Compiler::fgWalkResult fgWalkResult;
11084
11085     enum
11086     {
11087         ComputeStack      = false,
11088         DoPreOrder        = false,
11089         DoPostOrder       = false,
11090         DoLclVarsOnly     = false,
11091         UseExecutionOrder = false,
11092     };
11093
11094     Compiler*            m_compiler;
11095     ArrayStack<GenTree*> m_ancestors;
11096
11097     GenTreeVisitor(Compiler* compiler) : m_compiler(compiler), m_ancestors(compiler->getAllocator(CMK_ArrayStack))
11098     {
11099         assert(compiler != nullptr);
11100
11101         static_assert_no_msg(TVisitor::DoPreOrder || TVisitor::DoPostOrder);
11102         static_assert_no_msg(!TVisitor::DoLclVarsOnly || TVisitor::DoPreOrder);
11103     }
11104
11105     fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
11106     {
11107         return fgWalkResult::WALK_CONTINUE;
11108     }
11109
11110     fgWalkResult PostOrderVisit(GenTree** use, GenTree* user)
11111     {
11112         return fgWalkResult::WALK_CONTINUE;
11113     }
11114
11115 public:
11116     fgWalkResult WalkTree(GenTree** use, GenTree* user)
11117     {
11118         assert(use != nullptr);
11119
11120         GenTree* node = *use;
11121
11122         if (TVisitor::ComputeStack)
11123         {
11124             m_ancestors.Push(node);
11125         }
11126
11127         fgWalkResult result = fgWalkResult::WALK_CONTINUE;
11128         if (TVisitor::DoPreOrder && !TVisitor::DoLclVarsOnly)
11129         {
11130             result = reinterpret_cast<TVisitor*>(this)->PreOrderVisit(use, user);
11131             if (result == fgWalkResult::WALK_ABORT)
11132             {
11133                 return result;
11134             }
11135
11136             node = *use;
11137             if ((node == nullptr) || (result == fgWalkResult::WALK_SKIP_SUBTREES))
11138             {
11139                 goto DONE;
11140             }
11141         }
11142
11143         switch (node->OperGet())
11144         {
11145             // Leaf lclVars
11146             case GT_LCL_VAR:
11147             case GT_LCL_FLD:
11148             case GT_LCL_ADDR:
11149                 if (TVisitor::DoLclVarsOnly)
11150                 {
11151                     result = reinterpret_cast<TVisitor*>(this)->PreOrderVisit(use, user);
11152                     if (result == fgWalkResult::WALK_ABORT)
11153                     {
11154                         return result;
11155                     }
11156                 }
11157                 FALLTHROUGH;
11158
11159             // Leaf nodes
11160             case GT_CATCH_ARG:
11161             case GT_LABEL:
11162             case GT_FTN_ADDR:
11163             case GT_RET_EXPR:
11164             case GT_CNS_INT:
11165             case GT_CNS_LNG:
11166             case GT_CNS_DBL:
11167             case GT_CNS_STR:
11168             case GT_CNS_VEC:
11169             case GT_MEMORYBARRIER:
11170             case GT_JMP:
11171             case GT_JCC:
11172             case GT_SETCC:
11173             case GT_NO_OP:
11174             case GT_START_NONGC:
11175             case GT_START_PREEMPTGC:
11176             case GT_PROF_HOOK:
11177 #if !defined(FEATURE_EH_FUNCLETS)
11178             case GT_END_LFIN:
11179 #endif // !FEATURE_EH_FUNCLETS
11180             case GT_PHI_ARG:
11181             case GT_JMPTABLE:
11182             case GT_CLS_VAR_ADDR:
11183             case GT_PHYSREG:
11184             case GT_EMITNOP:
11185             case GT_PINVOKE_PROLOG:
11186             case GT_PINVOKE_EPILOG:
11187             case GT_IL_OFFSET:
11188                 break;
11189
11190             // Lclvar unary operators
11191             case GT_STORE_LCL_VAR:
11192             case GT_STORE_LCL_FLD:
11193                 if (TVisitor::DoLclVarsOnly)
11194                 {
11195                     result = reinterpret_cast<TVisitor*>(this)->PreOrderVisit(use, user);
11196                     if (result == fgWalkResult::WALK_ABORT)
11197                     {
11198                         return result;
11199                     }
11200                 }
11201                 FALLTHROUGH;
11202
11203             // Standard unary operators
11204             case GT_NOT:
11205             case GT_NEG:
11206             case GT_BSWAP:
11207             case GT_BSWAP16:
11208             case GT_COPY:
11209             case GT_RELOAD:
11210             case GT_ARR_LENGTH:
11211             case GT_MDARR_LENGTH:
11212             case GT_MDARR_LOWER_BOUND:
11213             case GT_CAST:
11214             case GT_BITCAST:
11215             case GT_CKFINITE:
11216             case GT_LCLHEAP:
11217             case GT_IND:
11218             case GT_BLK:
11219             case GT_BOX:
11220             case GT_ALLOCOBJ:
11221             case GT_INIT_VAL:
11222             case GT_JTRUE:
11223             case GT_SWITCH:
11224             case GT_NULLCHECK:
11225             case GT_PUTARG_REG:
11226             case GT_PUTARG_STK:
11227             case GT_RETURNTRAP:
11228             case GT_NOP:
11229             case GT_FIELD_ADDR:
11230             case GT_RETURN:
11231             case GT_RETFILT:
11232             case GT_RUNTIMELOOKUP:
11233             case GT_ARR_ADDR:
11234             case GT_KEEPALIVE:
11235             case GT_INC_SATURATE:
11236             {
11237                 GenTreeUnOp* const unOp = node->AsUnOp();
11238                 if (unOp->gtOp1 != nullptr)
11239                 {
11240                     result = WalkTree(&unOp->gtOp1, unOp);
11241                     if (result == fgWalkResult::WALK_ABORT)
11242                     {
11243                         return result;
11244                     }
11245                 }
11246                 break;
11247             }
11248
11249             // Special nodes
11250             case GT_PHI:
11251                 for (GenTreePhi::Use& use : node->AsPhi()->Uses())
11252                 {
11253                     result = WalkTree(&use.NodeRef(), node);
11254                     if (result == fgWalkResult::WALK_ABORT)
11255                     {
11256                         return result;
11257                     }
11258                 }
11259                 break;
11260
11261             case GT_FIELD_LIST:
11262                 for (GenTreeFieldList::Use& use : node->AsFieldList()->Uses())
11263                 {
11264                     result = WalkTree(&use.NodeRef(), node);
11265                     if (result == fgWalkResult::WALK_ABORT)
11266                     {
11267                         return result;
11268                     }
11269                 }
11270                 break;
11271
11272             case GT_CMPXCHG:
11273             {
11274                 GenTreeCmpXchg* const cmpXchg = node->AsCmpXchg();
11275
11276                 result = WalkTree(&cmpXchg->gtOpLocation, cmpXchg);
11277                 if (result == fgWalkResult::WALK_ABORT)
11278                 {
11279                     return result;
11280                 }
11281                 result = WalkTree(&cmpXchg->gtOpValue, cmpXchg);
11282                 if (result == fgWalkResult::WALK_ABORT)
11283                 {
11284                     return result;
11285                 }
11286                 result = WalkTree(&cmpXchg->gtOpComparand, cmpXchg);
11287                 if (result == fgWalkResult::WALK_ABORT)
11288                 {
11289                     return result;
11290                 }
11291                 break;
11292             }
11293
11294             case GT_ARR_ELEM:
11295             {
11296                 GenTreeArrElem* const arrElem = node->AsArrElem();
11297
11298                 result = WalkTree(&arrElem->gtArrObj, arrElem);
11299                 if (result == fgWalkResult::WALK_ABORT)
11300                 {
11301                     return result;
11302                 }
11303
11304                 const unsigned rank = arrElem->gtArrRank;
11305                 for (unsigned dim = 0; dim < rank; dim++)
11306                 {
11307                     result = WalkTree(&arrElem->gtArrInds[dim], arrElem);
11308                     if (result == fgWalkResult::WALK_ABORT)
11309                     {
11310                         return result;
11311                     }
11312                 }
11313                 break;
11314             }
11315
11316             case GT_STORE_DYN_BLK:
11317             {
11318                 GenTreeStoreDynBlk* const dynBlock = node->AsStoreDynBlk();
11319
11320                 result = WalkTree(&dynBlock->gtOp1, dynBlock);
11321                 if (result == fgWalkResult::WALK_ABORT)
11322                 {
11323                     return result;
11324                 }
11325                 result = WalkTree(&dynBlock->gtOp2, dynBlock);
11326                 if (result == fgWalkResult::WALK_ABORT)
11327                 {
11328                     return result;
11329                 }
11330                 result = WalkTree(&dynBlock->gtDynamicSize, dynBlock);
11331                 if (result == fgWalkResult::WALK_ABORT)
11332                 {
11333                     return result;
11334                 }
11335                 break;
11336             }
11337
11338             case GT_CALL:
11339             {
11340                 GenTreeCall* const call = node->AsCall();
11341
11342                 for (CallArg& arg : call->gtArgs.EarlyArgs())
11343                 {
11344                     result = WalkTree(&arg.EarlyNodeRef(), call);
11345                     if (result == fgWalkResult::WALK_ABORT)
11346                     {
11347                         return result;
11348                     }
11349                 }
11350
11351                 for (CallArg& arg : call->gtArgs.LateArgs())
11352                 {
11353                     result = WalkTree(&arg.LateNodeRef(), call);
11354                     if (result == fgWalkResult::WALK_ABORT)
11355                     {
11356                         return result;
11357                     }
11358                 }
11359
11360                 if (call->gtCallType == CT_INDIRECT)
11361                 {
11362                     if (call->gtCallCookie != nullptr)
11363                     {
11364                         result = WalkTree(&call->gtCallCookie, call);
11365                         if (result == fgWalkResult::WALK_ABORT)
11366                         {
11367                             return result;
11368                         }
11369                     }
11370
11371                     result = WalkTree(&call->gtCallAddr, call);
11372                     if (result == fgWalkResult::WALK_ABORT)
11373                     {
11374                         return result;
11375                     }
11376                 }
11377
11378                 if (call->gtControlExpr != nullptr)
11379                 {
11380                     result = WalkTree(&call->gtControlExpr, call);
11381                     if (result == fgWalkResult::WALK_ABORT)
11382                     {
11383                         return result;
11384                     }
11385                 }
11386
11387                 break;
11388             }
11389
11390 #if defined(FEATURE_HW_INTRINSICS)
11391             case GT_HWINTRINSIC:
11392                 if (TVisitor::UseExecutionOrder && node->IsReverseOp())
11393                 {
11394                     assert(node->AsMultiOp()->GetOperandCount() == 2);
11395                     result = WalkTree(&node->AsMultiOp()->Op(2), node);
11396                     if (result == fgWalkResult::WALK_ABORT)
11397                     {
11398                         return result;
11399                     }
11400                     result = WalkTree(&node->AsMultiOp()->Op(1), node);
11401                     if (result == fgWalkResult::WALK_ABORT)
11402                     {
11403                         return result;
11404                     }
11405                 }
11406                 else
11407                 {
11408                     for (GenTree** use : node->AsMultiOp()->UseEdges())
11409                     {
11410                         result = WalkTree(use, node);
11411                         if (result == fgWalkResult::WALK_ABORT)
11412                         {
11413                             return result;
11414                         }
11415                     }
11416                 }
11417                 break;
11418 #endif // defined(FEATURE_HW_INTRINSICS)
11419
11420             case GT_SELECT:
11421             {
11422                 GenTreeConditional* const conditional = node->AsConditional();
11423
11424                 result = WalkTree(&conditional->gtCond, conditional);
11425                 if (result == fgWalkResult::WALK_ABORT)
11426                 {
11427                     return result;
11428                 }
11429                 result = WalkTree(&conditional->gtOp1, conditional);
11430                 if (result == fgWalkResult::WALK_ABORT)
11431                 {
11432                     return result;
11433                 }
11434                 result = WalkTree(&conditional->gtOp2, conditional);
11435                 if (result == fgWalkResult::WALK_ABORT)
11436                 {
11437                     return result;
11438                 }
11439                 break;
11440             }
11441
11442             // Binary nodes
11443             default:
11444             {
11445                 assert(node->OperIsBinary());
11446
11447                 GenTreeOp* const op = node->AsOp();
11448
11449                 GenTree** op1Use = &op->gtOp1;
11450                 GenTree** op2Use = &op->gtOp2;
11451
11452                 if (TVisitor::UseExecutionOrder && node->IsReverseOp())
11453                 {
11454                     std::swap(op1Use, op2Use);
11455                 }
11456
11457                 if (*op1Use != nullptr)
11458                 {
11459                     result = WalkTree(op1Use, op);
11460                     if (result == fgWalkResult::WALK_ABORT)
11461                     {
11462                         return result;
11463                     }
11464                 }
11465
11466                 if (*op2Use != nullptr)
11467                 {
11468                     result = WalkTree(op2Use, op);
11469                     if (result == fgWalkResult::WALK_ABORT)
11470                     {
11471                         return result;
11472                     }
11473                 }
11474                 break;
11475             }
11476         }
11477
11478     DONE:
11479         // Finally, visit the current node
11480         if (TVisitor::DoPostOrder)
11481         {
11482             result = reinterpret_cast<TVisitor*>(this)->PostOrderVisit(use, user);
11483         }
11484
11485         if (TVisitor::ComputeStack)
11486         {
11487             m_ancestors.Pop();
11488         }
11489
11490         return result;
11491     }
11492 };
11493
11494 template <bool doPreOrder, bool doPostOrder, bool doLclVarsOnly, bool useExecutionOrder>
11495 class GenericTreeWalker final
11496     : public GenTreeVisitor<GenericTreeWalker<doPreOrder, doPostOrder, doLclVarsOnly, useExecutionOrder>>
11497 {
11498 public:
11499     enum
11500     {
11501         ComputeStack      = false,
11502         DoPreOrder        = doPreOrder,
11503         DoPostOrder       = doPostOrder,
11504         DoLclVarsOnly     = doLclVarsOnly,
11505         UseExecutionOrder = useExecutionOrder,
11506     };
11507
11508 private:
11509     Compiler::fgWalkData* m_walkData;
11510
11511 public:
11512     GenericTreeWalker(Compiler::fgWalkData* walkData)
11513         : GenTreeVisitor<GenericTreeWalker<doPreOrder, doPostOrder, doLclVarsOnly, useExecutionOrder>>(
11514               walkData->compiler)
11515         , m_walkData(walkData)
11516     {
11517         assert(walkData != nullptr);
11518     }
11519
11520     Compiler::fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
11521     {
11522         m_walkData->parent = user;
11523         return m_walkData->wtprVisitorFn(use, m_walkData);
11524     }
11525
11526     Compiler::fgWalkResult PostOrderVisit(GenTree** use, GenTree* user)
11527     {
11528         m_walkData->parent = user;
11529         return m_walkData->wtpoVisitorFn(use, m_walkData);
11530     }
11531 };
11532
11533 // A dominator tree visitor implemented using the curiously-recurring-template pattern, similar to GenTreeVisitor.
11534 template <typename TVisitor>
11535 class DomTreeVisitor
11536 {
11537 protected:
11538     Compiler* const    m_compiler;
11539     DomTreeNode* const m_domTree;
11540
11541     DomTreeVisitor(Compiler* compiler, DomTreeNode* domTree) : m_compiler(compiler), m_domTree(domTree)
11542     {
11543     }
11544
11545     void Begin()
11546     {
11547     }
11548
11549     void PreOrderVisit(BasicBlock* block)
11550     {
11551     }
11552
11553     void PostOrderVisit(BasicBlock* block)
11554     {
11555     }
11556
11557     void End()
11558     {
11559     }
11560
11561 public:
11562     //------------------------------------------------------------------------
11563     // WalkTree: Walk the dominator tree, starting from fgFirstBB.
11564     //
11565     // Notes:
11566     //    This performs a non-recursive, non-allocating walk of the tree by using
11567     //    DomTreeNode's firstChild and nextSibling links to locate the children of
11568     //    a node and BasicBlock's bbIDom parent link to go back up the tree when
11569     //    no more children are left.
11570     //
11571     //    Forests are also supported, provided that all the roots are chained via
11572     //    DomTreeNode::nextSibling to fgFirstBB.
11573     //
11574     void WalkTree()
11575     {
11576         static_cast<TVisitor*>(this)->Begin();
11577
11578         for (BasicBlock *next, *block = m_compiler->fgFirstBB; block != nullptr; block = next)
11579         {
11580             static_cast<TVisitor*>(this)->PreOrderVisit(block);
11581
11582             next = m_domTree[block->bbNum].firstChild;
11583
11584             if (next != nullptr)
11585             {
11586                 assert(next->bbIDom == block);
11587                 continue;
11588             }
11589
11590             do
11591             {
11592                 static_cast<TVisitor*>(this)->PostOrderVisit(block);
11593
11594                 next = m_domTree[block->bbNum].nextSibling;
11595
11596                 if (next != nullptr)
11597                 {
11598                     assert(next->bbIDom == block->bbIDom);
11599                     break;
11600                 }
11601
11602                 block = block->bbIDom;
11603
11604             } while (block != nullptr);
11605         }
11606
11607         static_cast<TVisitor*>(this)->End();
11608     }
11609 };
11610
11611 // EHClauses: adapter class for forward iteration of the exception handling table using range-based `for`, e.g.:
11612 //    for (EHblkDsc* const ehDsc : EHClauses(compiler))
11613 //
11614 class EHClauses
11615 {
11616     EHblkDsc* m_begin;
11617     EHblkDsc* m_end;
11618
11619     // Forward iterator for the exception handling table entries. Iteration is in table order.
11620     //
11621     class iterator
11622     {
11623         EHblkDsc* m_ehDsc;
11624
11625     public:
11626         iterator(EHblkDsc* ehDsc) : m_ehDsc(ehDsc)
11627         {
11628         }
11629
11630         EHblkDsc* operator*() const
11631         {
11632             return m_ehDsc;
11633         }
11634
11635         iterator& operator++()
11636         {
11637             ++m_ehDsc;
11638             return *this;
11639         }
11640
11641         bool operator!=(const iterator& i) const
11642         {
11643             return m_ehDsc != i.m_ehDsc;
11644         }
11645     };
11646
11647 public:
11648     EHClauses(Compiler* comp) : m_begin(comp->compHndBBtab), m_end(comp->compHndBBtab + comp->compHndBBtabCount)
11649     {
11650         assert((m_begin != nullptr) || (m_begin == m_end));
11651     }
11652
11653     iterator begin() const
11654     {
11655         return iterator(m_begin);
11656     }
11657
11658     iterator end() const
11659     {
11660         return iterator(m_end);
11661     }
11662 };
11663
11664 /*
11665 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11666 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11667 XX                                                                           XX
11668 XX                   Miscellaneous Compiler stuff                            XX
11669 XX                                                                           XX
11670 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11671 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11672 */
11673
11674 class StringPrinter
11675 {
11676     CompAllocator m_alloc;
11677     char*         m_buffer;
11678     size_t        m_bufferMax;
11679     size_t        m_bufferIndex = 0;
11680
11681     void Grow(size_t newSize);
11682
11683 public:
11684     StringPrinter(CompAllocator alloc, char* buffer = nullptr, size_t bufferMax = 0)
11685         : m_alloc(alloc), m_buffer(buffer), m_bufferMax(bufferMax)
11686     {
11687         if ((m_buffer == nullptr) || (m_bufferMax == 0))
11688         {
11689             m_bufferMax = 128;
11690             m_buffer    = alloc.allocate<char>(m_bufferMax);
11691         }
11692
11693         m_buffer[0] = '\0';
11694     }
11695
11696     size_t GetLength()
11697     {
11698         return m_bufferIndex;
11699     }
11700
11701     char* GetBuffer()
11702     {
11703         assert(m_buffer[GetLength()] == '\0');
11704         return m_buffer;
11705     }
11706     void Truncate(size_t newLength)
11707     {
11708         assert(newLength <= m_bufferIndex);
11709         m_bufferIndex           = newLength;
11710         m_buffer[m_bufferIndex] = '\0';
11711     }
11712
11713     void Append(const char* str);
11714     void Append(char chr);
11715 };
11716
11717 /*****************************************************************************
11718  *
11719  *  Variables to keep track of total code amounts.
11720  */
11721
11722 #if DISPLAY_SIZES
11723
11724 extern size_t grossVMsize;
11725 extern size_t grossNCsize;
11726 extern size_t totalNCsize;
11727
11728 extern unsigned genMethodICnt;
11729 extern unsigned genMethodNCnt;
11730 extern size_t   gcHeaderISize;
11731 extern size_t   gcPtrMapISize;
11732 extern size_t   gcHeaderNSize;
11733 extern size_t   gcPtrMapNSize;
11734
11735 #endif // DISPLAY_SIZES
11736
11737 /*****************************************************************************
11738  *
11739  *  Variables to keep track of basic block counts (more data on 1 BB methods)
11740  */
11741
11742 #if COUNT_BASIC_BLOCKS
11743 extern Histogram bbCntTable;
11744 extern Histogram bbOneBBSizeTable;
11745 extern Histogram domsChangedIterationTable;
11746 extern Histogram computeReachabilitySetsIterationTable;
11747 extern Histogram computeReachabilityIterationTable;
11748 #endif
11749
11750 /*****************************************************************************
11751  *
11752  *  Used by optFindNaturalLoops to gather statistical information such as
11753  *   - total number of natural loops
11754  *   - number of loops with 1, 2, ... exit conditions
11755  *   - number of loops that have an iterator (for like)
11756  *   - number of loops that have a constant iterator
11757  */
11758
11759 #if COUNT_LOOPS
11760
11761 extern unsigned  totalLoopMethods;        // counts the total number of methods that have natural loops
11762 extern unsigned  maxLoopsPerMethod;       // counts the maximum number of loops a method has
11763 extern unsigned  totalLoopOverflows;      // # of methods that identified more loops than we can represent
11764 extern unsigned  totalLoopCount;          // counts the total number of natural loops
11765 extern unsigned  totalUnnatLoopCount;     // counts the total number of (not-necessarily natural) loops
11766 extern unsigned  totalUnnatLoopOverflows; // # of methods that identified more unnatural loops than we can represent
11767 extern unsigned  iterLoopCount;           // counts the # of loops with an iterator (for like)
11768 extern unsigned  constIterLoopCount;      // counts the # of loops with a constant iterator (for like)
11769 extern bool      hasMethodLoops;          // flag to keep track if we already counted a method as having loops
11770 extern unsigned  loopsThisMethod;         // counts the number of loops in the current method
11771 extern bool      loopOverflowThisMethod;  // True if we exceeded the max # of loops in the method.
11772 extern Histogram loopCountTable;          // Histogram of loop counts
11773 extern Histogram loopExitCountTable;      // Histogram of loop exit counts
11774
11775 #endif // COUNT_LOOPS
11776
11777 #if MEASURE_BLOCK_SIZE
11778 extern size_t genFlowNodeSize;
11779 extern size_t genFlowNodeCnt;
11780 #endif // MEASURE_BLOCK_SIZE
11781
11782 #if MEASURE_NODE_SIZE
11783 struct NodeSizeStats
11784 {
11785     void Init()
11786     {
11787         genTreeNodeCnt        = 0;
11788         genTreeNodeSize       = 0;
11789         genTreeNodeActualSize = 0;
11790     }
11791
11792     // Count of tree nodes allocated.
11793     unsigned __int64 genTreeNodeCnt;
11794
11795     // The size we allocate.
11796     unsigned __int64 genTreeNodeSize;
11797
11798     // The actual size of the node. Note that the actual size will likely be smaller
11799     // than the allocated size, but we sometimes use SetOper()/ChangeOper() to change
11800     // a smaller node to a larger one. TODO-Cleanup: add stats on
11801     // SetOper()/ChangeOper() usage to quantify this.
11802     unsigned __int64 genTreeNodeActualSize;
11803 };
11804 extern NodeSizeStats genNodeSizeStats;        // Total node size stats
11805 extern NodeSizeStats genNodeSizeStatsPerFunc; // Per-function node size stats
11806 extern Histogram     genTreeNcntHist;
11807 extern Histogram     genTreeNsizHist;
11808 #endif // MEASURE_NODE_SIZE
11809
11810 /*****************************************************************************
11811  *  Count fatal errors (including noway_asserts).
11812  */
11813
11814 #if MEASURE_FATAL
11815 extern unsigned fatal_badCode;
11816 extern unsigned fatal_noWay;
11817 extern unsigned fatal_implLimitation;
11818 extern unsigned fatal_NOMEM;
11819 extern unsigned fatal_noWayAssertBody;
11820 #ifdef DEBUG
11821 extern unsigned fatal_noWayAssertBodyArgs;
11822 #endif // DEBUG
11823 extern unsigned fatal_NYI;
11824 #endif // MEASURE_FATAL
11825
11826 /*****************************************************************************
11827  * Codegen
11828  */
11829
11830 #ifdef TARGET_XARCH
11831
11832 const instruction INS_SHIFT_LEFT_LOGICAL  = INS_shl;
11833 const instruction INS_SHIFT_RIGHT_LOGICAL = INS_shr;
11834 const instruction INS_SHIFT_RIGHT_ARITHM  = INS_sar;
11835
11836 const instruction INS_AND             = INS_and;
11837 const instruction INS_OR              = INS_or;
11838 const instruction INS_XOR             = INS_xor;
11839 const instruction INS_NEG             = INS_neg;
11840 const instruction INS_TEST            = INS_test;
11841 const instruction INS_MUL             = INS_imul;
11842 const instruction INS_SIGNED_DIVIDE   = INS_idiv;
11843 const instruction INS_UNSIGNED_DIVIDE = INS_div;
11844 const instruction INS_BREAKPOINT      = INS_int3;
11845 const instruction INS_ADDC            = INS_adc;
11846 const instruction INS_SUBC            = INS_sbb;
11847 const instruction INS_NOT             = INS_not;
11848
11849 #endif // TARGET_XARCH
11850
11851 #ifdef TARGET_ARM
11852
11853 const instruction INS_SHIFT_LEFT_LOGICAL  = INS_lsl;
11854 const instruction INS_SHIFT_RIGHT_LOGICAL = INS_lsr;
11855 const instruction INS_SHIFT_RIGHT_ARITHM  = INS_asr;
11856
11857 const instruction INS_AND             = INS_and;
11858 const instruction INS_OR              = INS_orr;
11859 const instruction INS_XOR             = INS_eor;
11860 const instruction INS_NEG             = INS_rsb;
11861 const instruction INS_TEST            = INS_tst;
11862 const instruction INS_MUL             = INS_mul;
11863 const instruction INS_MULADD          = INS_mla;
11864 const instruction INS_SIGNED_DIVIDE   = INS_sdiv;
11865 const instruction INS_UNSIGNED_DIVIDE = INS_udiv;
11866 const instruction INS_BREAKPOINT      = INS_bkpt;
11867 const instruction INS_ADDC            = INS_adc;
11868 const instruction INS_SUBC            = INS_sbc;
11869 const instruction INS_NOT             = INS_mvn;
11870
11871 const instruction INS_ABS  = INS_vabs;
11872 const instruction INS_SQRT = INS_vsqrt;
11873
11874 #endif // TARGET_ARM
11875
11876 #ifdef TARGET_ARM64
11877
11878 const instruction        INS_MULADD = INS_madd;
11879 inline const instruction INS_BREAKPOINT_osHelper()
11880 {
11881     // GDB needs the encoding of brk #0
11882     // Windbg needs the encoding of brk #F000
11883     return TargetOS::IsUnix ? INS_brk_unix : INS_brk_windows;
11884 }
11885 #define INS_BREAKPOINT INS_BREAKPOINT_osHelper()
11886
11887 const instruction INS_ABS  = INS_fabs;
11888 const instruction INS_SQRT = INS_fsqrt;
11889
11890 #endif // TARGET_ARM64
11891
11892 #ifdef TARGET_LOONGARCH64
11893 const instruction INS_BREAKPOINT = INS_break;
11894 const instruction INS_MULADD     = INS_fmadd_d; // NOTE: default is double.
11895 const instruction INS_ABS        = INS_fabs_d;  // NOTE: default is double.
11896 const instruction INS_SQRT       = INS_fsqrt_d; // NOTE: default is double.
11897 #endif                                          // TARGET_LOONGARCH64
11898
11899 #ifdef TARGET_RISCV64
11900 const instruction INS_BREAKPOINT = INS_ebreak;
11901 #endif // TARGET_RISCV64
11902
11903 /*****************************************************************************/
11904
11905 extern const BYTE genTypeSizes[];
11906 extern const BYTE genTypeAlignments[];
11907 extern const BYTE genTypeStSzs[];
11908 extern const BYTE genActualTypes[];
11909
11910 /*****************************************************************************/
11911
11912 #ifdef DEBUG
11913 void dumpConvertedVarSet(Compiler* comp, VARSET_VALARG_TP vars);
11914 #endif // DEBUG
11915
11916 #include "compiler.hpp" // All the shared inline functions
11917
11918 /*****************************************************************************/
11919 #endif //_COMPILER_H_
11920 /*****************************************************************************/