Merge pull request #23119 from BruceForstall/Arm64PrePostIndexCoalescing
[platform/upstream/coreclr.git] / src / 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 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                           Compiler                                        XX
9 XX                                                                           XX
10 XX  Represents the method data we are currently JIT-compiling.               XX
11 XX  An instance of this class is created for every method we JIT.            XX
12 XX  This contains all the info needed for the method. So allocating a        XX
13 XX  a new instance per method makes it thread-safe.                          XX
14 XX  It should be used to do all the memory management for the compiler run.  XX
15 XX                                                                           XX
16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
17 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
18 */
19
20 /*****************************************************************************/
21 #ifndef _COMPILER_H_
22 #define _COMPILER_H_
23 /*****************************************************************************/
24
25 #include "jit.h"
26 #include "opcode.h"
27 #include "varset.h"
28 #include "jitstd.h"
29 #include "jithashtable.h"
30 #include "gentree.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 "reglist.h"
46 #include "jittelemetry.h"
47 #include "namedintrinsiclist.h"
48 #ifdef LATE_DISASM
49 #include "disasm.h"
50 #endif
51
52 #include "codegeninterface.h"
53 #include "regset.h"
54 #include "jitgcinfo.h"
55
56 #if DUMP_GC_TABLES && defined(JIT32_GCENCODER)
57 #include "gcdump.h"
58 #endif
59
60 #include "emit.h"
61
62 #include "hwintrinsic.h"
63 #include "simd.h"
64
65 // This is only used locally in the JIT to indicate that
66 // a verification block should be inserted
67 #define SEH_VERIFICATION_EXCEPTION 0xe0564552 // VER
68
69 /*****************************************************************************
70  *                  Forward declarations
71  */
72
73 struct InfoHdr;            // defined in GCInfo.h
74 struct escapeMapping_t;    // defined in flowgraph.cpp
75 class emitter;             // defined in emit.h
76 struct ShadowParamVarInfo; // defined in GSChecks.cpp
77 struct InitVarDscInfo;     // defined in register_arg_convention.h
78 class FgStack;             // defined in flowgraph.cpp
79 #if FEATURE_ANYCSE
80 class CSE_DataFlow; // defined in OptCSE.cpp
81 #endif
82 #ifdef DEBUG
83 struct IndentStack;
84 #endif
85
86 class Lowering; // defined in lower.h
87
88 // The following are defined in this file, Compiler.h
89
90 class Compiler;
91
92 /*****************************************************************************
93  *                  Unwind info
94  */
95
96 #include "unwind.h"
97
98 /*****************************************************************************/
99
100 //
101 // Declare global operator new overloads that use the compiler's arena allocator
102 //
103
104 // I wanted to make the second argument optional, with default = CMK_Unknown, but that
105 // caused these to be ambiguous with the global placement new operators.
106 void* __cdecl operator new(size_t n, Compiler* context, CompMemKind cmk);
107 void* __cdecl operator new[](size_t n, Compiler* context, CompMemKind cmk);
108 void* __cdecl operator new(size_t n, void* p, const jitstd::placement_t& syntax_difference);
109
110 // Requires the definitions of "operator new" so including "LoopCloning.h" after the definitions.
111 #include "loopcloning.h"
112
113 /*****************************************************************************/
114
115 /* This is included here and not earlier as it needs the definition of "CSE"
116  * which is defined in the section above */
117
118 /*****************************************************************************/
119
120 unsigned genLog2(unsigned value);
121 unsigned genLog2(unsigned __int64 value);
122
123 var_types genActualType(var_types type);
124 var_types genUnsignedType(var_types type);
125 var_types genSignedType(var_types type);
126
127 unsigned ReinterpretHexAsDecimal(unsigned);
128
129 /*****************************************************************************/
130
131 const unsigned FLG_CCTOR = (CORINFO_FLG_CONSTRUCTOR | CORINFO_FLG_STATIC);
132
133 #ifdef DEBUG
134 const int BAD_STK_OFFS = 0xBAADF00D; // for LclVarDsc::lvStkOffs
135 #endif
136
137 // The following holds the Local var info (scope information)
138 typedef const char* VarName; // Actual ASCII string
139 struct VarScopeDsc
140 {
141     IL_OFFSET vsdLifeBeg; // instr offset of beg of life
142     IL_OFFSET vsdLifeEnd; // instr offset of end of life
143     unsigned  vsdVarNum;  // (remapped) LclVarDsc number
144
145 #ifdef DEBUG
146     VarName vsdName; // name of the var
147 #endif
148
149     unsigned vsdLVnum; // 'which' in eeGetLVinfo().
150                        // Also, it is the index of this entry in the info.compVarScopes array,
151                        // which is useful since the array is also accessed via the
152                        // compEnterScopeList and compExitScopeList sorted arrays.
153 };
154
155 // This is the location of a SSA definition.
156 struct DefLoc
157 {
158     BasicBlock* m_blk;
159     GenTree*    m_tree;
160
161     DefLoc() : m_blk(nullptr), m_tree(nullptr)
162     {
163     }
164
165     DefLoc(BasicBlock* block, GenTree* tree) : m_blk(block), m_tree(tree)
166     {
167     }
168 };
169
170 // This class stores information associated with a LclVar SSA definition.
171 class LclSsaVarDsc
172 {
173 public:
174     LclSsaVarDsc()
175     {
176     }
177
178     LclSsaVarDsc(BasicBlock* block, GenTree* tree) : m_defLoc(block, tree)
179     {
180     }
181
182     ValueNumPair m_vnPair;
183     DefLoc       m_defLoc;
184 };
185
186 // This class stores information associated with a memory SSA definition.
187 class SsaMemDef
188 {
189 public:
190     ValueNumPair m_vnPair;
191 };
192
193 //------------------------------------------------------------------------
194 // SsaDefArray: A resizable array of SSA definitions.
195 //
196 // Unlike an ordinary resizable array implementation, this allows only element
197 // addition (by calling AllocSsaNum) and has special handling for RESERVED_SSA_NUM
198 // (basically it's a 1-based array). The array doesn't impose any particular
199 // requirements on the elements it stores and AllocSsaNum forwards its arguments
200 // to the array element constructor, this way the array supports both LclSsaVarDsc
201 // and SsaMemDef elements.
202 //
203 template <typename T>
204 class SsaDefArray
205 {
206     T*       m_array;
207     unsigned m_arraySize;
208     unsigned m_count;
209
210     static_assert_no_msg(SsaConfig::RESERVED_SSA_NUM == 0);
211     static_assert_no_msg(SsaConfig::FIRST_SSA_NUM == 1);
212
213     // Get the minimum valid SSA number.
214     unsigned GetMinSsaNum() const
215     {
216         return SsaConfig::FIRST_SSA_NUM;
217     }
218
219     // Increase (double) the size of the array.
220     void GrowArray(CompAllocator alloc)
221     {
222         unsigned oldSize = m_arraySize;
223         unsigned newSize = max(2, oldSize * 2);
224
225         T* newArray = alloc.allocate<T>(newSize);
226
227         for (unsigned i = 0; i < oldSize; i++)
228         {
229             newArray[i] = m_array[i];
230         }
231
232         m_array     = newArray;
233         m_arraySize = newSize;
234     }
235
236 public:
237     // Construct an empty SsaDefArray.
238     SsaDefArray() : m_array(nullptr), m_arraySize(0), m_count(0)
239     {
240     }
241
242     // Reset the array (used only if the SSA form is reconstructed).
243     void Reset()
244     {
245         m_count = 0;
246     }
247
248     // Allocate a new SSA number (starting with SsaConfig::FIRST_SSA_NUM).
249     template <class... Args>
250     unsigned AllocSsaNum(CompAllocator alloc, Args&&... args)
251     {
252         if (m_count == m_arraySize)
253         {
254             GrowArray(alloc);
255         }
256
257         unsigned ssaNum    = GetMinSsaNum() + m_count;
258         m_array[m_count++] = T(jitstd::forward<Args>(args)...);
259
260         // Ensure that the first SSA number we allocate is SsaConfig::FIRST_SSA_NUM
261         assert((ssaNum == SsaConfig::FIRST_SSA_NUM) || (m_count > 1));
262
263         return ssaNum;
264     }
265
266     // Get the number of SSA definitions in the array.
267     unsigned GetCount() const
268     {
269         return m_count;
270     }
271
272     // Get a pointer to the SSA definition at the specified index.
273     T* GetSsaDefByIndex(unsigned index)
274     {
275         assert(index < m_count);
276         return &m_array[index];
277     }
278
279     // Check if the specified SSA number is valid.
280     bool IsValidSsaNum(unsigned ssaNum) const
281     {
282         return (GetMinSsaNum() <= ssaNum) && (ssaNum < (GetMinSsaNum() + m_count));
283     }
284
285     // Get a pointer to the SSA definition associated with the specified SSA number.
286     T* GetSsaDef(unsigned ssaNum)
287     {
288         assert(ssaNum != SsaConfig::RESERVED_SSA_NUM);
289         return GetSsaDefByIndex(ssaNum - GetMinSsaNum());
290     }
291 };
292
293 enum RefCountState
294 {
295     RCS_INVALID, // not valid to get/set ref counts
296     RCS_EARLY,   // early counts for struct promotion and struct passing
297     RCS_NORMAL,  // normal ref counts (from lvaMarkRefs onward)
298 };
299
300 class LclVarDsc
301 {
302 public:
303     // The constructor. Most things can just be zero'ed.
304     //
305     // Initialize the ArgRegs to REG_STK.
306     // Morph will update if this local is passed in a register.
307     LclVarDsc()
308         : _lvArgReg(REG_STK)
309         ,
310 #if FEATURE_MULTIREG_ARGS
311         _lvOtherArgReg(REG_STK)
312         ,
313 #endif // FEATURE_MULTIREG_ARGS
314 #if ASSERTION_PROP
315         lvRefBlks(BlockSetOps::UninitVal())
316         ,
317 #endif // ASSERTION_PROP
318         lvPerSsaData()
319     {
320     }
321
322     // note this only packs because var_types is a typedef of unsigned char
323     var_types lvType : 5; // TYP_INT/LONG/FLOAT/DOUBLE/REF
324
325     unsigned char lvIsParam : 1;           // is this a parameter?
326     unsigned char lvIsRegArg : 1;          // is this a register argument?
327     unsigned char lvFramePointerBased : 1; // 0 = off of REG_SPBASE (e.g., ESP), 1 = off of REG_FPBASE (e.g., EBP)
328
329     unsigned char lvStructGcCount : 3; // if struct, how many GC pointer (stop counting at 7). The only use of values >1
330                                        // is to help determine whether to use block init in the prolog.
331     unsigned char lvOnFrame : 1;       // (part of) the variable lives on the frame
332     unsigned char lvRegister : 1;      // assigned to live in a register? For RyuJIT backend, this is only set if the
333                                        // variable is in the same register for the entire function.
334     unsigned char lvTracked : 1;       // is this a tracked variable?
335     bool          lvTrackedNonStruct()
336     {
337         return lvTracked && lvType != TYP_STRUCT;
338     }
339     unsigned char lvPinned : 1; // is this a pinned variable?
340
341     unsigned char lvMustInit : 1;    // must be initialized
342     unsigned char lvAddrExposed : 1; // The address of this variable is "exposed" -- passed as an argument, stored in a
343                                      // global location, etc.
344                                      // We cannot reason reliably about the value of the variable.
345     unsigned char lvDoNotEnregister : 1; // Do not enregister this variable.
346     unsigned char lvFieldAccessed : 1;   // The var is a struct local, and a field of the variable is accessed.  Affects
347                                          // struct promotion.
348
349     unsigned char lvInSsa : 1; // The variable is in SSA form (set by SsaBuilder)
350
351 #ifdef DEBUG
352     // These further document the reasons for setting "lvDoNotEnregister".  (Note that "lvAddrExposed" is one of the
353     // reasons;
354     // also, lvType == TYP_STRUCT prevents enregistration.  At least one of the reasons should be true.
355     unsigned char lvVMNeedsStackAddr : 1; // The VM may have access to a stack-relative address of the variable, and
356                                           // read/write its value.
357     unsigned char lvLiveInOutOfHndlr : 1; // The variable was live in or out of an exception handler, and this required
358                                           // the variable to be
359                                           // in the stack (at least at those boundaries.)
360     unsigned char lvLclFieldExpr : 1;     // The variable is not a struct, but was accessed like one (e.g., reading a
361                                           // particular byte from an int).
362     unsigned char lvLclBlockOpAddr : 1;   // The variable was written to via a block operation that took its address.
363     unsigned char lvLiveAcrossUCall : 1;  // The variable is live across an unmanaged call.
364 #endif
365     unsigned char lvIsCSE : 1;       // Indicates if this LclVar is a CSE variable.
366     unsigned char lvHasLdAddrOp : 1; // has ldloca or ldarga opcode on this local.
367     unsigned char lvStackByref : 1;  // This is a compiler temporary of TYP_BYREF that is known to point into our local
368                                      // stack frame.
369
370     unsigned char lvHasILStoreOp : 1;         // there is at least one STLOC or STARG on this local
371     unsigned char lvHasMultipleILStoreOp : 1; // there is more than one STLOC on this local
372
373     unsigned char lvIsTemp : 1; // Short-lifetime compiler temp (if lvIsParam is false), or implicit byref parameter
374                                 // (if lvIsParam is true)
375 #if OPT_BOOL_OPS
376     unsigned char lvIsBoolean : 1; // set if variable is boolean
377 #endif
378     unsigned char lvSingleDef : 1; // variable has a single def
379                                    // before lvaMarkLocalVars: identifies ref type locals that can get type updates
380                                    // after lvaMarkLocalVars: identifies locals that are suitable for optAddCopies
381
382 #if ASSERTION_PROP
383     unsigned char lvDisqualify : 1;   // variable is no longer OK for add copy optimization
384     unsigned char lvVolatileHint : 1; // hint for AssertionProp
385 #endif
386
387 #ifndef _TARGET_64BIT_
388     unsigned char lvStructDoubleAlign : 1; // Must we double align this struct?
389 #endif                                     // !_TARGET_64BIT_
390 #ifdef _TARGET_64BIT_
391     unsigned char lvQuirkToLong : 1; // Quirk to allocate this LclVar as a 64-bit long
392 #endif
393 #ifdef DEBUG
394     unsigned char lvKeepType : 1;       // Don't change the type of this variable
395     unsigned char lvNoLclFldStress : 1; // Can't apply local field stress on this one
396 #endif
397     unsigned char lvIsPtr : 1; // Might this be used in an address computation? (used by buffer overflow security
398                                // checks)
399     unsigned char lvIsUnsafeBuffer : 1; // Does this contain an unsafe buffer requiring buffer overflow security checks?
400     unsigned char lvPromoted : 1; // True when this local is a promoted struct, a normed struct, or a "split" long on a
401                                   // 32-bit target.  For implicit byref parameters, this gets hijacked between
402                                   // fgRetypeImplicitByRefArgs and fgMarkDemotedImplicitByRefArgs to indicate whether
403                                   // references to the arg are being rewritten as references to a promoted shadow local.
404     unsigned char lvIsStructField : 1;     // Is this local var a field of a promoted struct local?
405     unsigned char lvOverlappingFields : 1; // True when we have a struct with possibly overlapping fields
406     unsigned char lvContainsHoles : 1;     // True when we have a promoted struct that contains holes
407     unsigned char lvCustomLayout : 1;      // True when this struct has "CustomLayout"
408
409     unsigned char lvIsMultiRegArg : 1; // true if this is a multireg LclVar struct used in an argument context
410     unsigned char lvIsMultiRegRet : 1; // true if this is a multireg LclVar struct assigned from a multireg call
411
412 #ifdef FEATURE_HFA
413     unsigned char _lvIsHfa : 1;          // Is this a struct variable who's class handle is an HFA type
414     unsigned char _lvIsHfaRegArg : 1;    // Is this a HFA argument variable?    // TODO-CLEANUP: Remove this and replace
415                                          // with (lvIsRegArg && lvIsHfa())
416     unsigned char _lvHfaTypeIsFloat : 1; // Is the HFA type float or double?
417 #endif                                   // FEATURE_HFA
418
419 #ifdef DEBUG
420     // TODO-Cleanup: See the note on lvSize() - this flag is only in use by asserts that are checking for struct
421     // types, and is needed because of cases where TYP_STRUCT is bashed to an integral type.
422     // Consider cleaning this up so this workaround is not required.
423     unsigned char lvUnusedStruct : 1; // All references to this promoted struct are through its field locals.
424                                       // I.e. there is no longer any reference to the struct directly.
425                                       // In this case we can simply remove this struct local.
426 #endif
427
428     unsigned char lvLRACandidate : 1; // Tracked for linear scan register allocation purposes
429
430 #ifdef FEATURE_SIMD
431     // Note that both SIMD vector args and locals are marked as lvSIMDType = true, but the
432     // type of an arg node is TYP_BYREF and a local node is TYP_SIMD*.
433     unsigned char lvSIMDType : 1;            // This is a SIMD struct
434     unsigned char lvUsedInSIMDIntrinsic : 1; // This tells lclvar is used for simd intrinsic
435     var_types     lvBaseType : 5;            // Note: this only packs because var_types is a typedef of unsigned char
436 #endif                                       // FEATURE_SIMD
437     unsigned char lvRegStruct : 1;           // This is a reg-sized non-field-addressed struct.
438
439     unsigned char lvClassIsExact : 1; // lvClassHandle is the exact type
440
441 #ifdef DEBUG
442     unsigned char lvClassInfoUpdated : 1; // true if this var has updated class handle or exactness
443 #endif
444
445     unsigned char lvImplicitlyReferenced : 1; // true if there are non-IR references to this local (prolog, epilog, gc,
446                                               // eh)
447
448     union {
449         unsigned lvFieldLclStart; // The index of the local var representing the first field in the promoted struct
450                                   // local.  For implicit byref parameters, this gets hijacked between
451                                   // fgRetypeImplicitByRefArgs and fgMarkDemotedImplicitByRefArgs to point to the
452                                   // struct local created to model the parameter's struct promotion, if any.
453         unsigned lvParentLcl; // The index of the local var representing the parent (i.e. the promoted struct local).
454                               // Valid on promoted struct local fields.
455     };
456
457     unsigned char lvFieldCnt; //  Number of fields in the promoted VarDsc.
458     unsigned char lvFldOffset;
459     unsigned char lvFldOrdinal;
460
461 #if FEATURE_MULTIREG_ARGS
462     regNumber lvRegNumForSlot(unsigned slotNum)
463     {
464         if (slotNum == 0)
465         {
466             return lvArgReg;
467         }
468         else if (slotNum == 1)
469         {
470             return lvOtherArgReg;
471         }
472         else
473         {
474             assert(false && "Invalid slotNum!");
475         }
476
477         unreached();
478     }
479 #endif // FEATURE_MULTIREG_ARGS
480
481     bool lvIsHfa() const
482     {
483 #ifdef FEATURE_HFA
484         return _lvIsHfa;
485 #else
486         return false;
487 #endif
488     }
489
490     void lvSetIsHfa()
491     {
492 #ifdef FEATURE_HFA
493         _lvIsHfa = true;
494 #endif
495     }
496
497     bool lvIsHfaRegArg() const
498     {
499 #ifdef FEATURE_HFA
500         return _lvIsHfaRegArg;
501 #else
502         return false;
503 #endif
504     }
505
506     void lvSetIsHfaRegArg(bool value = true)
507     {
508 #ifdef FEATURE_HFA
509         _lvIsHfaRegArg = value;
510 #endif
511     }
512
513     bool lvHfaTypeIsFloat() const
514     {
515 #ifdef FEATURE_HFA
516         return _lvHfaTypeIsFloat;
517 #else
518         return false;
519 #endif
520     }
521
522     void lvSetHfaTypeIsFloat(bool value)
523     {
524 #ifdef FEATURE_HFA
525         _lvHfaTypeIsFloat = value;
526 #endif
527     }
528
529     // on Arm64 - Returns 1-4 indicating the number of register slots used by the HFA
530     // on Arm32 - Returns the total number of single FP register slots used by the HFA, max is 8
531     //
532     unsigned lvHfaSlots() const
533     {
534         assert(lvIsHfa());
535         assert(varTypeIsStruct(lvType));
536 #ifdef _TARGET_ARM_
537         return lvExactSize / sizeof(float);
538 #else  //  _TARGET_ARM64_
539         if (lvHfaTypeIsFloat())
540         {
541             return lvExactSize / sizeof(float);
542         }
543         else
544         {
545             return lvExactSize / sizeof(double);
546         }
547 #endif //  _TARGET_ARM64_
548     }
549
550     // lvIsMultiRegArgOrRet()
551     //     returns true if this is a multireg LclVar struct used in an argument context
552     //               or if this is a multireg LclVar struct assigned from a multireg call
553     bool lvIsMultiRegArgOrRet()
554     {
555         return lvIsMultiRegArg || lvIsMultiRegRet;
556     }
557
558 private:
559     regNumberSmall _lvRegNum; // Used to store the register this variable is in (or, the low register of a
560                               // register pair). It is set during codegen any time the
561                               // variable is enregistered (lvRegister is only set
562                               // to non-zero if the variable gets the same register assignment for its entire
563                               // lifetime).
564 #if !defined(_TARGET_64BIT_)
565     regNumberSmall _lvOtherReg; // Used for "upper half" of long var.
566 #endif                          // !defined(_TARGET_64BIT_)
567
568     regNumberSmall _lvArgReg; // The register in which this argument is passed.
569
570 #if FEATURE_MULTIREG_ARGS
571     regNumberSmall _lvOtherArgReg; // Used for the second part of the struct passed in a register.
572                                    // Note this is defined but not used by ARM32
573 #endif                             // FEATURE_MULTIREG_ARGS
574
575     regNumberSmall _lvArgInitReg; // the register into which the argument is moved at entry
576
577 public:
578     // The register number is stored in a small format (8 bits), but the getters return and the setters take
579     // a full-size (unsigned) format, to localize the casts here.
580
581     /////////////////////
582
583     __declspec(property(get = GetRegNum, put = SetRegNum)) regNumber lvRegNum;
584
585     regNumber GetRegNum() const
586     {
587         return (regNumber)_lvRegNum;
588     }
589
590     void SetRegNum(regNumber reg)
591     {
592         _lvRegNum = (regNumberSmall)reg;
593         assert(_lvRegNum == reg);
594     }
595
596 /////////////////////
597
598 #if defined(_TARGET_64BIT_)
599     __declspec(property(get = GetOtherReg, put = SetOtherReg)) regNumber lvOtherReg;
600
601     regNumber GetOtherReg() const
602     {
603         assert(!"shouldn't get here"); // can't use "unreached();" because it's NORETURN, which causes C4072
604                                        // "unreachable code" warnings
605         return REG_NA;
606     }
607
608     void SetOtherReg(regNumber reg)
609     {
610         assert(!"shouldn't get here"); // can't use "unreached();" because it's NORETURN, which causes C4072
611                                        // "unreachable code" warnings
612     }
613 #else  // !_TARGET_64BIT_
614     __declspec(property(get = GetOtherReg, put = SetOtherReg)) regNumber lvOtherReg;
615
616     regNumber GetOtherReg() const
617     {
618         return (regNumber)_lvOtherReg;
619     }
620
621     void SetOtherReg(regNumber reg)
622     {
623         _lvOtherReg = (regNumberSmall)reg;
624         assert(_lvOtherReg == reg);
625     }
626 #endif // !_TARGET_64BIT_
627
628     /////////////////////
629
630     __declspec(property(get = GetArgReg, put = SetArgReg)) regNumber lvArgReg;
631
632     regNumber GetArgReg() const
633     {
634         return (regNumber)_lvArgReg;
635     }
636
637     void SetArgReg(regNumber reg)
638     {
639         _lvArgReg = (regNumberSmall)reg;
640         assert(_lvArgReg == reg);
641     }
642
643 #if FEATURE_MULTIREG_ARGS
644     __declspec(property(get = GetOtherArgReg, put = SetOtherArgReg)) regNumber lvOtherArgReg;
645
646     regNumber GetOtherArgReg() const
647     {
648         return (regNumber)_lvOtherArgReg;
649     }
650
651     void SetOtherArgReg(regNumber reg)
652     {
653         _lvOtherArgReg = (regNumberSmall)reg;
654         assert(_lvOtherArgReg == reg);
655     }
656 #endif // FEATURE_MULTIREG_ARGS
657
658 #ifdef FEATURE_SIMD
659     // Is this is a SIMD struct?
660     bool lvIsSIMDType() const
661     {
662         return lvSIMDType;
663     }
664
665     // Is this is a SIMD struct which is used for SIMD intrinsic?
666     bool lvIsUsedInSIMDIntrinsic() const
667     {
668         return lvUsedInSIMDIntrinsic;
669     }
670 #else
671     // If feature_simd not enabled, return false
672     bool lvIsSIMDType() const
673     {
674         return false;
675     }
676     bool lvIsUsedInSIMDIntrinsic() const
677     {
678         return false;
679     }
680 #endif
681
682     /////////////////////
683
684     __declspec(property(get = GetArgInitReg, put = SetArgInitReg)) regNumber lvArgInitReg;
685
686     regNumber GetArgInitReg() const
687     {
688         return (regNumber)_lvArgInitReg;
689     }
690
691     void SetArgInitReg(regNumber reg)
692     {
693         _lvArgInitReg = (regNumberSmall)reg;
694         assert(_lvArgInitReg == reg);
695     }
696
697     /////////////////////
698
699     bool lvIsRegCandidate() const
700     {
701         return lvLRACandidate != 0;
702     }
703
704     bool lvIsInReg() const
705     {
706         return lvIsRegCandidate() && (lvRegNum != REG_STK);
707     }
708
709     regMaskTP lvRegMask() const
710     {
711         regMaskTP regMask = RBM_NONE;
712         if (varTypeIsFloating(TypeGet()))
713         {
714             if (lvRegNum != REG_STK)
715             {
716                 regMask = genRegMaskFloat(lvRegNum, TypeGet());
717             }
718         }
719         else
720         {
721             if (lvRegNum != REG_STK)
722             {
723                 regMask = genRegMask(lvRegNum);
724             }
725         }
726         return regMask;
727     }
728
729     unsigned short lvVarIndex; // variable tracking index
730
731 private:
732     unsigned short m_lvRefCnt; // unweighted (real) reference count.  For implicit by reference
733                                // parameters, this gets hijacked from fgMarkImplicitByRefArgs
734                                // through fgMarkDemotedImplicitByRefArgs, to provide a static
735                                // appearance count (computed during address-exposed analysis)
736                                // that fgMakeOutgoingStructArgCopy consults during global morph
737                                // to determine if eliding its copy is legal.
738
739     BasicBlock::weight_t m_lvRefCntWtd; // weighted reference count
740
741 public:
742     unsigned short lvRefCnt(RefCountState state = RCS_NORMAL) const;
743     void incLvRefCnt(unsigned short delta, RefCountState state = RCS_NORMAL);
744     void setLvRefCnt(unsigned short newValue, RefCountState state = RCS_NORMAL);
745
746     BasicBlock::weight_t lvRefCntWtd(RefCountState state = RCS_NORMAL) const;
747     void incLvRefCntWtd(BasicBlock::weight_t delta, RefCountState state = RCS_NORMAL);
748     void setLvRefCntWtd(BasicBlock::weight_t newValue, RefCountState state = RCS_NORMAL);
749
750     int      lvStkOffs;   // stack offset of home
751     unsigned lvExactSize; // (exact) size of the type in bytes
752
753     // Is this a promoted struct?
754     // This method returns true only for structs (including SIMD structs), not for
755     // locals that are split on a 32-bit target.
756     // It is only necessary to use this:
757     //   1) if only structs are wanted, and
758     //   2) if Lowering has already been done.
759     // Otherwise lvPromoted is valid.
760     bool lvPromotedStruct()
761     {
762 #if !defined(_TARGET_64BIT_)
763         return (lvPromoted && !varTypeIsLong(lvType));
764 #else  // defined(_TARGET_64BIT_)
765         return lvPromoted;
766 #endif // defined(_TARGET_64BIT_)
767     }
768
769     unsigned lvSize() const // Size needed for storage representation. Only used for structs or TYP_BLK.
770     {
771         // TODO-Review: Sometimes we get called on ARM with HFA struct variables that have been promoted,
772         // where the struct itself is no longer used because all access is via its member fields.
773         // When that happens, the struct is marked as unused and its type has been changed to
774         // TYP_INT (to keep the GC tracking code from looking at it).
775         // See Compiler::raAssignVars() for details. For example:
776         //      N002 (  4,  3) [00EA067C] -------------               return    struct $346
777         //      N001 (  3,  2) [00EA0628] -------------                  lclVar    struct(U) V03 loc2
778         //                                                                        float  V03.f1 (offs=0x00) -> V12 tmp7
779         //                                                                        f8 (last use) (last use) $345
780         // Here, the "struct(U)" shows that the "V03 loc2" variable is unused. Not shown is that V03
781         // is now TYP_INT in the local variable table. It's not really unused, because it's in the tree.
782
783         assert(varTypeIsStruct(lvType) || (lvType == TYP_BLK) || (lvPromoted && lvUnusedStruct));
784
785 #if defined(FEATURE_SIMD) && !defined(_TARGET_64BIT_)
786         // For 32-bit architectures, we make local variable SIMD12 types 16 bytes instead of just 12. We can't do
787         // this for arguments, which must be passed according the defined ABI. We don't want to do this for
788         // dependently promoted struct fields, but we don't know that here. See lvaMapSimd12ToSimd16().
789         // (Note that for 64-bits, we are already rounding up to 16.)
790         if ((lvType == TYP_SIMD12) && !lvIsParam)
791         {
792             assert(lvExactSize == 12);
793             return 16;
794         }
795 #endif // defined(FEATURE_SIMD) && !defined(_TARGET_64BIT_)
796
797         return roundUp(lvExactSize, TARGET_POINTER_SIZE);
798     }
799
800     size_t lvArgStackSize() const;
801
802     unsigned lvSlotNum; // original slot # (if remapped)
803
804     typeInfo lvVerTypeInfo; // type info needed for verification
805
806     CORINFO_CLASS_HANDLE lvClassHnd; // class handle for the local, or null if not known
807
808     CORINFO_FIELD_HANDLE lvFieldHnd; // field handle for promoted struct fields
809
810     BYTE* lvGcLayout; // GC layout info for structs
811
812 #if ASSERTION_PROP
813     BlockSet lvRefBlks;          // Set of blocks that contain refs
814     GenTree* lvDefStmt;          // Pointer to the statement with the single definition
815     void     lvaDisqualifyVar(); // Call to disqualify a local variable from use in optAddCopies
816 #endif
817     var_types TypeGet() const
818     {
819         return (var_types)lvType;
820     }
821     bool lvStackAligned() const
822     {
823         assert(lvIsStructField);
824         return ((lvFldOffset % TARGET_POINTER_SIZE) == 0);
825     }
826     bool lvNormalizeOnLoad() const
827     {
828         return varTypeIsSmall(TypeGet()) &&
829                // lvIsStructField is treated the same as the aliased local, see fgDoNormalizeOnStore.
830                (lvIsParam || lvAddrExposed || lvIsStructField);
831     }
832
833     bool lvNormalizeOnStore()
834     {
835         return varTypeIsSmall(TypeGet()) &&
836                // lvIsStructField is treated the same as the aliased local, see fgDoNormalizeOnStore.
837                !(lvIsParam || lvAddrExposed || lvIsStructField);
838     }
839
840     void incRefCnts(BasicBlock::weight_t weight,
841                     Compiler*            pComp,
842                     RefCountState        state     = RCS_NORMAL,
843                     bool                 propagate = true);
844     bool IsFloatRegType() const
845     {
846         return isFloatRegType(lvType) || lvIsHfaRegArg();
847     }
848     var_types GetHfaType() const
849     {
850         return lvIsHfa() ? (lvHfaTypeIsFloat() ? TYP_FLOAT : TYP_DOUBLE) : TYP_UNDEF;
851     }
852     void SetHfaType(var_types type)
853     {
854         assert(varTypeIsFloating(type));
855         lvSetHfaTypeIsFloat(type == TYP_FLOAT);
856     }
857
858     var_types lvaArgType();
859
860     SsaDefArray<LclSsaVarDsc> lvPerSsaData;
861
862     // Returns the address of the per-Ssa data for the given ssaNum (which is required
863     // not to be the SsaConfig::RESERVED_SSA_NUM, which indicates that the variable is
864     // not an SSA variable).
865     LclSsaVarDsc* GetPerSsaData(unsigned ssaNum)
866     {
867         return lvPerSsaData.GetSsaDef(ssaNum);
868     }
869
870 #ifdef DEBUG
871 public:
872     const char* lvReason;
873
874     void PrintVarReg() const
875     {
876         printf("%s", getRegName(lvRegNum));
877     }
878 #endif // DEBUG
879
880 }; // class LclVarDsc
881
882 /*
883 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
884 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
885 XX                                                                           XX
886 XX                           TempsInfo                                       XX
887 XX                                                                           XX
888 XX  The temporary lclVars allocated by the compiler for code generation      XX
889 XX                                                                           XX
890 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
891 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
892 */
893
894 /*****************************************************************************
895  *
896  *  The following keeps track of temporaries allocated in the stack frame
897  *  during code-generation (after register allocation). These spill-temps are
898  *  only used if we run out of registers while evaluating a tree.
899  *
900  *  These are different from the more common temps allocated by lvaGrabTemp().
901  */
902
903 class TempDsc
904 {
905 public:
906     TempDsc* tdNext;
907
908 private:
909     int tdOffs;
910 #ifdef DEBUG
911     static const int BAD_TEMP_OFFSET = 0xDDDDDDDD; // used as a sentinel "bad value" for tdOffs in DEBUG
912 #endif                                             // DEBUG
913
914     int       tdNum;
915     BYTE      tdSize;
916     var_types tdType;
917
918 public:
919     TempDsc(int _tdNum, unsigned _tdSize, var_types _tdType) : tdNum(_tdNum), tdSize((BYTE)_tdSize), tdType(_tdType)
920     {
921 #ifdef DEBUG
922         assert(tdNum <
923                0); // temps must have a negative number (so they have a different number from all local variables)
924         tdOffs = BAD_TEMP_OFFSET;
925 #endif // DEBUG
926         if (tdNum != _tdNum)
927         {
928             IMPL_LIMITATION("too many spill temps");
929         }
930     }
931
932 #ifdef DEBUG
933     bool tdLegalOffset() const
934     {
935         return tdOffs != BAD_TEMP_OFFSET;
936     }
937 #endif // DEBUG
938
939     int tdTempOffs() const
940     {
941         assert(tdLegalOffset());
942         return tdOffs;
943     }
944     void tdSetTempOffs(int offs)
945     {
946         tdOffs = offs;
947         assert(tdLegalOffset());
948     }
949     void tdAdjustTempOffs(int offs)
950     {
951         tdOffs += offs;
952         assert(tdLegalOffset());
953     }
954
955     int tdTempNum() const
956     {
957         assert(tdNum < 0);
958         return tdNum;
959     }
960     unsigned tdTempSize() const
961     {
962         return tdSize;
963     }
964     var_types tdTempType() const
965     {
966         return tdType;
967     }
968 };
969
970 // interface to hide linearscan implementation from rest of compiler
971 class LinearScanInterface
972 {
973 public:
974     virtual void doLinearScan()                                = 0;
975     virtual void recordVarLocationsAtStartOfBB(BasicBlock* bb) = 0;
976     virtual bool willEnregisterLocalVars() const               = 0;
977 };
978
979 LinearScanInterface* getLinearScanAllocator(Compiler* comp);
980
981 // Information about arrays: their element type and size, and the offset of the first element.
982 // We label GT_IND's that are array indices with GTF_IND_ARR_INDEX, and, for such nodes,
983 // associate an array info via the map retrieved by GetArrayInfoMap().  This information is used,
984 // for example, in value numbering of array index expressions.
985 struct ArrayInfo
986 {
987     var_types            m_elemType;
988     CORINFO_CLASS_HANDLE m_elemStructType;
989     unsigned             m_elemSize;
990     unsigned             m_elemOffset;
991
992     ArrayInfo() : m_elemType(TYP_UNDEF), m_elemStructType(nullptr), m_elemSize(0), m_elemOffset(0)
993     {
994     }
995
996     ArrayInfo(var_types elemType, unsigned elemSize, unsigned elemOffset, CORINFO_CLASS_HANDLE elemStructType)
997         : m_elemType(elemType), m_elemStructType(elemStructType), m_elemSize(elemSize), m_elemOffset(elemOffset)
998     {
999     }
1000 };
1001
1002 // This enumeration names the phases into which we divide compilation.  The phases should completely
1003 // partition a compilation.
1004 enum Phases
1005 {
1006 #define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) enum_nm,
1007 #include "compphases.h"
1008     PHASE_NUMBER_OF
1009 };
1010
1011 extern const char*   PhaseNames[];
1012 extern const char*   PhaseEnums[];
1013 extern const LPCWSTR PhaseShortNames[];
1014
1015 // The following enum provides a simple 1:1 mapping to CLR API's
1016 enum API_ICorJitInfo_Names
1017 {
1018 #define DEF_CLR_API(name) API_##name,
1019 #include "ICorJitInfo_API_names.h"
1020     API_COUNT
1021 };
1022
1023 //---------------------------------------------------------------
1024 // Compilation time.
1025 //
1026
1027 // A "CompTimeInfo" is a structure for tracking the compilation time of one or more methods.
1028 // We divide a compilation into a sequence of contiguous phases, and track the total (per-thread) cycles
1029 // of the compilation, as well as the cycles for each phase.  We also track the number of bytecodes.
1030 // If there is a failure in reading a timer at any point, the "CompTimeInfo" becomes invalid, as indicated
1031 // by "m_timerFailure" being true.
1032 // If FEATURE_JIT_METHOD_PERF is not set, we define a minimal form of this, enough to let other code compile.
1033 struct CompTimeInfo
1034 {
1035 #ifdef FEATURE_JIT_METHOD_PERF
1036     // The string names of the phases.
1037     static const char* PhaseNames[];
1038
1039     static bool PhaseHasChildren[];
1040     static int  PhaseParent[];
1041     static bool PhaseReportsIRSize[];
1042
1043     unsigned         m_byteCodeBytes;
1044     unsigned __int64 m_totalCycles;
1045     unsigned __int64 m_invokesByPhase[PHASE_NUMBER_OF];
1046     unsigned __int64 m_cyclesByPhase[PHASE_NUMBER_OF];
1047 #if MEASURE_CLRAPI_CALLS
1048     unsigned __int64 m_CLRinvokesByPhase[PHASE_NUMBER_OF];
1049     unsigned __int64 m_CLRcyclesByPhase[PHASE_NUMBER_OF];
1050 #endif
1051
1052     unsigned m_nodeCountAfterPhase[PHASE_NUMBER_OF];
1053
1054     // For better documentation, we call EndPhase on
1055     // non-leaf phases.  We should also call EndPhase on the
1056     // last leaf subphase; obviously, the elapsed cycles between the EndPhase
1057     // for the last leaf subphase and the EndPhase for an ancestor should be very small.
1058     // We add all such "redundant end phase" intervals to this variable below; we print
1059     // it out in a report, so we can verify that it is, indeed, very small.  If it ever
1060     // isn't, this means that we're doing something significant between the end of the last
1061     // declared subphase and the end of its parent.
1062     unsigned __int64 m_parentPhaseEndSlop;
1063     bool             m_timerFailure;
1064
1065 #if MEASURE_CLRAPI_CALLS
1066     // The following measures the time spent inside each individual CLR API call.
1067     unsigned         m_allClrAPIcalls;
1068     unsigned         m_perClrAPIcalls[API_ICorJitInfo_Names::API_COUNT];
1069     unsigned __int64 m_allClrAPIcycles;
1070     unsigned __int64 m_perClrAPIcycles[API_ICorJitInfo_Names::API_COUNT];
1071     unsigned __int32 m_maxClrAPIcycles[API_ICorJitInfo_Names::API_COUNT];
1072 #endif // MEASURE_CLRAPI_CALLS
1073
1074     CompTimeInfo(unsigned byteCodeBytes);
1075 #endif
1076 };
1077
1078 #ifdef FEATURE_JIT_METHOD_PERF
1079
1080 #if MEASURE_CLRAPI_CALLS
1081 struct WrapICorJitInfo;
1082 #endif
1083
1084 // This class summarizes the JIT time information over the course of a run: the number of methods compiled,
1085 // and the total and maximum timings.  (These are instances of the "CompTimeInfo" type described above).
1086 // The operation of adding a single method's timing to the summary may be performed concurrently by several
1087 // threads, so it is protected by a lock.
1088 // This class is intended to be used as a singleton type, with only a single instance.
1089 class CompTimeSummaryInfo
1090 {
1091     // This lock protects the fields of all CompTimeSummaryInfo(s) (of which we expect there to be one).
1092     static CritSecObject s_compTimeSummaryLock;
1093
1094     int          m_numMethods;
1095     int          m_totMethods;
1096     CompTimeInfo m_total;
1097     CompTimeInfo m_maximum;
1098
1099     int          m_numFilteredMethods;
1100     CompTimeInfo m_filtered;
1101
1102     // This can use what ever data you want to determine if the value to be added
1103     // belongs in the filtered section (it's always included in the unfiltered section)
1104     bool IncludedInFilteredData(CompTimeInfo& info);
1105
1106 public:
1107     // This is the unique CompTimeSummaryInfo object for this instance of the runtime.
1108     static CompTimeSummaryInfo s_compTimeSummary;
1109
1110     CompTimeSummaryInfo()
1111         : m_numMethods(0), m_totMethods(0), m_total(0), m_maximum(0), m_numFilteredMethods(0), m_filtered(0)
1112     {
1113     }
1114
1115     // Assumes that "info" is a completed CompTimeInfo for a compilation; adds it to the summary.
1116     // This is thread safe.
1117     void AddInfo(CompTimeInfo& info, bool includePhases);
1118
1119     // Print the summary information to "f".
1120     // This is not thread-safe; assumed to be called by only one thread.
1121     void Print(FILE* f);
1122 };
1123
1124 // A JitTimer encapsulates a CompTimeInfo for a single compilation. It also tracks the start of compilation,
1125 // and when the current phase started.  This is intended to be part of a Compilation object.  This is
1126 // disabled (FEATURE_JIT_METHOD_PERF not defined) when FEATURE_CORECLR is set, or on non-windows platforms.
1127 //
1128 class JitTimer
1129 {
1130     unsigned __int64 m_start;         // Start of the compilation.
1131     unsigned __int64 m_curPhaseStart; // Start of the current phase.
1132 #if MEASURE_CLRAPI_CALLS
1133     unsigned __int64 m_CLRcallStart;   // Start of the current CLR API call (if any).
1134     unsigned __int64 m_CLRcallInvokes; // CLR API invokes under current outer so far
1135     unsigned __int64 m_CLRcallCycles;  // CLR API  cycles under current outer so far.
1136     int              m_CLRcallAPInum;  // The enum/index of the current CLR API call (or -1).
1137     static double    s_cyclesPerSec;   // Cached for speedier measurements
1138 #endif
1139 #ifdef DEBUG
1140     Phases m_lastPhase; // The last phase that was completed (or (Phases)-1 to start).
1141 #endif
1142     CompTimeInfo m_info; // The CompTimeInfo for this compilation.
1143
1144     static CritSecObject s_csvLock; // Lock to protect the time log file.
1145     void PrintCsvMethodStats(Compiler* comp);
1146
1147 private:
1148     void* operator new(size_t);
1149     void* operator new[](size_t);
1150     void operator delete(void*);
1151     void operator delete[](void*);
1152
1153 public:
1154     // Initialized the timer instance
1155     JitTimer(unsigned byteCodeSize);
1156
1157     static JitTimer* Create(Compiler* comp, unsigned byteCodeSize)
1158     {
1159         return ::new (comp, CMK_Unknown) JitTimer(byteCodeSize);
1160     }
1161
1162     static void PrintCsvHeader();
1163
1164     // Ends the current phase (argument is for a redundant check).
1165     void EndPhase(Compiler* compiler, Phases phase);
1166
1167 #if MEASURE_CLRAPI_CALLS
1168     // Start and end a timed CLR API call.
1169     void CLRApiCallEnter(unsigned apix);
1170     void CLRApiCallLeave(unsigned apix);
1171 #endif // MEASURE_CLRAPI_CALLS
1172
1173     // Completes the timing of the current method, which is assumed to have "byteCodeBytes" bytes of bytecode,
1174     // and adds it to "sum".
1175     void Terminate(Compiler* comp, CompTimeSummaryInfo& sum, bool includePhases);
1176
1177     // Attempts to query the cycle counter of the current thread.  If successful, returns "true" and sets
1178     // *cycles to the cycle counter value.  Otherwise, returns false and sets the "m_timerFailure" flag of
1179     // "m_info" to true.
1180     bool GetThreadCycles(unsigned __int64* cycles)
1181     {
1182         bool res = CycleTimer::GetThreadCyclesS(cycles);
1183         if (!res)
1184         {
1185             m_info.m_timerFailure = true;
1186         }
1187         return res;
1188     }
1189 };
1190 #endif // FEATURE_JIT_METHOD_PERF
1191
1192 //------------------- Function/Funclet info -------------------------------
1193 enum FuncKind : BYTE
1194 {
1195     FUNC_ROOT,    // The main/root function (always id==0)
1196     FUNC_HANDLER, // a funclet associated with an EH handler (finally, fault, catch, filter handler)
1197     FUNC_FILTER,  // a funclet associated with an EH filter
1198     FUNC_COUNT
1199 };
1200
1201 class emitLocation;
1202
1203 struct FuncInfoDsc
1204 {
1205     FuncKind       funKind;
1206     BYTE           funFlags;   // Currently unused, just here for padding
1207     unsigned short funEHIndex; // index, into the ebd table, of innermost EH clause corresponding to this
1208                                // funclet. It is only valid if funKind field indicates this is a
1209                                // EH-related funclet: FUNC_HANDLER or FUNC_FILTER
1210
1211 #if defined(_TARGET_AMD64_)
1212
1213     // TODO-AMD64-Throughput: make the AMD64 info more like the ARM info to avoid having this large static array.
1214     emitLocation* startLoc;
1215     emitLocation* endLoc;
1216     emitLocation* coldStartLoc; // locations for the cold section, if there is one.
1217     emitLocation* coldEndLoc;
1218     UNWIND_INFO   unwindHeader;
1219     // Maximum of 255 UNWIND_CODE 'nodes' and then the unwind header. If there are an odd
1220     // number of codes, the VM or Zapper will 4-byte align the whole thing.
1221     BYTE     unwindCodes[offsetof(UNWIND_INFO, UnwindCode) + (0xFF * sizeof(UNWIND_CODE))];
1222     unsigned unwindCodeSlot;
1223
1224 #elif defined(_TARGET_X86_)
1225
1226 #if defined(_TARGET_UNIX_)
1227     emitLocation* startLoc;
1228     emitLocation* endLoc;
1229     emitLocation* coldStartLoc; // locations for the cold section, if there is one.
1230     emitLocation* coldEndLoc;
1231 #endif // _TARGET_UNIX_
1232
1233 #elif defined(_TARGET_ARMARCH_)
1234
1235     UnwindInfo  uwi;     // Unwind information for this function/funclet's hot  section
1236     UnwindInfo* uwiCold; // Unwind information for this function/funclet's cold section
1237                          //   Note: we only have a pointer here instead of the actual object,
1238                          //   to save memory in the JIT case (compared to the NGEN case),
1239                          //   where we don't have any cold section.
1240                          //   Note 2: we currently don't support hot/cold splitting in functions
1241                          //   with EH, so uwiCold will be NULL for all funclets.
1242
1243 #if defined(_TARGET_UNIX_)
1244     emitLocation* startLoc;
1245     emitLocation* endLoc;
1246     emitLocation* coldStartLoc; // locations for the cold section, if there is one.
1247     emitLocation* coldEndLoc;
1248 #endif // _TARGET_UNIX_
1249
1250 #endif // _TARGET_ARMARCH_
1251
1252 #if defined(_TARGET_UNIX_)
1253     jitstd::vector<CFI_CODE>* cfiCodes;
1254 #endif // _TARGET_UNIX_
1255
1256     // Eventually we may want to move rsModifiedRegsMask, lvaOutgoingArgSize, and anything else
1257     // that isn't shared between the main function body and funclets.
1258 };
1259
1260 struct fgArgTabEntry
1261 {
1262     GenTree* node;   // Initially points at the Op1 field of 'parent', but if the argument is replaced with an GT_ASG or
1263                      // placeholder it will point at the actual argument in the gtCallLateArgs list.
1264     GenTree* parent; // Points at the GT_LIST node in the gtCallArgs for this argument
1265
1266     unsigned argNum; // The original argument number, also specifies the required argument evaluation order from the IL
1267
1268 private:
1269     regNumberSmall regNums[MAX_ARG_REG_COUNT]; // The registers to use when passing this argument, set to REG_STK for
1270                                                // arguments passed on the stack
1271 public:
1272     unsigned numRegs; // Count of number of registers that this argument uses.
1273                       // Note that on ARM, if we have a double hfa, this reflects the number
1274                       // of DOUBLE registers.
1275
1276     // A slot is a pointer sized region in the OutArg area.
1277     unsigned slotNum;  // When an argument is passed in the OutArg area this is the slot number in the OutArg area
1278     unsigned numSlots; // Count of number of slots that this argument uses
1279
1280     unsigned alignment; // 1 or 2 (slots/registers)
1281 private:
1282     unsigned _lateArgInx; // index into gtCallLateArgs list; UINT_MAX if this is not a late arg.
1283 public:
1284     unsigned tmpNum; // the LclVar number if we had to force evaluation of this arg
1285
1286     var_types argType; // The type used to pass this argument. This is generally the original argument type, but when a
1287                        // struct is passed as a scalar type, this is that type.
1288                        // Note that if a struct is passed by reference, this will still be the struct type.
1289
1290     bool needTmp : 1;       // True when we force this argument's evaluation into a temp LclVar
1291     bool needPlace : 1;     // True when we must replace this argument with a placeholder node
1292     bool isTmp : 1;         // True when we setup a temp LclVar for this argument due to size issues with the struct
1293     bool processed : 1;     // True when we have decided the evaluation order for this argument in the gtCallLateArgs
1294     bool isBackFilled : 1;  // True when the argument fills a register slot skipped due to alignment requirements of
1295                             // previous arguments.
1296     bool isNonStandard : 1; // True if it is an arg that is passed in a reg other than a standard arg reg, or is forced
1297                             // to be on the stack despite its arg list position.
1298     bool isStruct : 1;      // True if this is a struct arg
1299     bool _isVararg : 1;     // True if the argument is in a vararg context.
1300     bool passedByRef : 1;   // True iff the argument is passed by reference.
1301 #ifdef FEATURE_ARG_SPLIT
1302     bool _isSplit : 1; // True when this argument is split between the registers and OutArg area
1303 #endif                 // FEATURE_ARG_SPLIT
1304 #ifdef FEATURE_HFA
1305     bool _isHfaArg : 1;    // True when the argument is an HFA type.
1306     bool _isDoubleHfa : 1; // True when the argument is an HFA, with an element type of DOUBLE.
1307 #endif
1308
1309     bool isLateArg()
1310     {
1311         bool isLate = (_lateArgInx != UINT_MAX);
1312         return isLate;
1313     }
1314
1315     __declspec(property(get = getLateArgInx, put = setLateArgInx)) unsigned lateArgInx;
1316     unsigned getLateArgInx()
1317     {
1318         assert(isLateArg());
1319         return _lateArgInx;
1320     }
1321     void setLateArgInx(unsigned inx)
1322     {
1323         _lateArgInx = inx;
1324     }
1325     __declspec(property(get = getRegNum)) regNumber regNum;
1326     regNumber getRegNum()
1327     {
1328         return (regNumber)regNums[0];
1329     }
1330     __declspec(property(get = getOtherRegNum)) regNumber otherRegNum;
1331     regNumber getOtherRegNum()
1332     {
1333         return (regNumber)regNums[1];
1334     }
1335
1336 #if defined(UNIX_AMD64_ABI)
1337     SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
1338 #endif
1339
1340     void setRegNum(unsigned int i, regNumber regNum)
1341     {
1342         assert(i < MAX_ARG_REG_COUNT);
1343         regNums[i] = (regNumberSmall)regNum;
1344     }
1345     regNumber getRegNum(unsigned int i)
1346     {
1347         assert(i < MAX_ARG_REG_COUNT);
1348         return (regNumber)regNums[i];
1349     }
1350
1351     __declspec(property(get = getIsSplit, put = setIsSplit)) bool isSplit;
1352     bool getIsSplit()
1353     {
1354 #ifdef FEATURE_ARG_SPLIT
1355         return _isSplit;
1356 #else // FEATURE_ARG_SPLIT
1357         return false;
1358 #endif
1359     }
1360     void setIsSplit(bool value)
1361     {
1362 #ifdef FEATURE_ARG_SPLIT
1363         _isSplit = value;
1364 #endif
1365     }
1366
1367     __declspec(property(get = getIsVararg, put = setIsVararg)) bool isVararg;
1368     bool getIsVararg()
1369     {
1370 #ifdef FEATURE_VARARG
1371         return _isVararg;
1372 #else
1373         return false;
1374 #endif
1375     }
1376     void setIsVararg(bool value)
1377     {
1378 #ifdef FEATURE_VARARG
1379         _isVararg = value;
1380 #endif // FEATURE_VARARG
1381     }
1382
1383     __declspec(property(get = getIsHfaArg)) bool isHfaArg;
1384     bool getIsHfaArg()
1385     {
1386 #ifdef FEATURE_HFA
1387         return _isHfaArg;
1388 #else
1389         return false;
1390 #endif
1391     }
1392
1393     __declspec(property(get = getIsHfaRegArg)) bool isHfaRegArg;
1394     bool getIsHfaRegArg()
1395     {
1396 #ifdef FEATURE_HFA
1397         return _isHfaArg && isPassedInRegisters();
1398 #else
1399         return false;
1400 #endif
1401     }
1402
1403     __declspec(property(get = getHfaType)) var_types hfaType;
1404     var_types getHfaType()
1405     {
1406 #ifdef FEATURE_HFA
1407         return _isHfaArg ? (_isDoubleHfa ? TYP_DOUBLE : TYP_FLOAT) : TYP_UNDEF;
1408 #else
1409         return TYP_UNDEF;
1410 #endif
1411     }
1412
1413     void setHfaType(var_types type, unsigned hfaSlots)
1414     {
1415 #ifdef FEATURE_HFA
1416         if (type != TYP_UNDEF)
1417         {
1418             // We must already have set the passing mode.
1419             assert(numRegs != 0 || numSlots != 0);
1420             // We originally set numRegs according to the size of the struct, but if the size of the
1421             // hfaType is not the same as the pointer size, we need to correct it.
1422             // Note that hfaSlots is the number of registers we will use. For ARM, that is twice
1423             // the number of "double registers".
1424             unsigned numHfaRegs = hfaSlots;
1425             if (isPassedInRegisters())
1426             {
1427 #ifdef _TARGET_ARM_
1428                 if (type == TYP_DOUBLE)
1429                 {
1430                     // Must be an even number of registers.
1431                     assert((numRegs & 1) == 0);
1432                     numHfaRegs = hfaSlots / 2;
1433                 }
1434 #endif // _TARGET_ARM_
1435                 if (_isHfaArg)
1436                 {
1437                     // This should already be set correctly.
1438                     assert(numRegs == numHfaRegs);
1439                     assert(_isDoubleHfa == (type == TYP_DOUBLE));
1440                 }
1441                 else
1442                 {
1443                     numRegs = numHfaRegs;
1444                 }
1445             }
1446             _isDoubleHfa = (type == TYP_DOUBLE);
1447             _isHfaArg    = true;
1448         }
1449 #endif // FEATURE_HFA
1450     }
1451
1452 #ifdef _TARGET_ARM_
1453     void SetIsBackFilled(bool backFilled)
1454     {
1455         isBackFilled = backFilled;
1456     }
1457
1458     bool IsBackFilled() const
1459     {
1460         return isBackFilled;
1461     }
1462 #else  // !_TARGET_ARM_
1463     void SetIsBackFilled(bool backFilled)
1464     {
1465     }
1466
1467     bool IsBackFilled() const
1468     {
1469         return false;
1470     }
1471 #endif // !_TARGET_ARM_
1472
1473     bool isPassedInRegisters()
1474     {
1475         return !isSplit && (numRegs != 0);
1476     }
1477
1478     bool isPassedInFloatRegisters()
1479     {
1480 #ifdef _TARGET_X86
1481         return false;
1482 #else
1483         return isValidFloatArgReg(regNum);
1484 #endif
1485     }
1486
1487     bool isSingleRegOrSlot()
1488     {
1489         return !isSplit && ((numRegs == 1) || (numSlots == 1));
1490     }
1491
1492     // Returns the number of "slots" used, where for this purpose a
1493     // register counts as a slot.
1494     unsigned getSlotCount()
1495     {
1496         if (isBackFilled)
1497         {
1498             assert(isPassedInRegisters());
1499             assert(numRegs == 1);
1500         }
1501         else if (regNum == REG_STK)
1502         {
1503             assert(!isPassedInRegisters());
1504             assert(numRegs == 0);
1505         }
1506         else
1507         {
1508             assert(numRegs > 0);
1509         }
1510         return numSlots + numRegs;
1511     }
1512
1513     // Returns the size as a multiple of pointer-size.
1514     // For targets without HFAs, this is the same as getSlotCount().
1515     unsigned getSize()
1516     {
1517         unsigned size = getSlotCount();
1518 #ifdef FEATURE_HFA
1519 #ifdef _TARGET_ARM_
1520         // We counted the number of regs, but if they are DOUBLE hfa regs we have to double the size.
1521         if (isHfaRegArg && (hfaType == TYP_DOUBLE))
1522         {
1523             assert(!isSplit);
1524             size <<= 1;
1525         }
1526 #elif defined(_TARGET_ARM64_)
1527         // We counted the number of regs, but if they are FLOAT hfa regs we have to halve the size.
1528         if (isHfaRegArg && (hfaType == TYP_FLOAT))
1529         {
1530             // Round up in case of odd HFA count.
1531             size = (size + 1) >> 1;
1532         }
1533 #endif // _TARGET_ARM64_
1534 #endif
1535         return size;
1536     }
1537
1538     // Set the register numbers for a multireg argument.
1539     // There's nothing to do on x64/Ux because the structDesc has already been used to set the
1540     // register numbers.
1541     void SetMultiRegNums()
1542     {
1543 #if FEATURE_MULTIREG_ARGS && !defined(UNIX_AMD64_ABI)
1544         if (numRegs == 1)
1545         {
1546             return;
1547         }
1548
1549         regNumber argReg = getRegNum(0);
1550 #ifdef _TARGET_ARM_
1551         unsigned int regSize = (hfaType == TYP_DOUBLE) ? 2 : 1;
1552 #else
1553         unsigned int regSize = 1;
1554 #endif
1555         for (unsigned int regIndex = 1; regIndex < numRegs; regIndex++)
1556         {
1557             argReg = (regNumber)(argReg + regSize);
1558             setRegNum(regIndex, argReg);
1559         }
1560 #endif // FEATURE_MULTIREG_ARGS && !defined(UNIX_AMD64_ABI)
1561     }
1562
1563     // Check that the value of 'isStruct' is consistent.
1564     // A struct arg must be one of the following:
1565     // - A node of struct type,
1566     // - A GT_FIELD_LIST, or
1567     // - A node of a scalar type, passed in a single register or slot
1568     //   (or two slots in the case of a struct pass on the stack as TYP_DOUBLE).
1569     //
1570     void checkIsStruct()
1571     {
1572         if (isStruct)
1573         {
1574             if (!varTypeIsStruct(node) && !node->OperIs(GT_FIELD_LIST))
1575             {
1576                 // This is the case where we are passing a struct as a primitive type.
1577                 // On most targets, this is always a single register or slot.
1578                 // However, on ARM this could be two slots if it is TYP_DOUBLE.
1579                 bool isPassedAsPrimitiveType = ((numRegs == 1) || ((numRegs == 0) && (numSlots == 1)));
1580 #ifdef _TARGET_ARM_
1581                 if (!isPassedAsPrimitiveType)
1582                 {
1583                     if (node->TypeGet() == TYP_DOUBLE && numRegs == 0 && (numSlots == 2))
1584                     {
1585                         isPassedAsPrimitiveType = true;
1586                     }
1587                 }
1588 #endif // _TARGET_ARM_
1589                 assert(isPassedAsPrimitiveType);
1590             }
1591         }
1592         else
1593         {
1594             assert(!varTypeIsStruct(node));
1595         }
1596     }
1597
1598 #ifdef DEBUG
1599     void Dump();
1600 #endif
1601 };
1602
1603 //-------------------------------------------------------------------------
1604 //
1605 //  The class fgArgInfo is used to handle the arguments
1606 //  when morphing a GT_CALL node.
1607 //
1608
1609 class fgArgInfo
1610 {
1611     Compiler*    compiler;    // Back pointer to the compiler instance so that we can allocate memory
1612     GenTreeCall* callTree;    // Back pointer to the GT_CALL node for this fgArgInfo
1613     unsigned     argCount;    // Updatable arg count value
1614     unsigned     nextSlotNum; // Updatable slot count value
1615     unsigned     stkLevel;    // Stack depth when we make this call (for x86)
1616
1617 #if defined(UNIX_X86_ABI)
1618     bool     alignmentDone; // Updateable flag, set to 'true' after we've done any required alignment.
1619     unsigned stkSizeBytes;  // Size of stack used by this call, in bytes. Calculated during fgMorphArgs().
1620     unsigned padStkAlign;   // Stack alignment in bytes required before arguments are pushed for this call.
1621                             // Computed dynamically during codegen, based on stkSizeBytes and the current
1622                             // stack level (genStackLevel) when the first stack adjustment is made for
1623                             // this call.
1624 #endif
1625
1626 #if FEATURE_FIXED_OUT_ARGS
1627     unsigned outArgSize; // Size of the out arg area for the call, will be at least MIN_ARG_AREA_FOR_CALL
1628 #endif
1629
1630     unsigned        argTableSize; // size of argTable array (equal to the argCount when done with fgMorphArgs)
1631     bool            hasRegArgs;   // true if we have one or more register arguments
1632     bool            hasStackArgs; // true if we have one or more stack arguments
1633     bool            argsComplete; // marker for state
1634     bool            argsSorted;   // marker for state
1635     bool            needsTemps;   // one or more arguments must be copied to a temp by EvalArgsToTemps
1636     fgArgTabEntry** argTable;     // variable sized array of per argument descrption: (i.e. argTable[argTableSize])
1637
1638 private:
1639     void AddArg(fgArgTabEntry* curArgTabEntry);
1640
1641 public:
1642     fgArgInfo(Compiler* comp, GenTreeCall* call, unsigned argCount);
1643     fgArgInfo(GenTreeCall* newCall, GenTreeCall* oldCall);
1644
1645     fgArgTabEntry* AddRegArg(unsigned  argNum,
1646                              GenTree*  node,
1647                              GenTree*  parent,
1648                              regNumber regNum,
1649                              unsigned  numRegs,
1650                              unsigned  alignment,
1651                              bool      isStruct,
1652                              bool      isVararg = false);
1653
1654 #ifdef UNIX_AMD64_ABI
1655     fgArgTabEntry* AddRegArg(unsigned                                                         argNum,
1656                              GenTree*                                                         node,
1657                              GenTree*                                                         parent,
1658                              regNumber                                                        regNum,
1659                              unsigned                                                         numRegs,
1660                              unsigned                                                         alignment,
1661                              const bool                                                       isStruct,
1662                              const bool                                                       isVararg,
1663                              const regNumber                                                  otherRegNum,
1664                              const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* const structDescPtr = nullptr);
1665 #endif // UNIX_AMD64_ABI
1666
1667     fgArgTabEntry* AddStkArg(unsigned argNum,
1668                              GenTree* node,
1669                              GenTree* parent,
1670                              unsigned numSlots,
1671                              unsigned alignment,
1672                              bool     isStruct,
1673                              bool     isVararg = false);
1674
1675     void RemorphReset();
1676     void UpdateRegArg(fgArgTabEntry* argEntry, GenTree* node, bool reMorphing);
1677     void UpdateStkArg(fgArgTabEntry* argEntry, GenTree* node, bool reMorphing);
1678
1679     void SplitArg(unsigned argNum, unsigned numRegs, unsigned numSlots);
1680
1681     void EvalToTmp(fgArgTabEntry* curArgTabEntry, unsigned tmpNum, GenTree* newNode);
1682
1683     void ArgsComplete();
1684
1685     void SortArgs();
1686
1687     void EvalArgsToTemps();
1688
1689     unsigned ArgCount()
1690     {
1691         return argCount;
1692     }
1693     fgArgTabEntry** ArgTable()
1694     {
1695         return argTable;
1696     }
1697     unsigned GetNextSlotNum()
1698     {
1699         return nextSlotNum;
1700     }
1701     bool HasRegArgs()
1702     {
1703         return hasRegArgs;
1704     }
1705     bool NeedsTemps()
1706     {
1707         return needsTemps;
1708     }
1709     bool HasStackArgs()
1710     {
1711         return hasStackArgs;
1712     }
1713     bool AreArgsComplete() const
1714     {
1715         return argsComplete;
1716     }
1717 #if FEATURE_FIXED_OUT_ARGS
1718     unsigned GetOutArgSize() const
1719     {
1720         return outArgSize;
1721     }
1722     void SetOutArgSize(unsigned newVal)
1723     {
1724         outArgSize = newVal;
1725     }
1726 #endif // FEATURE_FIXED_OUT_ARGS
1727
1728 #if defined(UNIX_X86_ABI)
1729     void ComputeStackAlignment(unsigned curStackLevelInBytes)
1730     {
1731         padStkAlign = AlignmentPad(curStackLevelInBytes, STACK_ALIGN);
1732     }
1733
1734     unsigned GetStkAlign()
1735     {
1736         return padStkAlign;
1737     }
1738
1739     void SetStkSizeBytes(unsigned newStkSizeBytes)
1740     {
1741         stkSizeBytes = newStkSizeBytes;
1742     }
1743
1744     unsigned GetStkSizeBytes() const
1745     {
1746         return stkSizeBytes;
1747     }
1748
1749     bool IsStkAlignmentDone() const
1750     {
1751         return alignmentDone;
1752     }
1753
1754     void SetStkAlignmentDone()
1755     {
1756         alignmentDone = true;
1757     }
1758 #endif // defined(UNIX_X86_ABI)
1759
1760     // Get the fgArgTabEntry for the arg at position argNum.
1761     fgArgTabEntry* GetArgEntry(unsigned argNum, bool reMorphing = true)
1762     {
1763         fgArgTabEntry* curArgTabEntry = nullptr;
1764
1765         if (!reMorphing)
1766         {
1767             // The arg table has not yet been sorted.
1768             curArgTabEntry = argTable[argNum];
1769             assert(curArgTabEntry->argNum == argNum);
1770             return curArgTabEntry;
1771         }
1772
1773         for (unsigned i = 0; i < argCount; i++)
1774         {
1775             curArgTabEntry = argTable[i];
1776             if (curArgTabEntry->argNum == argNum)
1777             {
1778                 return curArgTabEntry;
1779             }
1780         }
1781         noway_assert(!"GetArgEntry: argNum not found");
1782         return nullptr;
1783     }
1784
1785     // Get the node for the arg at position argIndex.
1786     // Caller must ensure that this index is a valid arg index.
1787     GenTree* GetArgNode(unsigned argIndex)
1788     {
1789         return GetArgEntry(argIndex)->node;
1790     }
1791
1792     void Dump(Compiler* compiler);
1793 };
1794
1795 #ifdef DEBUG
1796 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1797 // We have the ability to mark source expressions with "Test Labels."
1798 // These drive assertions within the JIT, or internal JIT testing.  For example, we could label expressions
1799 // that should be CSE defs, and other expressions that should uses of those defs, with a shared label.
1800
1801 enum TestLabel // This must be kept identical to System.Runtime.CompilerServices.JitTestLabel.TestLabel.
1802 {
1803     TL_SsaName,
1804     TL_VN,        // Defines a "VN equivalence class".  (For full VN, including exceptions thrown).
1805     TL_VNNorm,    // Like above, but uses the non-exceptional value of the expression.
1806     TL_CSE_Def,   //  This must be identified in the JIT as a CSE def
1807     TL_CSE_Use,   //  This must be identified in the JIT as a CSE use
1808     TL_LoopHoist, // Expression must (or must not) be hoisted out of the loop.
1809 };
1810
1811 struct TestLabelAndNum
1812 {
1813     TestLabel m_tl;
1814     ssize_t   m_num;
1815
1816     TestLabelAndNum() : m_tl(TestLabel(0)), m_num(0)
1817     {
1818     }
1819 };
1820
1821 typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, TestLabelAndNum> NodeToTestDataMap;
1822
1823 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1824 #endif // DEBUG
1825
1826 /*
1827 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1828 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1829 XX                                                                           XX
1830 XX   The big guy. The sections are currently organized as :                  XX
1831 XX                                                                           XX
1832 XX    o  GenTree and BasicBlock                                              XX
1833 XX    o  LclVarsInfo                                                         XX
1834 XX    o  Importer                                                            XX
1835 XX    o  FlowGraph                                                           XX
1836 XX    o  Optimizer                                                           XX
1837 XX    o  RegAlloc                                                            XX
1838 XX    o  EEInterface                                                         XX
1839 XX    o  TempsInfo                                                           XX
1840 XX    o  RegSet                                                              XX
1841 XX    o  GCInfo                                                              XX
1842 XX    o  Instruction                                                         XX
1843 XX    o  ScopeInfo                                                           XX
1844 XX    o  PrologScopeInfo                                                     XX
1845 XX    o  CodeGenerator                                                       XX
1846 XX    o  UnwindInfo                                                          XX
1847 XX    o  Compiler                                                            XX
1848 XX    o  typeInfo                                                            XX
1849 XX                                                                           XX
1850 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1851 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1852 */
1853
1854 struct HWIntrinsicInfo;
1855
1856 class Compiler
1857 {
1858     friend class emitter;
1859     friend class UnwindInfo;
1860     friend class UnwindFragmentInfo;
1861     friend class UnwindEpilogInfo;
1862     friend class JitTimer;
1863     friend class LinearScan;
1864     friend class fgArgInfo;
1865     friend class Rationalizer;
1866     friend class Phase;
1867     friend class Lowering;
1868     friend class CSE_DataFlow;
1869     friend class CSE_Heuristic;
1870     friend class CodeGenInterface;
1871     friend class CodeGen;
1872     friend class LclVarDsc;
1873     friend class TempDsc;
1874     friend class LIR;
1875     friend class ObjectAllocator;
1876     friend class LocalAddressVisitor;
1877     friend struct GenTree;
1878
1879 #ifdef FEATURE_HW_INTRINSICS
1880     friend struct HWIntrinsicInfo;
1881 #endif // FEATURE_HW_INTRINSICS
1882
1883 #ifndef _TARGET_64BIT_
1884     friend class DecomposeLongs;
1885 #endif // !_TARGET_64BIT_
1886
1887     /*
1888     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1889     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1890     XX                                                                           XX
1891     XX  Misc structs definitions                                                 XX
1892     XX                                                                           XX
1893     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1894     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1895     */
1896
1897 public:
1898     hashBvGlobalData hbvGlobalData; // Used by the hashBv bitvector package.
1899
1900 #ifdef DEBUG
1901     bool    verbose;
1902     bool    dumpIR;
1903     bool    dumpIRNodes;
1904     bool    dumpIRTypes;
1905     bool    dumpIRKinds;
1906     bool    dumpIRLocals;
1907     bool    dumpIRRegs;
1908     bool    dumpIRSsa;
1909     bool    dumpIRValnums;
1910     bool    dumpIRCosts;
1911     bool    dumpIRFlags;
1912     bool    dumpIRNoLists;
1913     bool    dumpIRNoLeafs;
1914     bool    dumpIRNoStmts;
1915     bool    dumpIRTrees;
1916     bool    dumpIRLinear;
1917     bool    dumpIRDataflow;
1918     bool    dumpIRBlockHeaders;
1919     bool    dumpIRExit;
1920     LPCWSTR dumpIRPhase;
1921     LPCWSTR dumpIRFormat;
1922     bool    verboseTrees;
1923     bool    shouldUseVerboseTrees();
1924     bool    asciiTrees; // If true, dump trees using only ASCII characters
1925     bool    shouldDumpASCIITrees();
1926     bool    verboseSsa; // If true, produce especially verbose dump output in SSA construction.
1927     bool    shouldUseVerboseSsa();
1928     bool    treesBeforeAfterMorph; // If true, print trees before/after morphing (paired by an intra-compilation id:
1929     int     morphNum; // This counts the the trees that have been morphed, allowing us to label each uniquely.
1930
1931     const char* VarNameToStr(VarName name)
1932     {
1933         return name;
1934     }
1935
1936     DWORD expensiveDebugCheckLevel;
1937 #endif
1938
1939 #if FEATURE_MULTIREG_RET
1940     GenTree* impAssignMultiRegTypeToVar(GenTree* op, CORINFO_CLASS_HANDLE hClass);
1941 #endif // FEATURE_MULTIREG_RET
1942
1943     GenTree* impAssignSmallStructTypeToVar(GenTree* op, CORINFO_CLASS_HANDLE hClass);
1944
1945 #ifdef ARM_SOFTFP
1946     bool isSingleFloat32Struct(CORINFO_CLASS_HANDLE hClass);
1947 #endif // ARM_SOFTFP
1948
1949     //-------------------------------------------------------------------------
1950     // Functions to handle homogeneous floating-point aggregates (HFAs) in ARM.
1951     // HFAs are one to four element structs where each element is the same
1952     // type, either all float or all double. They are treated specially
1953     // in the ARM Procedure Call Standard, specifically, they are passed in
1954     // floating-point registers instead of the general purpose registers.
1955     //
1956
1957     bool IsHfa(CORINFO_CLASS_HANDLE hClass);
1958     bool IsHfa(GenTree* tree);
1959
1960     var_types GetHfaType(GenTree* tree);
1961     unsigned GetHfaCount(GenTree* tree);
1962
1963     var_types GetHfaType(CORINFO_CLASS_HANDLE hClass);
1964     unsigned GetHfaCount(CORINFO_CLASS_HANDLE hClass);
1965
1966     bool IsMultiRegReturnedType(CORINFO_CLASS_HANDLE hClass);
1967
1968     //-------------------------------------------------------------------------
1969     // The following is used for validating format of EH table
1970     //
1971
1972     struct EHNodeDsc;
1973     typedef struct EHNodeDsc* pEHNodeDsc;
1974
1975     EHNodeDsc* ehnTree; // root of the tree comprising the EHnodes.
1976     EHNodeDsc* ehnNext; // root of the tree comprising the EHnodes.
1977
1978     struct EHNodeDsc
1979     {
1980         enum EHBlockType
1981         {
1982             TryNode,
1983             FilterNode,
1984             HandlerNode,
1985             FinallyNode,
1986             FaultNode
1987         };
1988
1989         EHBlockType ehnBlockType;   // kind of EH block
1990         IL_OFFSET   ehnStartOffset; // IL offset of start of the EH block
1991         IL_OFFSET ehnEndOffset; // IL offset past end of the EH block. (TODO: looks like verInsertEhNode() sets this to
1992                                 // the last IL offset, not "one past the last one", i.e., the range Start to End is
1993                                 // inclusive).
1994         pEHNodeDsc ehnNext;     // next (non-nested) block in sequential order
1995         pEHNodeDsc ehnChild;    // leftmost nested block
1996         union {
1997             pEHNodeDsc ehnTryNode;     // for filters and handlers, the corresponding try node
1998             pEHNodeDsc ehnHandlerNode; // for a try node, the corresponding handler node
1999         };
2000         pEHNodeDsc ehnFilterNode; // if this is a try node and has a filter, otherwise 0
2001         pEHNodeDsc ehnEquivalent; // if blockType=tryNode, start offset and end offset is same,
2002
2003         void ehnSetTryNodeType()
2004         {
2005             ehnBlockType = TryNode;
2006         }
2007         void ehnSetFilterNodeType()
2008         {
2009             ehnBlockType = FilterNode;
2010         }
2011         void ehnSetHandlerNodeType()
2012         {
2013             ehnBlockType = HandlerNode;
2014         }
2015         void ehnSetFinallyNodeType()
2016         {
2017             ehnBlockType = FinallyNode;
2018         }
2019         void ehnSetFaultNodeType()
2020         {
2021             ehnBlockType = FaultNode;
2022         }
2023
2024         BOOL ehnIsTryBlock()
2025         {
2026             return ehnBlockType == TryNode;
2027         }
2028         BOOL ehnIsFilterBlock()
2029         {
2030             return ehnBlockType == FilterNode;
2031         }
2032         BOOL ehnIsHandlerBlock()
2033         {
2034             return ehnBlockType == HandlerNode;
2035         }
2036         BOOL ehnIsFinallyBlock()
2037         {
2038             return ehnBlockType == FinallyNode;
2039         }
2040         BOOL ehnIsFaultBlock()
2041         {
2042             return ehnBlockType == FaultNode;
2043         }
2044
2045         // returns true if there is any overlap between the two nodes
2046         static BOOL ehnIsOverlap(pEHNodeDsc node1, pEHNodeDsc node2)
2047         {
2048             if (node1->ehnStartOffset < node2->ehnStartOffset)
2049             {
2050                 return (node1->ehnEndOffset >= node2->ehnStartOffset);
2051             }
2052             else
2053             {
2054                 return (node1->ehnStartOffset <= node2->ehnEndOffset);
2055             }
2056         }
2057
2058         // fails with BADCODE if inner is not completely nested inside outer
2059         static BOOL ehnIsNested(pEHNodeDsc inner, pEHNodeDsc outer)
2060         {
2061             return ((inner->ehnStartOffset >= outer->ehnStartOffset) && (inner->ehnEndOffset <= outer->ehnEndOffset));
2062         }
2063     };
2064
2065 //-------------------------------------------------------------------------
2066 // Exception handling functions
2067 //
2068
2069 #if !FEATURE_EH_FUNCLETS
2070
2071     bool ehNeedsShadowSPslots()
2072     {
2073         return (info.compXcptnsCount || opts.compDbgEnC);
2074     }
2075
2076     // 0 for methods with no EH
2077     // 1 for methods with non-nested EH, or where only the try blocks are nested
2078     // 2 for a method with a catch within a catch
2079     // etc.
2080     unsigned ehMaxHndNestingCount;
2081
2082 #endif // !FEATURE_EH_FUNCLETS
2083
2084     static bool jitIsBetween(unsigned value, unsigned start, unsigned end);
2085     static bool jitIsBetweenInclusive(unsigned value, unsigned start, unsigned end);
2086
2087     bool bbInCatchHandlerILRange(BasicBlock* blk);
2088     bool bbInFilterILRange(BasicBlock* blk);
2089     bool bbInTryRegions(unsigned regionIndex, BasicBlock* blk);
2090     bool bbInExnFlowRegions(unsigned regionIndex, BasicBlock* blk);
2091     bool bbInHandlerRegions(unsigned regionIndex, BasicBlock* blk);
2092     bool bbInCatchHandlerRegions(BasicBlock* tryBlk, BasicBlock* hndBlk);
2093     unsigned short bbFindInnermostCommonTryRegion(BasicBlock* bbOne, BasicBlock* bbTwo);
2094
2095     unsigned short bbFindInnermostTryRegionContainingHandlerRegion(unsigned handlerIndex);
2096     unsigned short bbFindInnermostHandlerRegionContainingTryRegion(unsigned tryIndex);
2097
2098     // Returns true if "block" is the start of a try region.
2099     bool bbIsTryBeg(BasicBlock* block);
2100
2101     // Returns true if "block" is the start of a handler or filter region.
2102     bool bbIsHandlerBeg(BasicBlock* block);
2103
2104     // Returns true iff "block" is where control flows if an exception is raised in the
2105     // try region, and sets "*regionIndex" to the index of the try for the handler.
2106     // Differs from "IsHandlerBeg" in the case of filters, where this is true for the first
2107     // block of the filter, but not for the filter's handler.
2108     bool bbIsExFlowBlock(BasicBlock* block, unsigned* regionIndex);
2109
2110     bool ehHasCallableHandlers();
2111
2112     // Return the EH descriptor for the given region index.
2113     EHblkDsc* ehGetDsc(unsigned regionIndex);
2114
2115     // Return the EH index given a region descriptor.
2116     unsigned ehGetIndex(EHblkDsc* ehDsc);
2117
2118     // Return the EH descriptor index of the enclosing try, for the given region index.
2119     unsigned ehGetEnclosingTryIndex(unsigned regionIndex);
2120
2121     // Return the EH descriptor index of the enclosing handler, for the given region index.
2122     unsigned ehGetEnclosingHndIndex(unsigned regionIndex);
2123
2124     // Return the EH descriptor for the most nested 'try' region this BasicBlock is a member of (or nullptr if this
2125     // block is not in a 'try' region).
2126     EHblkDsc* ehGetBlockTryDsc(BasicBlock* block);
2127
2128     // Return the EH descriptor for the most nested filter or handler region this BasicBlock is a member of (or nullptr
2129     // if this block is not in a filter or handler region).
2130     EHblkDsc* ehGetBlockHndDsc(BasicBlock* block);
2131
2132     // Return the EH descriptor for the most nested region that may handle exceptions raised in this BasicBlock (or
2133     // nullptr if this block's exceptions propagate to caller).
2134     EHblkDsc* ehGetBlockExnFlowDsc(BasicBlock* block);
2135
2136     EHblkDsc* ehIsBlockTryLast(BasicBlock* block);
2137     EHblkDsc* ehIsBlockHndLast(BasicBlock* block);
2138     bool ehIsBlockEHLast(BasicBlock* block);
2139
2140     bool ehBlockHasExnFlowDsc(BasicBlock* block);
2141
2142     // Return the region index of the most nested EH region this block is in.
2143     unsigned ehGetMostNestedRegionIndex(BasicBlock* block, bool* inTryRegion);
2144
2145     // Find the true enclosing try index, ignoring 'mutual protect' try. Uses IL ranges to check.
2146     unsigned ehTrueEnclosingTryIndexIL(unsigned regionIndex);
2147
2148     // Return the index of the most nested enclosing region for a particular EH region. Returns NO_ENCLOSING_INDEX
2149     // if there is no enclosing region. If the returned index is not NO_ENCLOSING_INDEX, then '*inTryRegion'
2150     // is set to 'true' if the enclosing region is a 'try', or 'false' if the enclosing region is a handler.
2151     // (It can never be a filter.)
2152     unsigned ehGetEnclosingRegionIndex(unsigned regionIndex, bool* inTryRegion);
2153
2154     // A block has been deleted. Update the EH table appropriately.
2155     void ehUpdateForDeletedBlock(BasicBlock* block);
2156
2157     // Determine whether a block can be deleted while preserving the EH normalization rules.
2158     bool ehCanDeleteEmptyBlock(BasicBlock* block);
2159
2160     // Update the 'last' pointers in the EH table to reflect new or deleted blocks in an EH region.
2161     void ehUpdateLastBlocks(BasicBlock* oldLast, BasicBlock* newLast);
2162
2163     // For a finally handler, find the region index that the BBJ_CALLFINALLY lives in that calls the handler,
2164     // or NO_ENCLOSING_INDEX if the BBJ_CALLFINALLY lives in the main function body. Normally, the index
2165     // is the same index as the handler (and the BBJ_CALLFINALLY lives in the 'try' region), but for AMD64 the
2166     // BBJ_CALLFINALLY lives in the enclosing try or handler region, whichever is more nested, or the main function
2167     // body. If the returned index is not NO_ENCLOSING_INDEX, then '*inTryRegion' is set to 'true' if the
2168     // BBJ_CALLFINALLY lives in the returned index's 'try' region, or 'false' if lives in the handler region. (It never
2169     // lives in a filter.)
2170     unsigned ehGetCallFinallyRegionIndex(unsigned finallyIndex, bool* inTryRegion);
2171
2172     // Find the range of basic blocks in which all BBJ_CALLFINALLY will be found that target the 'finallyIndex' region's
2173     // handler. Set begBlk to the first block, and endBlk to the block after the last block of the range
2174     // (nullptr if the last block is the last block in the program).
2175     // Precondition: 'finallyIndex' is the EH region of a try/finally clause.
2176     void ehGetCallFinallyBlockRange(unsigned finallyIndex, BasicBlock** begBlk, BasicBlock** endBlk);
2177
2178 #ifdef DEBUG
2179     // Given a BBJ_CALLFINALLY block and the EH region index of the finally it is calling, return
2180     // 'true' if the BBJ_CALLFINALLY is in the correct EH region.
2181     bool ehCallFinallyInCorrectRegion(BasicBlock* blockCallFinally, unsigned finallyIndex);
2182 #endif // DEBUG
2183
2184 #if FEATURE_EH_FUNCLETS
2185     // Do we need a PSPSym in the main function? For codegen purposes, we only need one
2186     // if there is a filter that protects a region with a nested EH clause (such as a
2187     // try/catch nested in the 'try' body of a try/filter/filter-handler). See
2188     // genFuncletProlog() for more details. However, the VM seems to use it for more
2189     // purposes, maybe including debugging. Until we are sure otherwise, always create
2190     // a PSPSym for functions with any EH.
2191     bool ehNeedsPSPSym() const
2192     {
2193 #ifdef _TARGET_X86_
2194         return false;
2195 #else  // _TARGET_X86_
2196         return compHndBBtabCount > 0;
2197 #endif // _TARGET_X86_
2198     }
2199
2200     bool     ehAnyFunclets();  // Are there any funclets in this function?
2201     unsigned ehFuncletCount(); // Return the count of funclets in the function
2202
2203     unsigned bbThrowIndex(BasicBlock* blk); // Get the index to use as the cache key for sharing throw blocks
2204 #else                                       // !FEATURE_EH_FUNCLETS
2205     bool ehAnyFunclets()
2206     {
2207         return false;
2208     }
2209     unsigned ehFuncletCount()
2210     {
2211         return 0;
2212     }
2213
2214     unsigned bbThrowIndex(BasicBlock* blk)
2215     {
2216         return blk->bbTryIndex;
2217     } // Get the index to use as the cache key for sharing throw blocks
2218 #endif                                      // !FEATURE_EH_FUNCLETS
2219
2220     // Returns a flowList representing the "EH predecessors" of "blk".  These are the normal predecessors of
2221     // "blk", plus one special case: if "blk" is the first block of a handler, considers the predecessor(s) of the first
2222     // first block of the corresponding try region to be "EH predecessors".  (If there is a single such predecessor,
2223     // for example, we want to consider that the immediate dominator of the catch clause start block, so it's
2224     // convenient to also consider it a predecessor.)
2225     flowList* BlockPredsWithEH(BasicBlock* blk);
2226
2227     // This table is useful for memoization of the method above.
2228     typedef JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, flowList*> BlockToFlowListMap;
2229     BlockToFlowListMap* m_blockToEHPreds;
2230     BlockToFlowListMap* GetBlockToEHPreds()
2231     {
2232         if (m_blockToEHPreds == nullptr)
2233         {
2234             m_blockToEHPreds = new (getAllocator()) BlockToFlowListMap(getAllocator());
2235         }
2236         return m_blockToEHPreds;
2237     }
2238
2239     void* ehEmitCookie(BasicBlock* block);
2240     UNATIVE_OFFSET ehCodeOffset(BasicBlock* block);
2241
2242     EHblkDsc* ehInitHndRange(BasicBlock* src, IL_OFFSET* hndBeg, IL_OFFSET* hndEnd, bool* inFilter);
2243
2244     EHblkDsc* ehInitTryRange(BasicBlock* src, IL_OFFSET* tryBeg, IL_OFFSET* tryEnd);
2245
2246     EHblkDsc* ehInitHndBlockRange(BasicBlock* blk, BasicBlock** hndBeg, BasicBlock** hndLast, bool* inFilter);
2247
2248     EHblkDsc* ehInitTryBlockRange(BasicBlock* blk, BasicBlock** tryBeg, BasicBlock** tryLast);
2249
2250     void fgSetTryEnd(EHblkDsc* handlerTab, BasicBlock* newTryLast);
2251
2252     void fgSetHndEnd(EHblkDsc* handlerTab, BasicBlock* newHndLast);
2253
2254     void fgSkipRmvdBlocks(EHblkDsc* handlerTab);
2255
2256     void fgAllocEHTable();
2257
2258     void fgRemoveEHTableEntry(unsigned XTnum);
2259
2260 #if FEATURE_EH_FUNCLETS
2261
2262     EHblkDsc* fgAddEHTableEntry(unsigned XTnum);
2263
2264 #endif // FEATURE_EH_FUNCLETS
2265
2266 #if !FEATURE_EH
2267     void fgRemoveEH();
2268 #endif // !FEATURE_EH
2269
2270     void fgSortEHTable();
2271
2272     // Causes the EH table to obey some well-formedness conditions, by inserting
2273     // empty BB's when necessary:
2274     //   * No block is both the first block of a handler and the first block of a try.
2275     //   * No block is the first block of multiple 'try' regions.
2276     //   * No block is the last block of multiple EH regions.
2277     void fgNormalizeEH();
2278     bool fgNormalizeEHCase1();
2279     bool fgNormalizeEHCase2();
2280     bool fgNormalizeEHCase3();
2281
2282 #ifdef DEBUG
2283     void dispIncomingEHClause(unsigned num, const CORINFO_EH_CLAUSE& clause);
2284     void dispOutgoingEHClause(unsigned num, const CORINFO_EH_CLAUSE& clause);
2285     void fgVerifyHandlerTab();
2286     void fgDispHandlerTab();
2287 #endif // DEBUG
2288
2289     bool fgNeedToSortEHTable;
2290
2291     void verInitEHTree(unsigned numEHClauses);
2292     void verInsertEhNode(CORINFO_EH_CLAUSE* clause, EHblkDsc* handlerTab);
2293     void verInsertEhNodeInTree(EHNodeDsc** ppRoot, EHNodeDsc* node);
2294     void verInsertEhNodeParent(EHNodeDsc** ppRoot, EHNodeDsc* node);
2295     void verCheckNestingLevel(EHNodeDsc* initRoot);
2296
2297     /*
2298     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2299     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2300     XX                                                                           XX
2301     XX                        GenTree and BasicBlock                             XX
2302     XX                                                                           XX
2303     XX  Functions to allocate and display the GenTrees and BasicBlocks           XX
2304     XX                                                                           XX
2305     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2306     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2307     */
2308
2309     // Functions to create nodes
2310     GenTreeStmt* gtNewStmt(GenTree* expr = nullptr, IL_OFFSETX offset = BAD_IL_OFFSET);
2311
2312     // For unary opers.
2313     GenTree* gtNewOperNode(genTreeOps oper, var_types type, GenTree* op1, bool doSimplifications = TRUE);
2314
2315     // For binary opers.
2316     GenTree* gtNewOperNode(genTreeOps oper, var_types type, GenTree* op1, GenTree* op2);
2317
2318     GenTree* gtNewQmarkNode(var_types type, GenTree* cond, GenTree* colon);
2319
2320     GenTree* gtNewLargeOperNode(genTreeOps oper,
2321                                 var_types  type = TYP_I_IMPL,
2322                                 GenTree*   op1  = nullptr,
2323                                 GenTree*   op2  = nullptr);
2324
2325     GenTreeIntCon* gtNewIconNode(ssize_t value, var_types type = TYP_INT);
2326
2327     GenTree* gtNewPhysRegNode(regNumber reg, var_types type);
2328
2329     GenTree* gtNewJmpTableNode();
2330
2331     GenTree* gtNewIndOfIconHandleNode(var_types indType, size_t value, unsigned iconFlags, bool isInvariant);
2332
2333     GenTree* gtNewIconHandleNode(size_t value, unsigned flags, FieldSeqNode* fields = nullptr);
2334
2335     unsigned gtTokenToIconFlags(unsigned token);
2336
2337     GenTree* gtNewIconEmbHndNode(void* value, void* pValue, unsigned flags, void* compileTimeHandle);
2338
2339     GenTree* gtNewIconEmbScpHndNode(CORINFO_MODULE_HANDLE scpHnd);
2340     GenTree* gtNewIconEmbClsHndNode(CORINFO_CLASS_HANDLE clsHnd);
2341     GenTree* gtNewIconEmbMethHndNode(CORINFO_METHOD_HANDLE methHnd);
2342     GenTree* gtNewIconEmbFldHndNode(CORINFO_FIELD_HANDLE fldHnd);
2343
2344     GenTree* gtNewStringLiteralNode(InfoAccessType iat, void* pValue);
2345
2346     GenTree* gtNewLconNode(__int64 value);
2347
2348     GenTree* gtNewDconNode(double value, var_types type = TYP_DOUBLE);
2349
2350     GenTree* gtNewSconNode(int CPX, CORINFO_MODULE_HANDLE scpHandle);
2351
2352     GenTree* gtNewZeroConNode(var_types type);
2353
2354     GenTree* gtNewOneConNode(var_types type);
2355
2356 #ifdef FEATURE_SIMD
2357     GenTree* gtNewSIMDVectorZero(var_types simdType, var_types baseType, unsigned size);
2358     GenTree* gtNewSIMDVectorOne(var_types simdType, var_types baseType, unsigned size);
2359 #endif
2360
2361     GenTree* gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, unsigned size, bool isVolatile, bool isCopyBlock);
2362
2363     GenTree* gtNewPutArgReg(var_types type, GenTree* arg, regNumber argReg);
2364
2365     GenTree* gtNewBitCastNode(var_types type, GenTree* arg);
2366
2367 protected:
2368     void gtBlockOpInit(GenTree* result, GenTree* dst, GenTree* srcOrFillVal, bool isVolatile);
2369
2370 public:
2371     GenTree* gtNewObjNode(CORINFO_CLASS_HANDLE structHnd, GenTree* addr);
2372     void gtSetObjGcInfo(GenTreeObj* objNode);
2373     GenTree* gtNewStructVal(CORINFO_CLASS_HANDLE structHnd, GenTree* addr);
2374     GenTree* gtNewBlockVal(GenTree* addr, unsigned size);
2375
2376     GenTree* gtNewCpObjNode(GenTree* dst, GenTree* src, CORINFO_CLASS_HANDLE structHnd, bool isVolatile);
2377
2378     GenTreeArgList* gtNewListNode(GenTree* op1, GenTreeArgList* op2);
2379
2380     GenTreeCall* gtNewCallNode(gtCallTypes           callType,
2381                                CORINFO_METHOD_HANDLE handle,
2382                                var_types             type,
2383                                GenTreeArgList*       args,
2384                                IL_OFFSETX            ilOffset = BAD_IL_OFFSET);
2385
2386     GenTreeCall* gtNewIndCallNode(GenTree*        addr,
2387                                   var_types       type,
2388                                   GenTreeArgList* args,
2389                                   IL_OFFSETX      ilOffset = BAD_IL_OFFSET);
2390
2391     GenTreeCall* gtNewHelperCallNode(unsigned helper, var_types type, GenTreeArgList* args = nullptr);
2392
2393     GenTree* gtNewLclvNode(unsigned lnum, var_types type DEBUGARG(IL_OFFSETX ILoffs = BAD_IL_OFFSET));
2394     GenTree* gtNewLclLNode(unsigned lnum, var_types type DEBUGARG(IL_OFFSETX ILoffs = BAD_IL_OFFSET));
2395
2396 #ifdef FEATURE_SIMD
2397     GenTreeSIMD* gtNewSIMDNode(
2398         var_types type, GenTree* op1, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size);
2399     GenTreeSIMD* gtNewSIMDNode(
2400         var_types type, GenTree* op1, GenTree* op2, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size);
2401     void SetOpLclRelatedToSIMDIntrinsic(GenTree* op);
2402 #endif
2403
2404 #ifdef FEATURE_HW_INTRINSICS
2405     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2406                                                  NamedIntrinsic hwIntrinsicID,
2407                                                  var_types      baseType,
2408                                                  unsigned       size);
2409     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(
2410         var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned size);
2411     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(
2412         var_types type, GenTree* op1, GenTree* op2, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned size);
2413     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2414                                                  GenTree*       op1,
2415                                                  GenTree*       op2,
2416                                                  GenTree*       op3,
2417                                                  NamedIntrinsic hwIntrinsicID,
2418                                                  var_types      baseType,
2419                                                  unsigned       size);
2420     GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types      type,
2421                                                  GenTree*       op1,
2422                                                  GenTree*       op2,
2423                                                  GenTree*       op3,
2424                                                  GenTree*       op4,
2425                                                  NamedIntrinsic hwIntrinsicID,
2426                                                  var_types      baseType,
2427                                                  unsigned       size);
2428     GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID);
2429     GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types      type,
2430                                                    GenTree*       op1,
2431                                                    GenTree*       op2,
2432                                                    NamedIntrinsic hwIntrinsicID);
2433     GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(
2434         var_types type, GenTree* op1, GenTree* op2, GenTree* op3, NamedIntrinsic hwIntrinsicID);
2435     GenTree* gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd);
2436     CORINFO_CLASS_HANDLE gtGetStructHandleForHWSIMD(var_types simdType, var_types simdBaseType);
2437 #endif // FEATURE_HW_INTRINSICS
2438
2439     GenTreeLclFld* gtNewLclFldNode(unsigned lnum, var_types type, unsigned offset);
2440     GenTree* gtNewInlineCandidateReturnExpr(GenTree* inlineCandidate, var_types type);
2441
2442     GenTree* gtNewFieldRef(var_types typ, CORINFO_FIELD_HANDLE fldHnd, GenTree* obj = nullptr, DWORD offset = 0);
2443
2444     GenTree* gtNewIndexRef(var_types typ, GenTree* arrayOp, GenTree* indexOp);
2445
2446     GenTreeArrLen* gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset);
2447
2448     GenTree* gtNewIndir(var_types typ, GenTree* addr);
2449
2450     GenTreeArgList* gtNewArgList(GenTree* op);
2451     GenTreeArgList* gtNewArgList(GenTree* op1, GenTree* op2);
2452     GenTreeArgList* gtNewArgList(GenTree* op1, GenTree* op2, GenTree* op3);
2453     GenTreeArgList* gtNewArgList(GenTree* op1, GenTree* op2, GenTree* op3, GenTree* op4);
2454
2455     static fgArgTabEntry* gtArgEntryByArgNum(GenTreeCall* call, unsigned argNum);
2456     static fgArgTabEntry* gtArgEntryByNode(GenTreeCall* call, GenTree* node);
2457     fgArgTabEntry* gtArgEntryByLateArgIndex(GenTreeCall* call, unsigned lateArgInx);
2458     static GenTree* gtArgNodeByLateArgInx(GenTreeCall* call, unsigned lateArgInx);
2459     bool gtArgIsThisPtr(fgArgTabEntry* argEntry);
2460
2461     GenTree* gtNewAssignNode(GenTree* dst, GenTree* src);
2462
2463     GenTree* gtNewTempAssign(unsigned    tmp,
2464                              GenTree*    val,
2465                              GenTree**   pAfterStmt = nullptr,
2466                              IL_OFFSETX  ilOffset   = BAD_IL_OFFSET,
2467                              BasicBlock* block      = nullptr);
2468
2469     GenTree* gtNewRefCOMfield(GenTree*                objPtr,
2470                               CORINFO_RESOLVED_TOKEN* pResolvedToken,
2471                               CORINFO_ACCESS_FLAGS    access,
2472                               CORINFO_FIELD_INFO*     pFieldInfo,
2473                               var_types               lclTyp,
2474                               CORINFO_CLASS_HANDLE    structType,
2475                               GenTree*                assg);
2476
2477     GenTree* gtNewNothingNode();
2478
2479     GenTree* gtNewArgPlaceHolderNode(var_types type, CORINFO_CLASS_HANDLE clsHnd);
2480
2481     GenTree* gtUnusedValNode(GenTree* expr);
2482
2483     GenTreeCast* gtNewCastNode(var_types typ, GenTree* op1, bool fromUnsigned, var_types castType);
2484
2485     GenTreeCast* gtNewCastNodeL(var_types typ, GenTree* op1, bool fromUnsigned, var_types castType);
2486
2487     GenTreeAllocObj* gtNewAllocObjNode(
2488         unsigned int helper, bool helperHasSideEffects, CORINFO_CLASS_HANDLE clsHnd, var_types type, GenTree* op1);
2489
2490     GenTreeAllocObj* gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, BOOL useParent);
2491
2492     GenTree* gtNewRuntimeLookup(CORINFO_GENERIC_HANDLE hnd, CorInfoGenericHandleType hndTyp, GenTree* lookupTree);
2493
2494     //------------------------------------------------------------------------
2495     // Other GenTree functions
2496
2497     GenTree* gtClone(GenTree* tree, bool complexOK = false);
2498
2499     // If `tree` is a lclVar with lclNum `varNum`, return an IntCns with value `varVal`; otherwise,
2500     // create a copy of `tree`, adding specified flags, replacing uses of lclVar `deepVarNum` with
2501     // IntCnses with value `deepVarVal`.
2502     GenTree* gtCloneExpr(
2503         GenTree* tree, unsigned addFlags, unsigned varNum, int varVal, unsigned deepVarNum, int deepVarVal);
2504
2505     // Create a copy of `tree`, optionally adding specifed flags, and optionally mapping uses of local
2506     // `varNum` to int constants with value `varVal`.
2507     GenTree* gtCloneExpr(GenTree* tree, unsigned addFlags = 0, unsigned varNum = BAD_VAR_NUM, int varVal = 0)
2508     {
2509         return gtCloneExpr(tree, addFlags, varNum, varVal, varNum, varVal);
2510     }
2511
2512     // Internal helper for cloning a call
2513     GenTreeCall* gtCloneExprCallHelper(GenTreeCall* call,
2514                                        unsigned     addFlags   = 0,
2515                                        unsigned     deepVarNum = BAD_VAR_NUM,
2516                                        int          deepVarVal = 0);
2517
2518     // Create copy of an inline or guarded devirtualization candidate tree.
2519     GenTreeCall* gtCloneCandidateCall(GenTreeCall* call);
2520
2521     GenTree* gtReplaceTree(GenTree* stmt, GenTree* tree, GenTree* replacementTree);
2522
2523     void gtUpdateSideEffects(GenTree* stmt, GenTree* tree);
2524
2525     void gtUpdateTreeAncestorsSideEffects(GenTree* tree);
2526
2527     void gtUpdateStmtSideEffects(GenTree* stmt);
2528
2529     void gtUpdateNodeSideEffects(GenTree* tree);
2530
2531     void gtUpdateNodeOperSideEffects(GenTree* tree);
2532
2533     // Returns "true" iff the complexity (not formally defined, but first interpretation
2534     // is #of nodes in subtree) of "tree" is greater than "limit".
2535     // (This is somewhat redundant with the "gtCostEx/gtCostSz" fields, but can be used
2536     // before they have been set.)
2537     bool gtComplexityExceeds(GenTree** tree, unsigned limit);
2538
2539     bool gtCompareTree(GenTree* op1, GenTree* op2);
2540
2541     GenTree* gtReverseCond(GenTree* tree);
2542
2543     bool gtHasRef(GenTree* tree, ssize_t lclNum, bool defOnly);
2544
2545     bool gtHasLocalsWithAddrOp(GenTree* tree);
2546
2547     unsigned gtSetListOrder(GenTree* list, bool regs, bool isListCallArgs);
2548
2549     void gtWalkOp(GenTree** op1, GenTree** op2, GenTree* base, bool constOnly);
2550
2551 #ifdef DEBUG
2552     unsigned gtHashValue(GenTree* tree);
2553
2554     GenTree* gtWalkOpEffectiveVal(GenTree* op);
2555 #endif
2556
2557     void gtPrepareCost(GenTree* tree);
2558     bool gtIsLikelyRegVar(GenTree* tree);
2559
2560     // Returns true iff the secondNode can be swapped with firstNode.
2561     bool gtCanSwapOrder(GenTree* firstNode, GenTree* secondNode);
2562
2563     // Given an address expression, compute its costs and addressing mode opportunities,
2564     // and mark addressing mode candidates as GTF_DONT_CSE.
2565     // TODO-Throughput - Consider actually instantiating these early, to avoid
2566     // having to re-run the algorithm that looks for them (might also improve CQ).
2567     bool gtMarkAddrMode(GenTree* addr, int* costEx, int* costSz, var_types type);
2568
2569     unsigned gtSetEvalOrder(GenTree* tree);
2570
2571     void gtSetStmtInfo(GenTree* stmt);
2572
2573     // Returns "true" iff "node" has any of the side effects in "flags".
2574     bool gtNodeHasSideEffects(GenTree* node, unsigned flags);
2575
2576     // Returns "true" iff "tree" or its (transitive) children have any of the side effects in "flags".
2577     bool gtTreeHasSideEffects(GenTree* tree, unsigned flags);
2578
2579     // Appends 'expr' in front of 'list'
2580     //    'list' will typically start off as 'nullptr'
2581     //    when 'list' is non-null a GT_COMMA node is used to insert 'expr'
2582     GenTree* gtBuildCommaList(GenTree* list, GenTree* expr);
2583
2584     void gtExtractSideEffList(GenTree*  expr,
2585                               GenTree** pList,
2586                               unsigned  flags      = GTF_SIDE_EFFECT,
2587                               bool      ignoreRoot = false);
2588
2589     GenTree* gtGetThisArg(GenTreeCall* call);
2590
2591     // Static fields of struct types (and sometimes the types that those are reduced to) are represented by having the
2592     // static field contain an object pointer to the boxed struct.  This simplifies the GC implementation...but
2593     // complicates the JIT somewhat.  This predicate returns "true" iff a node with type "fieldNodeType", representing
2594     // the given "fldHnd", is such an object pointer.
2595     bool gtIsStaticFieldPtrToBoxedStruct(var_types fieldNodeType, CORINFO_FIELD_HANDLE fldHnd);
2596
2597     // Return true if call is a recursive call; return false otherwise.
2598     // Note when inlining, this looks for calls back to the root method.
2599     bool gtIsRecursiveCall(GenTreeCall* call)
2600     {
2601         return gtIsRecursiveCall(call->gtCallMethHnd);
2602     }
2603
2604     bool gtIsRecursiveCall(CORINFO_METHOD_HANDLE callMethodHandle)
2605     {
2606         return (callMethodHandle == impInlineRoot()->info.compMethodHnd);
2607     }
2608
2609     //-------------------------------------------------------------------------
2610
2611     GenTree* gtFoldExpr(GenTree* tree);
2612     GenTree*
2613 #ifdef __clang__
2614         // TODO-Amd64-Unix: Remove this when the clang optimizer is fixed and/or the method implementation is
2615         // refactored in a simpler code. This is a workaround for a bug in the clang-3.5 optimizer. The issue is that in
2616         // release build the optimizer is mistyping (or just wrongly decides to use 32 bit operation for a corner case
2617         // of MIN_LONG) the args of the (ltemp / lval2) to int (it does a 32 bit div operation instead of 64 bit) - see
2618         // the implementation of the method in gentree.cpp. For the case of lval1 and lval2 equal to MIN_LONG
2619         // (0x8000000000000000) this results in raising a SIGFPE. The method implementation is rather complex. Disable
2620         // optimizations for now.
2621         __attribute__((optnone))
2622 #endif // __clang__
2623         gtFoldExprConst(GenTree* tree);
2624     GenTree* gtFoldExprSpecial(GenTree* tree);
2625     GenTree* gtFoldExprCompare(GenTree* tree);
2626     GenTree* gtCreateHandleCompare(genTreeOps             oper,
2627                                    GenTree*               op1,
2628                                    GenTree*               op2,
2629                                    CorInfoInlineTypeCheck typeCheckInliningResult);
2630     GenTree* gtFoldExprCall(GenTreeCall* call);
2631     GenTree* gtFoldTypeCompare(GenTree* tree);
2632     GenTree* gtFoldTypeEqualityCall(CorInfoIntrinsics methodID, GenTree* op1, GenTree* op2);
2633
2634     // Options to control behavior of gtTryRemoveBoxUpstreamEffects
2635     enum BoxRemovalOptions
2636     {
2637         BR_REMOVE_AND_NARROW, // remove effects, minimize remaining work, return possibly narrowed source tree
2638         BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE, // remove effects and minimize remaining work, return type handle tree
2639         BR_REMOVE_BUT_NOT_NARROW,              // remove effects, return original source tree
2640         BR_DONT_REMOVE,                        // check if removal is possible, return copy source tree
2641         BR_DONT_REMOVE_WANT_TYPE_HANDLE,       // check if removal is possible, return type handle tree
2642         BR_MAKE_LOCAL_COPY                     // revise box to copy to temp local and return local's address
2643     };
2644
2645     GenTree* gtTryRemoveBoxUpstreamEffects(GenTree* tree, BoxRemovalOptions options = BR_REMOVE_AND_NARROW);
2646     GenTree* gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp);
2647
2648     //-------------------------------------------------------------------------
2649     // Get the handle, if any.
2650     CORINFO_CLASS_HANDLE gtGetStructHandleIfPresent(GenTree* tree);
2651     // Get the handle, and assert if not found.
2652     CORINFO_CLASS_HANDLE gtGetStructHandle(GenTree* tree);
2653     // Get the handle for a ref type.
2654     CORINFO_CLASS_HANDLE gtGetClassHandle(GenTree* tree, bool* pIsExact, bool* pIsNonNull);
2655     // Get the class handle for an helper call
2656     CORINFO_CLASS_HANDLE gtGetHelperCallClassHandle(GenTreeCall* call, bool* pIsExact, bool* pIsNonNull);
2657     // Get the element handle for an array of ref type.
2658     CORINFO_CLASS_HANDLE gtGetArrayElementClassHandle(GenTree* array);
2659     // Get a class handle from a helper call argument
2660     CORINFO_CLASS_HANDLE gtGetHelperArgClassHandle(GenTree*  array,
2661                                                    unsigned* runtimeLookupCount = nullptr,
2662                                                    GenTree** handleTree         = nullptr);
2663     // Get the class handle for a field
2664     CORINFO_CLASS_HANDLE gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsExact, bool* pIsNonNull);
2665     // Check if this tree is a gc static base helper call
2666     bool gtIsStaticGCBaseHelperCall(GenTree* tree);
2667
2668 //-------------------------------------------------------------------------
2669 // Functions to display the trees
2670
2671 #ifdef DEBUG
2672     void gtDispNode(GenTree* tree, IndentStack* indentStack, __in_z const char* msg, bool isLIR);
2673
2674     void gtDispVN(GenTree* tree);
2675     void gtDispConst(GenTree* tree);
2676     void gtDispLeaf(GenTree* tree, IndentStack* indentStack);
2677     void gtDispNodeName(GenTree* tree);
2678     void gtDispRegVal(GenTree* tree);
2679
2680     enum IndentInfo
2681     {
2682         IINone,
2683         IIArc,
2684         IIArcTop,
2685         IIArcBottom,
2686         IIEmbedded,
2687         IIError,
2688         IndentInfoCount
2689     };
2690     void gtDispChild(GenTree*             child,
2691                      IndentStack*         indentStack,
2692                      IndentInfo           arcType,
2693                      __in_opt const char* msg     = nullptr,
2694                      bool                 topOnly = false);
2695     void gtDispTree(GenTree*             tree,
2696                     IndentStack*         indentStack = nullptr,
2697                     __in_opt const char* msg         = nullptr,
2698                     bool                 topOnly     = false,
2699                     bool                 isLIR       = false);
2700     void gtGetLclVarNameInfo(unsigned lclNum, const char** ilKindOut, const char** ilNameOut, unsigned* ilNumOut);
2701     int gtGetLclVarName(unsigned lclNum, char* buf, unsigned buf_remaining);
2702     char* gtGetLclVarName(unsigned lclNum);
2703     void gtDispLclVar(unsigned varNum, bool padForBiggestDisp = true);
2704     void gtDispTreeList(GenTree* tree, IndentStack* indentStack = nullptr);
2705     void gtGetArgMsg(GenTreeCall* call, GenTree* arg, unsigned argNum, int listCount, char* bufp, unsigned bufLength);
2706     void gtGetLateArgMsg(GenTreeCall* call, GenTree* arg, int argNum, int listCount, char* bufp, unsigned bufLength);
2707     void gtDispArgList(GenTreeCall* call, IndentStack* indentStack);
2708     void gtDispFieldSeq(FieldSeqNode* pfsn);
2709
2710     void gtDispRange(LIR::ReadOnlyRange const& range);
2711
2712     void gtDispTreeRange(LIR::Range& containingRange, GenTree* tree);
2713
2714     void gtDispLIRNode(GenTree* node, const char* prefixMsg = nullptr);
2715 #endif
2716
2717     // For tree walks
2718
2719     enum fgWalkResult
2720     {
2721         WALK_CONTINUE,
2722         WALK_SKIP_SUBTREES,
2723         WALK_ABORT
2724     };
2725     struct fgWalkData;
2726     typedef fgWalkResult(fgWalkPreFn)(GenTree** pTree, fgWalkData* data);
2727     typedef fgWalkResult(fgWalkPostFn)(GenTree** pTree, fgWalkData* data);
2728
2729 #ifdef DEBUG
2730     static fgWalkPreFn gtAssertColonCond;
2731 #endif
2732     static fgWalkPreFn gtMarkColonCond;
2733     static fgWalkPreFn gtClearColonCond;
2734
2735     GenTree** gtFindLink(GenTree* stmt, GenTree* node);
2736     bool gtHasCatchArg(GenTree* tree);
2737
2738     typedef ArrayStack<GenTree*> GenTreeStack;
2739
2740     static bool gtHasCallOnStack(GenTreeStack* parentStack);
2741
2742 //=========================================================================
2743 // BasicBlock functions
2744 #ifdef DEBUG
2745     // This is a debug flag we will use to assert when creating block during codegen
2746     // as this interferes with procedure splitting. If you know what you're doing, set
2747     // it to true before creating the block. (DEBUG only)
2748     bool fgSafeBasicBlockCreation;
2749 #endif
2750
2751     BasicBlock* bbNewBasicBlock(BBjumpKinds jumpKind);
2752
2753     /*
2754     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2755     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2756     XX                                                                           XX
2757     XX                           LclVarsInfo                                     XX
2758     XX                                                                           XX
2759     XX   The variables to be used by the code generator.                         XX
2760     XX                                                                           XX
2761     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2762     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2763     */
2764
2765     //
2766     // For both PROMOTION_TYPE_NONE and PROMOTION_TYPE_DEPENDENT the struct will
2767     // be placed in the stack frame and it's fields must be laid out sequentially.
2768     //
2769     // For PROMOTION_TYPE_INDEPENDENT each of the struct's fields is replaced by
2770     //  a local variable that can be enregistered or placed in the stack frame.
2771     //  The fields do not need to be laid out sequentially
2772     //
2773     enum lvaPromotionType
2774     {
2775         PROMOTION_TYPE_NONE,        // The struct local is not promoted
2776         PROMOTION_TYPE_INDEPENDENT, // The struct local is promoted,
2777                                     //   and its field locals are independent of its parent struct local.
2778         PROMOTION_TYPE_DEPENDENT    // The struct local is promoted,
2779                                     //   but its field locals depend on its parent struct local.
2780     };
2781
2782     static int __cdecl RefCntCmp(const void* op1, const void* op2);
2783     static int __cdecl WtdRefCntCmp(const void* op1, const void* op2);
2784
2785     /*****************************************************************************/
2786
2787     enum FrameLayoutState
2788     {
2789         NO_FRAME_LAYOUT,
2790         INITIAL_FRAME_LAYOUT,
2791         PRE_REGALLOC_FRAME_LAYOUT,
2792         REGALLOC_FRAME_LAYOUT,
2793         TENTATIVE_FRAME_LAYOUT,
2794         FINAL_FRAME_LAYOUT
2795     };
2796
2797 public:
2798     RefCountState lvaRefCountState; // Current local ref count state
2799
2800     bool lvaLocalVarRefCounted() const
2801     {
2802         return lvaRefCountState == RCS_NORMAL;
2803     }
2804
2805     bool     lvaTrackedFixed; // true: We cannot add new 'tracked' variable
2806     unsigned lvaCount;        // total number of locals
2807
2808     unsigned   lvaRefCount; // total number of references to locals
2809     LclVarDsc* lvaTable;    // variable descriptor table
2810     unsigned   lvaTableCnt; // lvaTable size (>= lvaCount)
2811
2812     LclVarDsc** lvaRefSorted; // table sorted by refcount
2813
2814     unsigned short lvaTrackedCount;       // actual # of locals being tracked
2815     unsigned lvaTrackedCountInSizeTUnits; // min # of size_t's sufficient to hold a bit for all the locals being tracked
2816
2817 #ifdef DEBUG
2818     VARSET_TP lvaTrackedVars; // set of tracked variables
2819 #endif
2820 #ifndef _TARGET_64BIT_
2821     VARSET_TP lvaLongVars; // set of long (64-bit) variables
2822 #endif
2823     VARSET_TP lvaFloatVars; // set of floating-point (32-bit and 64-bit) variables
2824
2825     unsigned lvaCurEpoch; // VarSets are relative to a specific set of tracked var indices.
2826                           // It that changes, this changes.  VarSets from different epochs
2827                           // cannot be meaningfully combined.
2828
2829     unsigned GetCurLVEpoch()
2830     {
2831         return lvaCurEpoch;
2832     }
2833
2834     // reverse map of tracked number to var number
2835     unsigned* lvaTrackedToVarNum;
2836
2837 #if DOUBLE_ALIGN
2838 #ifdef DEBUG
2839     // # of procs compiled a with double-aligned stack
2840     static unsigned s_lvaDoubleAlignedProcsCount;
2841 #endif
2842 #endif
2843
2844     // Getters and setters for address-exposed and do-not-enregister local var properties.
2845     bool lvaVarAddrExposed(unsigned varNum);
2846     void lvaSetVarAddrExposed(unsigned varNum);
2847     bool lvaVarDoNotEnregister(unsigned varNum);
2848 #ifdef DEBUG
2849     // Reasons why we can't enregister.  Some of these correspond to debug properties of local vars.
2850     enum DoNotEnregisterReason
2851     {
2852         DNER_AddrExposed,
2853         DNER_IsStruct,
2854         DNER_LocalField,
2855         DNER_VMNeedsStackAddr,
2856         DNER_LiveInOutOfHandler,
2857         DNER_LiveAcrossUnmanagedCall,
2858         DNER_BlockOp,     // Is read or written via a block operation that explicitly takes the address.
2859         DNER_IsStructArg, // Is a struct passed as an argument in a way that requires a stack location.
2860         DNER_DepField,    // It is a field of a dependently promoted struct
2861         DNER_NoRegVars,   // opts.compFlags & CLFLG_REGVAR is not set
2862         DNER_MinOptsGC,   // It is a GC Ref and we are compiling MinOpts
2863 #if !defined(_TARGET_64BIT_)
2864         DNER_LongParamField, // It is a decomposed field of a long parameter.
2865 #endif
2866 #ifdef JIT32_GCENCODER
2867         DNER_PinningRef,
2868 #endif
2869     };
2870 #endif
2871     void lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(DoNotEnregisterReason reason));
2872
2873     unsigned lvaVarargsHandleArg;
2874 #ifdef _TARGET_X86_
2875     unsigned lvaVarargsBaseOfStkArgs; // Pointer (computed based on incoming varargs handle) to the start of the stack
2876                                       // arguments
2877 #endif                                // _TARGET_X86_
2878
2879     unsigned lvaInlinedPInvokeFrameVar; // variable representing the InlinedCallFrame
2880     unsigned lvaReversePInvokeFrameVar; // variable representing the reverse PInvoke frame
2881 #if FEATURE_FIXED_OUT_ARGS
2882     unsigned lvaPInvokeFrameRegSaveVar; // variable representing the RegSave for PInvoke inlining.
2883 #endif
2884     unsigned lvaMonAcquired; // boolean variable introduced into in synchronized methods
2885                              // that tracks whether the lock has been taken
2886
2887     unsigned lvaArg0Var; // The lclNum of arg0. Normally this will be info.compThisArg.
2888                          // However, if there is a "ldarga 0" or "starg 0" in the IL,
2889                          // we will redirect all "ldarg(a) 0" and "starg 0" to this temp.
2890
2891     unsigned lvaInlineeReturnSpillTemp; // The temp to spill the non-VOID return expression
2892                                         // in case there are multiple BBJ_RETURN blocks in the inlinee
2893                                         // or if the inlinee has GC ref locals.
2894
2895 #if FEATURE_FIXED_OUT_ARGS
2896     unsigned            lvaOutgoingArgSpaceVar;  // dummy TYP_LCLBLK var for fixed outgoing argument space
2897     PhasedVar<unsigned> lvaOutgoingArgSpaceSize; // size of fixed outgoing argument space
2898 #endif                                           // FEATURE_FIXED_OUT_ARGS
2899
2900 #ifdef _TARGET_ARM_
2901     // On architectures whose ABIs allow structs to be passed in registers, struct promotion will sometimes
2902     // require us to "rematerialize" a struct from it's separate constituent field variables.  Packing several sub-word
2903     // field variables into an argument register is a hard problem.  It's easier to reserve a word of memory into which
2904     // such field can be copied, after which the assembled memory word can be read into the register.  We will allocate
2905     // this variable to be this scratch word whenever struct promotion occurs.
2906     unsigned lvaPromotedStructAssemblyScratchVar;
2907 #endif // _TARGET_ARM_
2908
2909 #if defined(DEBUG) && defined(_TARGET_XARCH_)
2910
2911     unsigned lvaReturnSpCheck; // Stores SP to confirm it is not corrupted on return.
2912
2913 #endif // defined(DEBUG) && defined(_TARGET_XARCH_)
2914
2915 #if defined(DEBUG) && defined(_TARGET_X86_)
2916
2917     unsigned lvaCallSpCheck; // Stores SP to confirm it is not corrupted after every call.
2918
2919 #endif // defined(DEBUG) && defined(_TARGET_X86_)
2920
2921     unsigned lvaGenericsContextUseCount;
2922
2923     bool lvaKeepAliveAndReportThis(); // Synchronized instance method of a reference type, or
2924                                       // CORINFO_GENERICS_CTXT_FROM_THIS?
2925     bool lvaReportParamTypeArg();     // Exceptions and CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG?
2926
2927 //-------------------------------------------------------------------------
2928 // All these frame offsets are inter-related and must be kept in sync
2929
2930 #if !FEATURE_EH_FUNCLETS
2931     // This is used for the callable handlers
2932     unsigned lvaShadowSPslotsVar; // TYP_BLK variable for all the shadow SP slots
2933 #endif                            // FEATURE_EH_FUNCLETS
2934
2935     int lvaCachedGenericContextArgOffs;
2936     int lvaCachedGenericContextArgOffset(); // For CORINFO_CALLCONV_PARAMTYPE and if generic context is passed as
2937                                             // THIS pointer
2938
2939 #ifdef JIT32_GCENCODER
2940
2941     unsigned lvaLocAllocSPvar; // variable which stores the value of ESP after the the last alloca/localloc
2942
2943 #endif // JIT32_GCENCODER
2944
2945     unsigned lvaNewObjArrayArgs; // variable with arguments for new MD array helper
2946
2947     // TODO-Review: Prior to reg predict we reserve 24 bytes for Spill temps.
2948     //              after the reg predict we will use a computed maxTmpSize
2949     //              which is based upon the number of spill temps predicted by reg predict
2950     //              All this is necessary because if we under-estimate the size of the spill
2951     //              temps we could fail when encoding instructions that reference stack offsets for ARM.
2952     //
2953     // Pre codegen max spill temp size.
2954     static const unsigned MAX_SPILL_TEMP_SIZE = 24;
2955
2956     //-------------------------------------------------------------------------
2957
2958     unsigned lvaGetMaxSpillTempSize();
2959 #ifdef _TARGET_ARM_
2960     bool lvaIsPreSpilled(unsigned lclNum, regMaskTP preSpillMask);
2961 #endif // _TARGET_ARM_
2962     void lvaAssignFrameOffsets(FrameLayoutState curState);
2963     void lvaFixVirtualFrameOffsets();
2964     void lvaUpdateArgsWithInitialReg();
2965     void lvaAssignVirtualFrameOffsetsToArgs();
2966 #ifdef UNIX_AMD64_ABI
2967     int lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, unsigned argSize, int argOffs, int* callerArgOffset);
2968 #else  // !UNIX_AMD64_ABI
2969     int lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, unsigned argSize, int argOffs);
2970 #endif // !UNIX_AMD64_ABI
2971     void lvaAssignVirtualFrameOffsetsToLocals();
2972     int lvaAllocLocalAndSetVirtualOffset(unsigned lclNum, unsigned size, int stkOffs);
2973 #ifdef _TARGET_AMD64_
2974     // Returns true if compCalleeRegsPushed (including RBP if used as frame pointer) is even.
2975     bool lvaIsCalleeSavedIntRegCountEven();
2976 #endif
2977     void lvaAlignFrame();
2978     void lvaAssignFrameOffsetsToPromotedStructs();
2979     int lvaAllocateTemps(int stkOffs, bool mustDoubleAlign);
2980
2981 #ifdef DEBUG
2982     void lvaDumpRegLocation(unsigned lclNum);
2983     void lvaDumpFrameLocation(unsigned lclNum);
2984     void lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t refCntWtdWidth = 6);
2985     void lvaTableDump(FrameLayoutState curState = NO_FRAME_LAYOUT); // NO_FRAME_LAYOUT means use the current frame
2986                                                                     // layout state defined by lvaDoneFrameLayout
2987 #endif
2988
2989 // Limit frames size to 1GB. The maximum is 2GB in theory - make it intentionally smaller
2990 // to avoid bugs from borderline cases.
2991 #define MAX_FrameSize 0x3FFFFFFF
2992     void lvaIncrementFrameSize(unsigned size);
2993
2994     unsigned lvaFrameSize(FrameLayoutState curState);
2995
2996     // Returns the caller-SP-relative offset for the SP/FP relative offset determined by FP based.
2997     int lvaToCallerSPRelativeOffset(int offs, bool isFpBased);
2998
2999     // Returns the caller-SP-relative offset for the local variable "varNum."
3000     int lvaGetCallerSPRelativeOffset(unsigned varNum);
3001
3002     // Returns the SP-relative offset for the local variable "varNum". Illegal to ask this for functions with localloc.
3003     int lvaGetSPRelativeOffset(unsigned varNum);
3004
3005     int lvaToInitialSPRelativeOffset(unsigned offset, bool isFpBased);
3006     int lvaGetInitialSPRelativeOffset(unsigned varNum);
3007
3008     //------------------------ For splitting types ----------------------------
3009
3010     void lvaInitTypeRef();
3011
3012     void lvaInitArgs(InitVarDscInfo* varDscInfo);
3013     void lvaInitThisPtr(InitVarDscInfo* varDscInfo);
3014     void lvaInitRetBuffArg(InitVarDscInfo* varDscInfo);
3015     void lvaInitUserArgs(InitVarDscInfo* varDscInfo);
3016     void lvaInitGenericsCtxt(InitVarDscInfo* varDscInfo);
3017     void lvaInitVarArgsHandle(InitVarDscInfo* varDscInfo);
3018
3019     void lvaInitVarDsc(LclVarDsc*              varDsc,
3020                        unsigned                varNum,
3021                        CorInfoType             corInfoType,
3022                        CORINFO_CLASS_HANDLE    typeHnd,
3023                        CORINFO_ARG_LIST_HANDLE varList,
3024                        CORINFO_SIG_INFO*       varSig);
3025
3026     static unsigned lvaTypeRefMask(var_types type);
3027
3028     var_types lvaGetActualType(unsigned lclNum);
3029     var_types lvaGetRealType(unsigned lclNum);
3030
3031     //-------------------------------------------------------------------------
3032
3033     void lvaInit();
3034
3035     LclVarDsc* lvaGetDesc(unsigned lclNum)
3036     {
3037         assert(lclNum < lvaCount);
3038         return &lvaTable[lclNum];
3039     }
3040
3041     LclVarDsc* lvaGetDesc(GenTreeLclVarCommon* lclVar)
3042     {
3043         assert(lclVar->GetLclNum() < lvaCount);
3044         return &lvaTable[lclVar->GetLclNum()];
3045     }
3046
3047     unsigned lvaLclSize(unsigned varNum);
3048     unsigned lvaLclExactSize(unsigned varNum);
3049
3050     bool lvaHaveManyLocals() const;
3051
3052     unsigned lvaGrabTemp(bool shortLifetime DEBUGARG(const char* reason));
3053     unsigned lvaGrabTemps(unsigned cnt DEBUGARG(const char* reason));
3054     unsigned lvaGrabTempWithImplicitUse(bool shortLifetime DEBUGARG(const char* reason));
3055
3056     void lvaSortOnly();
3057     void lvaSortByRefCount();
3058     void lvaDumpRefCounts();
3059
3060     void lvaMarkLocalVars(); // Local variable ref-counting
3061     void lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers);
3062     void lvaMarkLocalVars(BasicBlock* block, bool isRecompute);
3063
3064     void lvaAllocOutgoingArgSpaceVar(); // Set up lvaOutgoingArgSpaceVar
3065
3066     VARSET_VALRET_TP lvaStmtLclMask(GenTree* stmt);
3067
3068 #ifdef DEBUG
3069     struct lvaStressLclFldArgs
3070     {
3071         Compiler* m_pCompiler;
3072         bool      m_bFirstPass;
3073     };
3074
3075     static fgWalkPreFn lvaStressLclFldCB;
3076     void               lvaStressLclFld();
3077
3078     void lvaDispVarSet(VARSET_VALARG_TP set, VARSET_VALARG_TP allVars);
3079     void lvaDispVarSet(VARSET_VALARG_TP set);
3080
3081 #endif
3082
3083 #ifdef _TARGET_ARM_
3084     int lvaFrameAddress(int varNum, bool mustBeFPBased, regNumber* pBaseReg, int addrModeOffset, bool isFloatUsage);
3085 #else
3086     int lvaFrameAddress(int varNum, bool* pFPbased);
3087 #endif
3088
3089     bool lvaIsParameter(unsigned varNum);
3090     bool lvaIsRegArgument(unsigned varNum);
3091     BOOL lvaIsOriginalThisArg(unsigned varNum); // Is this varNum the original this argument?
3092     BOOL lvaIsOriginalThisReadOnly();           // return TRUE if there is no place in the code
3093                                                 // that writes to arg0
3094
3095     // Struct parameters that are passed by reference are marked as both lvIsParam and lvIsTemp
3096     // (this is an overload of lvIsTemp because there are no temp parameters).
3097     // For x64 this is 3, 5, 6, 7, >8 byte structs that are passed by reference.
3098     // For ARM64, this is structs larger than 16 bytes that are passed by reference.
3099     bool lvaIsImplicitByRefLocal(unsigned varNum)
3100     {
3101 #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
3102         LclVarDsc* varDsc = &(lvaTable[varNum]);
3103         if (varDsc->lvIsParam && varDsc->lvIsTemp)
3104         {
3105             assert(varTypeIsStruct(varDsc) || (varDsc->lvType == TYP_BYREF));
3106             return true;
3107         }
3108 #endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
3109         return false;
3110     }
3111
3112     // Returns true if this local var is a multireg struct
3113     bool lvaIsMultiregStruct(LclVarDsc* varDsc, bool isVararg);
3114
3115     // If the local is a TYP_STRUCT, get/set a class handle describing it
3116     CORINFO_CLASS_HANDLE lvaGetStruct(unsigned varNum);
3117     void lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool unsafeValueClsCheck, bool setTypeInfo = true);
3118     void lvaSetStructUsedAsVarArg(unsigned varNum);
3119
3120     // If the local is TYP_REF, set or update the associated class information.
3121     void lvaSetClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false);
3122     void lvaSetClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE stackHandle = nullptr);
3123     void lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false);
3124     void lvaUpdateClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE stackHandle = nullptr);
3125
3126 #define MAX_NumOfFieldsInPromotableStruct 4 // Maximum number of fields in promotable struct
3127
3128     // Info about struct type fields.
3129     struct lvaStructFieldInfo
3130     {
3131         CORINFO_FIELD_HANDLE fldHnd;
3132         unsigned char        fldOffset;
3133         unsigned char        fldOrdinal;
3134         var_types            fldType;
3135         unsigned             fldSize;
3136         CORINFO_CLASS_HANDLE fldTypeHnd;
3137
3138         lvaStructFieldInfo()
3139             : fldHnd(nullptr), fldOffset(0), fldOrdinal(0), fldType(TYP_UNDEF), fldSize(0), fldTypeHnd(nullptr)
3140         {
3141         }
3142     };
3143
3144     // Info about a struct type, instances of which may be candidates for promotion.
3145     struct lvaStructPromotionInfo
3146     {
3147         CORINFO_CLASS_HANDLE typeHnd;
3148         bool                 canPromote;
3149         bool                 containsHoles;
3150         bool                 customLayout;
3151         bool                 fieldsSorted;
3152         unsigned char        fieldCnt;
3153         lvaStructFieldInfo   fields[MAX_NumOfFieldsInPromotableStruct];
3154
3155         lvaStructPromotionInfo(CORINFO_CLASS_HANDLE typeHnd = nullptr)
3156             : typeHnd(typeHnd)
3157             , canPromote(false)
3158             , containsHoles(false)
3159             , customLayout(false)
3160             , fieldsSorted(false)
3161             , fieldCnt(0)
3162         {
3163         }
3164     };
3165
3166     static int __cdecl lvaFieldOffsetCmp(const void* field1, const void* field2);
3167
3168     // This class is responsible for checking validity and profitability of struct promotion.
3169     // If it is both legal and profitable, then TryPromoteStructVar promotes the struct and initializes
3170     // nessesary information for fgMorphStructField to use.
3171     class StructPromotionHelper
3172     {
3173     public:
3174         StructPromotionHelper(Compiler* compiler);
3175
3176         bool CanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd);
3177         bool TryPromoteStructVar(unsigned lclNum);
3178
3179 #ifdef DEBUG
3180         void CheckRetypedAsScalar(CORINFO_FIELD_HANDLE fieldHnd, var_types requestedType);
3181 #endif // DEBUG
3182
3183 #ifdef _TARGET_ARM_
3184         bool GetRequiresScratchVar();
3185 #endif // _TARGET_ARM_
3186
3187     private:
3188         bool CanPromoteStructVar(unsigned lclNum);
3189         bool ShouldPromoteStructVar(unsigned lclNum);
3190         void PromoteStructVar(unsigned lclNum);
3191         void SortStructFields();
3192
3193         lvaStructFieldInfo GetFieldInfo(CORINFO_FIELD_HANDLE fieldHnd, BYTE ordinal);
3194         bool TryPromoteStructField(lvaStructFieldInfo& outerFieldInfo);
3195
3196     private:
3197         Compiler*              compiler;
3198         lvaStructPromotionInfo structPromotionInfo;
3199
3200 #ifdef _TARGET_ARM_
3201         bool requiresScratchVar;
3202 #endif // _TARGET_ARM_
3203
3204 #ifdef DEBUG
3205         typedef JitHashTable<CORINFO_FIELD_HANDLE, JitPtrKeyFuncs<CORINFO_FIELD_STRUCT_>, var_types>
3206                                  RetypedAsScalarFieldsMap;
3207         RetypedAsScalarFieldsMap retypedFieldsMap;
3208 #endif // DEBUG
3209     };
3210
3211     StructPromotionHelper* structPromotionHelper;
3212
3213 #if !defined(_TARGET_64BIT_)
3214     void lvaPromoteLongVars();
3215 #endif // !defined(_TARGET_64BIT_)
3216     unsigned lvaGetFieldLocal(const LclVarDsc* varDsc, unsigned int fldOffset);
3217     lvaPromotionType lvaGetPromotionType(const LclVarDsc* varDsc);
3218     lvaPromotionType lvaGetPromotionType(unsigned varNum);
3219     lvaPromotionType lvaGetParentPromotionType(const LclVarDsc* varDsc);
3220     lvaPromotionType lvaGetParentPromotionType(unsigned varNum);
3221     bool lvaIsFieldOfDependentlyPromotedStruct(const LclVarDsc* varDsc);
3222     bool lvaIsGCTracked(const LclVarDsc* varDsc);
3223
3224 #if defined(FEATURE_SIMD)
3225     bool lvaMapSimd12ToSimd16(const LclVarDsc* varDsc)
3226     {
3227         assert(varDsc->lvType == TYP_SIMD12);
3228         assert(varDsc->lvExactSize == 12);
3229
3230 #if defined(_TARGET_64BIT_)
3231         assert(varDsc->lvSize() == 16);
3232 #endif // defined(_TARGET_64BIT_)
3233
3234         // We make local variable SIMD12 types 16 bytes instead of just 12. lvSize()
3235         // already does this calculation. However, we also need to prevent mapping types if the var is a
3236         // dependently promoted struct field, which must remain its exact size within its parent struct.
3237         // However, we don't know this until late, so we may have already pretended the field is bigger
3238         // before that.
3239         if ((varDsc->lvSize() == 16) && !lvaIsFieldOfDependentlyPromotedStruct(varDsc))
3240         {
3241             return true;
3242         }
3243         else
3244         {
3245             return false;
3246         }
3247     }
3248 #endif // defined(FEATURE_SIMD)
3249
3250     BYTE* lvaGetGcLayout(unsigned varNum);
3251     bool lvaTypeIsGC(unsigned varNum);
3252     unsigned lvaGSSecurityCookie; // LclVar number
3253     bool     lvaTempsHaveLargerOffsetThanVars();
3254
3255     // Returns "true" iff local variable "lclNum" is in SSA form.
3256     bool lvaInSsa(unsigned lclNum)
3257     {
3258         assert(lclNum < lvaCount);
3259         return lvaTable[lclNum].lvInSsa;
3260     }
3261
3262     unsigned lvaSecurityObject;  // variable representing the security object on the stack
3263     unsigned lvaStubArgumentVar; // variable representing the secret stub argument coming in EAX
3264
3265 #if FEATURE_EH_FUNCLETS
3266     unsigned lvaPSPSym; // variable representing the PSPSym
3267 #endif
3268
3269     InlineInfo*     impInlineInfo;
3270     InlineStrategy* m_inlineStrategy;
3271
3272     // The Compiler* that is the root of the inlining tree of which "this" is a member.
3273     Compiler* impInlineRoot();
3274
3275 #if defined(DEBUG) || defined(INLINE_DATA)
3276     unsigned __int64 getInlineCycleCount()
3277     {
3278         return m_compCycles;
3279     }
3280 #endif // defined(DEBUG) || defined(INLINE_DATA)
3281
3282     bool fgNoStructPromotion;      // Set to TRUE to turn off struct promotion for this method.
3283     bool fgNoStructParamPromotion; // Set to TRUE to turn off struct promotion for parameters this method.
3284
3285     //=========================================================================
3286     //                          PROTECTED
3287     //=========================================================================
3288
3289 protected:
3290     //---------------- Local variable ref-counting ----------------------------
3291
3292     void lvaMarkLclRefs(GenTree* tree, BasicBlock* block, GenTreeStmt* stmt, bool isRecompute);
3293     bool IsDominatedByExceptionalEntry(BasicBlock* block);
3294     void SetVolatileHint(LclVarDsc* varDsc);
3295
3296     // Keeps the mapping from SSA #'s to VN's for the implicit memory variables.
3297     SsaDefArray<SsaMemDef> lvMemoryPerSsaData;
3298
3299 public:
3300     // Returns the address of the per-Ssa data for memory at the given ssaNum (which is required
3301     // not to be the SsaConfig::RESERVED_SSA_NUM, which indicates that the variable is
3302     // not an SSA variable).
3303     SsaMemDef* GetMemoryPerSsaData(unsigned ssaNum)
3304     {
3305         return lvMemoryPerSsaData.GetSsaDef(ssaNum);
3306     }
3307
3308     /*
3309     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3310     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3311     XX                                                                           XX
3312     XX                           Importer                                        XX
3313     XX                                                                           XX
3314     XX   Imports the given method and converts it to semantic trees              XX
3315     XX                                                                           XX
3316     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3317     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3318     */
3319
3320 public:
3321     void impInit();
3322
3323     void impImport(BasicBlock* method);
3324
3325     CORINFO_CLASS_HANDLE impGetRefAnyClass();
3326     CORINFO_CLASS_HANDLE impGetRuntimeArgumentHandle();
3327     CORINFO_CLASS_HANDLE impGetTypeHandleClass();
3328     CORINFO_CLASS_HANDLE impGetStringClass();
3329     CORINFO_CLASS_HANDLE impGetObjectClass();
3330
3331     // Returns underlying type of handles returned by ldtoken instruction
3332     var_types GetRuntimeHandleUnderlyingType()
3333     {
3334         // RuntimeTypeHandle is backed by raw pointer on CoreRT and by object reference on other runtimes
3335         return IsTargetAbi(CORINFO_CORERT_ABI) ? TYP_I_IMPL : TYP_REF;
3336     }
3337
3338     void impDevirtualizeCall(GenTreeCall*            call,
3339                              CORINFO_METHOD_HANDLE*  method,
3340                              unsigned*               methodFlags,
3341                              CORINFO_CONTEXT_HANDLE* contextHandle,
3342                              CORINFO_CONTEXT_HANDLE* exactContextHandle,
3343                              bool                    isLateDevirtualization,
3344                              bool                    isExplicitTailCall);
3345
3346     //=========================================================================
3347     //                          PROTECTED
3348     //=========================================================================
3349
3350 protected:
3351     //-------------------- Stack manipulation ---------------------------------
3352
3353     unsigned impStkSize; // Size of the full stack
3354
3355 #define SMALL_STACK_SIZE 16 // number of elements in impSmallStack
3356
3357     struct SavedStack // used to save/restore stack contents.
3358     {
3359         unsigned    ssDepth; // number of values on stack
3360         StackEntry* ssTrees; // saved tree values
3361     };
3362
3363     bool impIsPrimitive(CorInfoType type);
3364     bool impILConsumesAddr(const BYTE* codeAddr, CORINFO_METHOD_HANDLE fncHandle, CORINFO_MODULE_HANDLE scpHandle);
3365
3366     void impResolveToken(const BYTE* addr, CORINFO_RESOLVED_TOKEN* pResolvedToken, CorInfoTokenKind kind);
3367
3368     void impPushOnStack(GenTree* tree, typeInfo ti);
3369     void        impPushNullObjRefOnStack();
3370     StackEntry  impPopStack();
3371     StackEntry& impStackTop(unsigned n = 0);
3372     unsigned impStackHeight();
3373
3374     void impSaveStackState(SavedStack* savePtr, bool copy);
3375     void impRestoreStackState(SavedStack* savePtr);
3376
3377     GenTree* impImportLdvirtftn(GenTree* thisPtr, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
3378
3379     void impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken);
3380
3381     void impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
3382
3383     bool impCanPInvokeInline();
3384     bool impCanPInvokeInlineCallSite(BasicBlock* block);
3385     void impCheckForPInvokeCall(
3386         GenTreeCall* call, CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sig, unsigned mflags, BasicBlock* block);
3387     GenTreeCall* impImportIndirectCall(CORINFO_SIG_INFO* sig, IL_OFFSETX ilOffset = BAD_IL_OFFSET);
3388     void impPopArgsForUnmanagedCall(GenTree* call, CORINFO_SIG_INFO* sig);
3389
3390     void impInsertHelperCall(CORINFO_HELPER_DESC* helperCall);
3391     void impHandleAccessAllowed(CorInfoIsAccessAllowedResult result, CORINFO_HELPER_DESC* helperCall);
3392     void impHandleAccessAllowedInternal(CorInfoIsAccessAllowedResult result, CORINFO_HELPER_DESC* helperCall);
3393
3394     var_types impImportCall(OPCODE                  opcode,
3395                             CORINFO_RESOLVED_TOKEN* pResolvedToken,
3396                             CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, // Is this a "constrained." call on a
3397                                                                                // type parameter?
3398                             GenTree*           newobjThis,
3399                             int                prefixFlags,
3400                             CORINFO_CALL_INFO* callInfo,
3401                             IL_OFFSET          rawILOffset);
3402
3403     CORINFO_CLASS_HANDLE impGetSpecialIntrinsicExactReturnType(CORINFO_METHOD_HANDLE specialIntrinsicHandle);
3404
3405     bool impMethodInfo_hasRetBuffArg(CORINFO_METHOD_INFO* methInfo);
3406
3407     GenTree* impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HANDLE retClsHnd);
3408
3409     GenTree* impFixupStructReturnType(GenTree* op, CORINFO_CLASS_HANDLE retClsHnd);
3410
3411 #ifdef DEBUG
3412     var_types impImportJitTestLabelMark(int numArgs);
3413 #endif // DEBUG
3414
3415     GenTree* impInitClass(CORINFO_RESOLVED_TOKEN* pResolvedToken);
3416
3417     GenTree* impImportStaticReadOnlyField(void* fldAddr, var_types lclTyp);
3418
3419     GenTree* impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3420                                         CORINFO_ACCESS_FLAGS    access,
3421                                         CORINFO_FIELD_INFO*     pFieldInfo,
3422                                         var_types               lclTyp);
3423
3424     static void impBashVarAddrsToI(GenTree* tree1, GenTree* tree2 = nullptr);
3425
3426     GenTree* impImplicitIorI4Cast(GenTree* tree, var_types dstTyp);
3427
3428     GenTree* impImplicitR4orR8Cast(GenTree* tree, var_types dstTyp);
3429
3430     void impImportLeave(BasicBlock* block);
3431     void impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr);
3432     GenTree* impIntrinsic(GenTree*                newobjThis,
3433                           CORINFO_CLASS_HANDLE    clsHnd,
3434                           CORINFO_METHOD_HANDLE   method,
3435                           CORINFO_SIG_INFO*       sig,
3436                           unsigned                methodFlags,
3437                           int                     memberRef,
3438                           bool                    readonlyCall,
3439                           bool                    tailCall,
3440                           CORINFO_RESOLVED_TOKEN* pContstrainedResolvedToken,
3441                           CORINFO_THIS_TRANSFORM  constraintCallThisTransform,
3442                           CorInfoIntrinsics*      pIntrinsicID,
3443                           bool*                   isSpecialIntrinsic = nullptr);
3444     GenTree* impMathIntrinsic(CORINFO_METHOD_HANDLE method,
3445                               CORINFO_SIG_INFO*     sig,
3446                               var_types             callType,
3447                               CorInfoIntrinsics     intrinsicID,
3448                               bool                  tailCall);
3449     NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method);
3450
3451 #ifdef FEATURE_HW_INTRINSICS
3452     GenTree* impHWIntrinsic(NamedIntrinsic        intrinsic,
3453                             CORINFO_METHOD_HANDLE method,
3454                             CORINFO_SIG_INFO*     sig,
3455                             bool                  mustExpand);
3456     GenTree* impUnsupportedHWIntrinsic(unsigned              helper,
3457                                        CORINFO_METHOD_HANDLE method,
3458                                        CORINFO_SIG_INFO*     sig,
3459                                        bool                  mustExpand);
3460
3461 protected:
3462     bool compSupportsHWIntrinsic(InstructionSet isa);
3463
3464 #ifdef _TARGET_XARCH_
3465     GenTree* impBaseIntrinsic(NamedIntrinsic        intrinsic,
3466                               CORINFO_METHOD_HANDLE method,
3467                               CORINFO_SIG_INFO*     sig,
3468                               bool                  mustExpand);
3469     GenTree* impSSEIntrinsic(NamedIntrinsic        intrinsic,
3470                              CORINFO_METHOD_HANDLE method,
3471                              CORINFO_SIG_INFO*     sig,
3472                              bool                  mustExpand);
3473     GenTree* impSSE2Intrinsic(NamedIntrinsic        intrinsic,
3474                               CORINFO_METHOD_HANDLE method,
3475                               CORINFO_SIG_INFO*     sig,
3476                               bool                  mustExpand);
3477     GenTree* impSSE42Intrinsic(NamedIntrinsic        intrinsic,
3478                                CORINFO_METHOD_HANDLE method,
3479                                CORINFO_SIG_INFO*     sig,
3480                                bool                  mustExpand);
3481     GenTree* impAvxOrAvx2Intrinsic(NamedIntrinsic        intrinsic,
3482                                    CORINFO_METHOD_HANDLE method,
3483                                    CORINFO_SIG_INFO*     sig,
3484                                    bool                  mustExpand);
3485     GenTree* impAESIntrinsic(NamedIntrinsic        intrinsic,
3486                              CORINFO_METHOD_HANDLE method,
3487                              CORINFO_SIG_INFO*     sig,
3488                              bool                  mustExpand);
3489     GenTree* impBMI1OrBMI2Intrinsic(NamedIntrinsic        intrinsic,
3490                                     CORINFO_METHOD_HANDLE method,
3491                                     CORINFO_SIG_INFO*     sig,
3492                                     bool                  mustExpand);
3493     GenTree* impFMAIntrinsic(NamedIntrinsic        intrinsic,
3494                              CORINFO_METHOD_HANDLE method,
3495                              CORINFO_SIG_INFO*     sig,
3496                              bool                  mustExpand);
3497     GenTree* impLZCNTIntrinsic(NamedIntrinsic        intrinsic,
3498                                CORINFO_METHOD_HANDLE method,
3499                                CORINFO_SIG_INFO*     sig,
3500                                bool                  mustExpand);
3501     GenTree* impPCLMULQDQIntrinsic(NamedIntrinsic        intrinsic,
3502                                    CORINFO_METHOD_HANDLE method,
3503                                    CORINFO_SIG_INFO*     sig,
3504                                    bool                  mustExpand);
3505     GenTree* impPOPCNTIntrinsic(NamedIntrinsic        intrinsic,
3506                                 CORINFO_METHOD_HANDLE method,
3507                                 CORINFO_SIG_INFO*     sig,
3508                                 bool                  mustExpand);
3509
3510 protected:
3511     GenTree* getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass);
3512     GenTree* impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, var_types baseType);
3513     GenTree* addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* lastOp, bool mustExpand);
3514 #endif // _TARGET_XARCH_
3515 #ifdef _TARGET_ARM64_
3516     InstructionSet lookupHWIntrinsicISA(const char* className);
3517     NamedIntrinsic lookupHWIntrinsic(const char* className, const char* methodName);
3518     GenTree* addRangeCheckIfNeeded(GenTree* lastOp, unsigned int max, bool mustExpand);
3519 #endif // _TARGET_ARM64_
3520 #endif // FEATURE_HW_INTRINSICS
3521     GenTree* impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
3522                                      CORINFO_SIG_INFO*    sig,
3523                                      int                  memberRef,
3524                                      bool                 readonlyCall,
3525                                      CorInfoIntrinsics    intrinsicID);
3526     GenTree* impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig);
3527
3528     GenTree* impMethodPointer(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
3529
3530     GenTree* impTransformThis(GenTree*                thisPtr,
3531                               CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
3532                               CORINFO_THIS_TRANSFORM  transform);
3533
3534     //----------------- Manipulating the trees and stmts ----------------------
3535
3536     GenTree* impTreeList; // Trees for the BB being imported
3537     GenTree* impTreeLast; // The last tree for the current BB
3538
3539 public:
3540     enum
3541     {
3542         CHECK_SPILL_ALL  = -1,
3543         CHECK_SPILL_NONE = -2
3544     };
3545
3546     void impBeginTreeList();
3547     void impEndTreeList(BasicBlock* block, GenTree* firstStmt, GenTree* lastStmt);
3548     void impEndTreeList(BasicBlock* block);
3549     void impAppendStmtCheck(GenTree* stmt, unsigned chkLevel);
3550     void impAppendStmt(GenTree* stmt, unsigned chkLevel);
3551     void impInsertStmtBefore(GenTree* stmt, GenTree* stmtBefore);
3552     GenTree* impAppendTree(GenTree* tree, unsigned chkLevel, IL_OFFSETX offset);
3553     void impInsertTreeBefore(GenTree* tree, IL_OFFSETX offset, GenTree* stmtBefore);
3554     void impAssignTempGen(unsigned    tmp,
3555                           GenTree*    val,
3556                           unsigned    curLevel,
3557                           GenTree**   pAfterStmt = nullptr,
3558                           IL_OFFSETX  ilOffset   = BAD_IL_OFFSET,
3559                           BasicBlock* block      = nullptr);
3560     void impAssignTempGen(unsigned             tmpNum,
3561                           GenTree*             val,
3562                           CORINFO_CLASS_HANDLE structHnd,
3563                           unsigned             curLevel,
3564                           GenTree**            pAfterStmt = nullptr,
3565                           IL_OFFSETX           ilOffset   = BAD_IL_OFFSET,
3566                           BasicBlock*          block      = nullptr);
3567     GenTree* impCloneExpr(GenTree*             tree,
3568                           GenTree**            clone,
3569                           CORINFO_CLASS_HANDLE structHnd,
3570                           unsigned             curLevel,
3571                           GenTree** pAfterStmt DEBUGARG(const char* reason));
3572     GenTree* impAssignStruct(GenTree*             dest,
3573                              GenTree*             src,
3574                              CORINFO_CLASS_HANDLE structHnd,
3575                              unsigned             curLevel,
3576                              GenTree**            pAfterStmt = nullptr,
3577                              IL_OFFSETX           ilOffset   = BAD_IL_OFFSET,
3578                              BasicBlock*          block      = nullptr);
3579     GenTree* impAssignStructPtr(GenTree*             dest,
3580                                 GenTree*             src,
3581                                 CORINFO_CLASS_HANDLE structHnd,
3582                                 unsigned             curLevel,
3583                                 GenTree**            pAfterStmt = nullptr,
3584                                 IL_OFFSETX           ilOffset   = BAD_IL_OFFSET,
3585                                 BasicBlock*          block      = nullptr);
3586
3587     GenTree* impGetStructAddr(GenTree* structVal, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, bool willDeref);
3588
3589     var_types impNormStructType(CORINFO_CLASS_HANDLE structHnd,
3590                                 BYTE*                gcLayout     = nullptr,
3591                                 unsigned*            numGCVars    = nullptr,
3592                                 var_types*           simdBaseType = nullptr);
3593
3594     GenTree* impNormStructVal(GenTree*             structVal,
3595                               CORINFO_CLASS_HANDLE structHnd,
3596                               unsigned             curLevel,
3597                               bool                 forceNormalization = false);
3598
3599     GenTree* impTokenToHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3600                               BOOL*                   pRuntimeLookup    = nullptr,
3601                               BOOL                    mustRestoreHandle = FALSE,
3602                               BOOL                    importParent      = FALSE);
3603
3604     GenTree* impParentClassTokenToHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3605                                          BOOL*                   pRuntimeLookup    = nullptr,
3606                                          BOOL                    mustRestoreHandle = FALSE)
3607     {
3608         return impTokenToHandle(pResolvedToken, pRuntimeLookup, mustRestoreHandle, TRUE);
3609     }
3610
3611     GenTree* impLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3612                              CORINFO_LOOKUP*         pLookup,
3613                              unsigned                flags,
3614                              void*                   compileTimeHandle);
3615
3616     GenTree* getRuntimeContextTree(CORINFO_RUNTIME_LOOKUP_KIND kind);
3617
3618     GenTree* impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3619                                     CORINFO_LOOKUP*         pLookup,
3620                                     void*                   compileTimeHandle);
3621
3622     GenTree* impReadyToRunLookupToTree(CORINFO_CONST_LOOKUP* pLookup, unsigned flags, void* compileTimeHandle);
3623
3624     GenTreeCall* impReadyToRunHelperToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3625                                            CorInfoHelpFunc         helper,
3626                                            var_types               type,
3627                                            GenTreeArgList*         arg                = nullptr,
3628                                            CORINFO_LOOKUP_KIND*    pGenericLookupKind = nullptr);
3629
3630     GenTree* impCastClassOrIsInstToTree(GenTree*                op1,
3631                                         GenTree*                op2,
3632                                         CORINFO_RESOLVED_TOKEN* pResolvedToken,
3633                                         bool                    isCastClass);
3634
3635     GenTree* impOptimizeCastClassOrIsInst(GenTree* op1, CORINFO_RESOLVED_TOKEN* pResolvedToken, bool isCastClass);
3636
3637     bool VarTypeIsMultiByteAndCanEnreg(
3638         var_types type, CORINFO_CLASS_HANDLE typeClass, unsigned* typeSize, bool forReturn, bool isVarArg);
3639
3640     bool IsIntrinsicImplementedByUserCall(CorInfoIntrinsics intrinsicId);
3641     bool IsTargetIntrinsic(CorInfoIntrinsics intrinsicId);
3642     bool IsMathIntrinsic(CorInfoIntrinsics intrinsicId);
3643     bool IsMathIntrinsic(GenTree* tree);
3644
3645 private:
3646     //----------------- Importing the method ----------------------------------
3647
3648     CORINFO_CONTEXT_HANDLE impTokenLookupContextHandle; // The context used for looking up tokens.
3649
3650 #ifdef DEBUG
3651     unsigned    impCurOpcOffs;
3652     const char* impCurOpcName;
3653     bool        impNestedStackSpill;
3654
3655     // For displaying instrs with generated native code (-n:B)
3656     GenTree* impLastILoffsStmt; // oldest stmt added for which we did not gtStmtLastILoffs
3657     void     impNoteLastILoffs();
3658 #endif
3659
3660     /* IL offset of the stmt currently being imported. It gets set to
3661        BAD_IL_OFFSET after it has been set in the appended trees. Then it gets
3662        updated at IL offsets for which we have to report mapping info.
3663        It also includes flag bits, so use jitGetILoffs()
3664        to get the actual IL offset value.
3665     */
3666
3667     IL_OFFSETX impCurStmtOffs;
3668     void impCurStmtOffsSet(IL_OFFSET offs);
3669
3670     void impNoteBranchOffs();
3671
3672     unsigned impInitBlockLineInfo();
3673
3674     GenTree* impCheckForNullPointer(GenTree* obj);
3675     bool impIsThis(GenTree* obj);
3676     bool impIsLDFTN_TOKEN(const BYTE* delegateCreateStart, const BYTE* newobjCodeAddr);
3677     bool impIsDUP_LDVIRTFTN_TOKEN(const BYTE* delegateCreateStart, const BYTE* newobjCodeAddr);
3678     bool impIsAnySTLOC(OPCODE opcode)
3679     {
3680         return ((opcode == CEE_STLOC) || (opcode == CEE_STLOC_S) ||
3681                 ((opcode >= CEE_STLOC_0) && (opcode <= CEE_STLOC_3)));
3682     }
3683
3684     GenTreeArgList* impPopList(unsigned count, CORINFO_SIG_INFO* sig, GenTreeArgList* prefixTree = nullptr);
3685
3686     GenTreeArgList* impPopRevList(unsigned count, CORINFO_SIG_INFO* sig, unsigned skipReverseCount = 0);
3687
3688     /*
3689      * Get current IL offset with stack-empty info incoporated
3690      */
3691     IL_OFFSETX impCurILOffset(IL_OFFSET offs, bool callInstruction = false);
3692
3693     //---------------- Spilling the importer stack ----------------------------
3694
3695     // The maximum number of bytes of IL processed without clean stack state.
3696     // It allows to limit the maximum tree size and depth.
3697     static const unsigned MAX_TREE_SIZE = 200;
3698     bool impCanSpillNow(OPCODE prevOpcode);
3699
3700     struct PendingDsc
3701     {
3702         PendingDsc*   pdNext;
3703         BasicBlock*   pdBB;
3704         SavedStack    pdSavedStack;
3705         ThisInitState pdThisPtrInit;
3706     };
3707
3708     PendingDsc* impPendingList; // list of BBs currently waiting to be imported.
3709     PendingDsc* impPendingFree; // Freed up dscs that can be reused
3710
3711     // We keep a byte-per-block map (dynamically extended) in the top-level Compiler object of a compilation.
3712     JitExpandArray<BYTE> impPendingBlockMembers;
3713
3714     // Return the byte for "b" (allocating/extending impPendingBlockMembers if necessary.)
3715     // Operates on the map in the top-level ancestor.
3716     BYTE impGetPendingBlockMember(BasicBlock* blk)
3717     {
3718         return impInlineRoot()->impPendingBlockMembers.Get(blk->bbInd());
3719     }
3720
3721     // Set the byte for "b" to "val" (allocating/extending impPendingBlockMembers if necessary.)
3722     // Operates on the map in the top-level ancestor.
3723     void impSetPendingBlockMember(BasicBlock* blk, BYTE val)
3724     {
3725         impInlineRoot()->impPendingBlockMembers.Set(blk->bbInd(), val);
3726     }
3727
3728     bool impCanReimport;
3729
3730     bool impSpillStackEntry(unsigned level,
3731                             unsigned varNum
3732 #ifdef DEBUG
3733                             ,
3734                             bool        bAssertOnRecursion,
3735                             const char* reason
3736 #endif
3737                             );
3738
3739     void impSpillStackEnsure(bool spillLeaves = false);
3740     void impEvalSideEffects();
3741     void impSpillSpecialSideEff();
3742     void impSpillSideEffects(bool spillGlobEffects, unsigned chkLevel DEBUGARG(const char* reason));
3743     void               impSpillValueClasses();
3744     void               impSpillEvalStack();
3745     static fgWalkPreFn impFindValueClasses;
3746     void impSpillLclRefs(ssize_t lclNum);
3747
3748     BasicBlock* impPushCatchArgOnStack(BasicBlock* hndBlk, CORINFO_CLASS_HANDLE clsHnd, bool isSingleBlockFilter);
3749
3750     void impImportBlockCode(BasicBlock* block);
3751
3752     void impReimportMarkBlock(BasicBlock* block);
3753     void impReimportMarkSuccessors(BasicBlock* block);
3754
3755     void impVerifyEHBlock(BasicBlock* block, bool isTryStart);
3756
3757     void impImportBlockPending(BasicBlock* block);
3758
3759     // Similar to impImportBlockPending, but assumes that block has already been imported once and is being
3760     // reimported for some reason.  It specifically does *not* look at verCurrentState to set the EntryState
3761     // for the block, but instead, just re-uses the block's existing EntryState.
3762     void impReimportBlockPending(BasicBlock* block);
3763
3764     var_types impGetByRefResultType(genTreeOps oper, bool fUnsigned, GenTree** pOp1, GenTree** pOp2);
3765
3766     void impImportBlock(BasicBlock* block);
3767
3768     // Assumes that "block" is a basic block that completes with a non-empty stack. We will assign the values
3769     // on the stack to local variables (the "spill temp" variables). The successor blocks will assume that
3770     // its incoming stack contents are in those locals. This requires "block" and its successors to agree on
3771     // the variables that will be used -- and for all the predecessors of those successors, and the
3772     // successors of those predecessors, etc. Call such a set of blocks closed under alternating
3773     // successor/predecessor edges a "spill clique." A block is a "predecessor" or "successor" member of the
3774     // clique (or, conceivably, both). Each block has a specified sequence of incoming and outgoing spill
3775     // temps. If "block" already has its outgoing spill temps assigned (they are always a contiguous series
3776     // of local variable numbers, so we represent them with the base local variable number), returns that.
3777     // Otherwise, picks a set of spill temps, and propagates this choice to all blocks in the spill clique of
3778     // which "block" is a member (asserting, in debug mode, that no block in this clique had its spill temps
3779     // chosen already. More precisely, that the incoming or outgoing spill temps are not chosen, depending
3780     // on which kind of member of the clique the block is).
3781     unsigned impGetSpillTmpBase(BasicBlock* block);
3782
3783     // Assumes that "block" is a basic block that completes with a non-empty stack. We have previously
3784     // assigned the values on the stack to local variables (the "spill temp" variables). The successor blocks
3785     // will assume that its incoming stack contents are in those locals. This requires "block" and its
3786     // successors to agree on the variables and their types that will be used.  The CLI spec allows implicit
3787     // conversions between 'int' and 'native int' or 'float' and 'double' stack types. So one predecessor can
3788     // push an int and another can push a native int.  For 64-bit we have chosen to implement this by typing
3789     // the "spill temp" as native int, and then importing (or re-importing as needed) so that all the
3790     // predecessors in the "spill clique" push a native int (sign-extending if needed), and all the
3791     // successors receive a native int. Similarly float and double are unified to double.
3792     // This routine is called after a type-mismatch is detected, and it will walk the spill clique to mark
3793     // blocks for re-importation as appropriate (both successors, so they get the right incoming type, and
3794     // predecessors, so they insert an upcast if needed).
3795     void impReimportSpillClique(BasicBlock* block);
3796
3797     // When we compute a "spill clique" (see above) these byte-maps are allocated to have a byte per basic
3798     // block, and represent the predecessor and successor members of the clique currently being computed.
3799     // *** Access to these will need to be locked in a parallel compiler.
3800     JitExpandArray<BYTE> impSpillCliquePredMembers;
3801     JitExpandArray<BYTE> impSpillCliqueSuccMembers;
3802
3803     enum SpillCliqueDir
3804     {
3805         SpillCliquePred,
3806         SpillCliqueSucc
3807     };
3808
3809     // Abstract class for receiving a callback while walking a spill clique
3810     class SpillCliqueWalker
3811     {
3812     public:
3813         virtual void Visit(SpillCliqueDir predOrSucc, BasicBlock* blk) = 0;
3814     };
3815
3816     // This class is used for setting the bbStkTempsIn and bbStkTempsOut on the blocks within a spill clique
3817     class SetSpillTempsBase : public SpillCliqueWalker
3818     {
3819         unsigned m_baseTmp;
3820
3821     public:
3822         SetSpillTempsBase(unsigned baseTmp) : m_baseTmp(baseTmp)
3823         {
3824         }
3825         virtual void Visit(SpillCliqueDir predOrSucc, BasicBlock* blk);
3826     };
3827
3828     // This class is used for implementing impReimportSpillClique part on each block within the spill clique
3829     class ReimportSpillClique : public SpillCliqueWalker
3830     {
3831         Compiler* m_pComp;
3832
3833     public:
3834         ReimportSpillClique(Compiler* pComp) : m_pComp(pComp)
3835         {
3836         }
3837         virtual void Visit(SpillCliqueDir predOrSucc, BasicBlock* blk);
3838     };
3839
3840     // This is the heart of the algorithm for walking spill cliques. It invokes callback->Visit for each
3841     // predecessor or successor within the spill clique
3842     void impWalkSpillCliqueFromPred(BasicBlock* pred, SpillCliqueWalker* callback);
3843
3844     // For a BasicBlock that has already been imported, the EntryState has an array of GenTrees for the
3845     // incoming locals. This walks that list an resets the types of the GenTrees to match the types of
3846     // the VarDscs. They get out of sync when we have int/native int issues (see impReimportSpillClique).
3847     void impRetypeEntryStateTemps(BasicBlock* blk);
3848
3849     BYTE impSpillCliqueGetMember(SpillCliqueDir predOrSucc, BasicBlock* blk);
3850     void impSpillCliqueSetMember(SpillCliqueDir predOrSucc, BasicBlock* blk, BYTE val);
3851
3852     void impPushVar(GenTree* op, typeInfo tiRetVal);
3853     void impLoadVar(unsigned lclNum, IL_OFFSET offset, typeInfo tiRetVal);
3854     void impLoadVar(unsigned lclNum, IL_OFFSET offset)
3855     {
3856         impLoadVar(lclNum, offset, lvaTable[lclNum].lvVerTypeInfo);
3857     }
3858     void impLoadArg(unsigned ilArgNum, IL_OFFSET offset);
3859     void impLoadLoc(unsigned ilLclNum, IL_OFFSET offset);
3860     bool impReturnInstruction(BasicBlock* block, int prefixFlags, OPCODE& opcode);
3861
3862 #ifdef _TARGET_ARM_
3863     void impMarkLclDstNotPromotable(unsigned tmpNum, GenTree* op, CORINFO_CLASS_HANDLE hClass);
3864 #endif
3865
3866     // A free list of linked list nodes used to represent to-do stacks of basic blocks.
3867     struct BlockListNode
3868     {
3869         BasicBlock*    m_blk;
3870         BlockListNode* m_next;
3871         BlockListNode(BasicBlock* blk, BlockListNode* next = nullptr) : m_blk(blk), m_next(next)
3872         {
3873         }
3874         void* operator new(size_t sz, Compiler* comp);
3875     };
3876     BlockListNode* impBlockListNodeFreeList;
3877
3878     void FreeBlockListNode(BlockListNode* node);
3879
3880     bool impIsValueType(typeInfo* pTypeInfo);
3881     var_types mangleVarArgsType(var_types type);
3882
3883 #if FEATURE_VARARG
3884     regNumber getCallArgIntRegister(regNumber floatReg);
3885     regNumber getCallArgFloatRegister(regNumber intReg);
3886 #endif // FEATURE_VARARG
3887
3888 #if defined(DEBUG)
3889     static unsigned jitTotalMethodCompiled;
3890 #endif
3891
3892 #ifdef DEBUG
3893     static LONG jitNestingLevel;
3894 #endif // DEBUG
3895
3896     static BOOL impIsAddressInLocal(GenTree* tree, GenTree** lclVarTreeOut);
3897
3898     void impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, InlineResult* inlineResult);
3899
3900     // STATIC inlining decision based on the IL code.
3901     void impCanInlineIL(CORINFO_METHOD_HANDLE fncHandle,
3902                         CORINFO_METHOD_INFO*  methInfo,
3903                         bool                  forceInline,
3904                         InlineResult*         inlineResult);
3905
3906     void impCheckCanInline(GenTreeCall*           call,
3907                            CORINFO_METHOD_HANDLE  fncHandle,
3908                            unsigned               methAttr,
3909                            CORINFO_CONTEXT_HANDLE exactContextHnd,
3910                            InlineCandidateInfo**  ppInlineCandidateInfo,
3911                            InlineResult*          inlineResult);
3912
3913     void impInlineRecordArgInfo(InlineInfo*   pInlineInfo,
3914                                 GenTree*      curArgVal,
3915                                 unsigned      argNum,
3916                                 InlineResult* inlineResult);
3917
3918     void impInlineInitVars(InlineInfo* pInlineInfo);
3919
3920     unsigned impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reason));
3921
3922     GenTree* impInlineFetchArg(unsigned lclNum, InlArgInfo* inlArgInfo, InlLclVarInfo* lclTypeInfo);
3923
3924     BOOL impInlineIsThis(GenTree* tree, InlArgInfo* inlArgInfo);
3925
3926     BOOL impInlineIsGuaranteedThisDerefBeforeAnySideEffects(GenTree*    additionalTreesToBeEvaluatedBefore,
3927                                                             GenTree*    variableBeingDereferenced,
3928                                                             InlArgInfo* inlArgInfo);
3929
3930     void impMarkInlineCandidate(GenTree*               call,
3931                                 CORINFO_CONTEXT_HANDLE exactContextHnd,
3932                                 bool                   exactContextNeedsRuntimeLookup,
3933                                 CORINFO_CALL_INFO*     callInfo);
3934
3935     void impMarkInlineCandidateHelper(GenTreeCall*           call,
3936                                       CORINFO_CONTEXT_HANDLE exactContextHnd,
3937                                       bool                   exactContextNeedsRuntimeLookup,
3938                                       CORINFO_CALL_INFO*     callInfo);
3939
3940     bool impTailCallRetTypeCompatible(var_types            callerRetType,
3941                                       CORINFO_CLASS_HANDLE callerRetTypeClass,
3942                                       var_types            calleeRetType,
3943                                       CORINFO_CLASS_HANDLE calleeRetTypeClass);
3944
3945     bool impIsTailCallILPattern(bool        tailPrefixed,
3946                                 OPCODE      curOpcode,
3947                                 const BYTE* codeAddrOfNextOpcode,
3948                                 const BYTE* codeEnd,
3949                                 bool        isRecursive,
3950                                 bool*       IsCallPopRet = nullptr);
3951
3952     bool impIsImplicitTailCallCandidate(
3953         OPCODE curOpcode, const BYTE* codeAddrOfNextOpcode, const BYTE* codeEnd, int prefixFlags, bool isRecursive);
3954
3955     CORINFO_RESOLVED_TOKEN* impAllocateToken(CORINFO_RESOLVED_TOKEN token);
3956
3957     /*
3958     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3959     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3960     XX                                                                           XX
3961     XX                           FlowGraph                                       XX
3962     XX                                                                           XX
3963     XX   Info about the basic-blocks, their contents and the flow analysis       XX
3964     XX                                                                           XX
3965     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3966     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3967     */
3968
3969 public:
3970     BasicBlock* fgFirstBB;        // Beginning of the basic block list
3971     BasicBlock* fgLastBB;         // End of the basic block list
3972     BasicBlock* fgFirstColdBlock; // First block to be placed in the cold section
3973 #if FEATURE_EH_FUNCLETS
3974     BasicBlock* fgFirstFuncletBB; // First block of outlined funclets (to allow block insertion before the funclets)
3975 #endif
3976     BasicBlock* fgFirstBBScratch;   // Block inserted for initialization stuff. Is nullptr if no such block has been
3977                                     // created.
3978     BasicBlockList* fgReturnBlocks; // list of BBJ_RETURN blocks
3979     unsigned        fgEdgeCount;    // # of control flow edges between the BBs
3980     unsigned        fgBBcount;      // # of BBs in the method
3981 #ifdef DEBUG
3982     unsigned fgBBcountAtCodegen; // # of BBs in the method at the start of codegen
3983 #endif
3984     unsigned     fgBBNumMax;       // The max bbNum that has been assigned to basic blocks
3985     unsigned     fgDomBBcount;     // # of BBs for which we have dominator and reachability information
3986     BasicBlock** fgBBInvPostOrder; // The flow graph stored in an array sorted in topological order, needed to compute
3987                                    // dominance. Indexed by block number. Size: fgBBNumMax + 1.
3988
3989     // After the dominance tree is computed, we cache a DFS preorder number and DFS postorder number to compute
3990     // dominance queries in O(1). fgDomTreePreOrder and fgDomTreePostOrder are arrays giving the block's preorder and
3991     // postorder number, respectively. The arrays are indexed by basic block number. (Note that blocks are numbered
3992     // starting from one. Thus, we always waste element zero. This makes debugging easier and makes the code less likely
3993     // to suffer from bugs stemming from forgetting to add or subtract one from the block number to form an array
3994     // index). The arrays are of size fgBBNumMax + 1.
3995     unsigned* fgDomTreePreOrder;
3996     unsigned* fgDomTreePostOrder;
3997
3998     bool fgBBVarSetsInited;
3999
4000     // Allocate array like T* a = new T[fgBBNumMax + 1];
4001     // Using helper so we don't keep forgetting +1.
4002     template <typename T>
4003     T* fgAllocateTypeForEachBlk(CompMemKind cmk = CMK_Unknown)
4004     {
4005         return getAllocator(cmk).allocate<T>(fgBBNumMax + 1);
4006     }
4007
4008     // BlockSets are relative to a specific set of BasicBlock numbers. If that changes
4009     // (if the blocks are renumbered), this changes. BlockSets from different epochs
4010     // cannot be meaningfully combined. Note that new blocks can be created with higher
4011     // block numbers without changing the basic block epoch. These blocks *cannot*
4012     // participate in a block set until the blocks are all renumbered, causing the epoch
4013     // to change. This is useful if continuing to use previous block sets is valuable.
4014     // If the epoch is zero, then it is uninitialized, and block sets can't be used.
4015     unsigned fgCurBBEpoch;
4016
4017     unsigned GetCurBasicBlockEpoch()
4018     {
4019         return fgCurBBEpoch;
4020     }
4021
4022     // The number of basic blocks in the current epoch. When the blocks are renumbered,
4023     // this is fgBBcount. As blocks are added, fgBBcount increases, fgCurBBEpochSize remains
4024     // the same, until a new BasicBlock epoch is created, such as when the blocks are all renumbered.
4025     unsigned fgCurBBEpochSize;
4026
4027     // The number of "size_t" elements required to hold a bitset large enough for fgCurBBEpochSize
4028     // bits. This is precomputed to avoid doing math every time BasicBlockBitSetTraits::GetArrSize() is called.
4029     unsigned fgBBSetCountInSizeTUnits;
4030
4031     void NewBasicBlockEpoch()
4032     {
4033         INDEBUG(unsigned oldEpochArrSize = fgBBSetCountInSizeTUnits);
4034
4035         // We have a new epoch. Compute and cache the size needed for new BlockSets.
4036         fgCurBBEpoch++;
4037         fgCurBBEpochSize = fgBBNumMax + 1;
4038         fgBBSetCountInSizeTUnits =
4039             roundUp(fgCurBBEpochSize, (unsigned)(sizeof(size_t) * 8)) / unsigned(sizeof(size_t) * 8);
4040
4041 #ifdef DEBUG
4042         // All BlockSet objects are now invalid!
4043         fgReachabilitySetsValid = false; // the bbReach sets are now invalid!
4044         fgEnterBlksSetValid     = false; // the fgEnterBlks set is now invalid!
4045
4046         if (verbose)
4047         {
4048             unsigned epochArrSize = BasicBlockBitSetTraits::GetArrSize(this, sizeof(size_t));
4049             printf("\nNew BlockSet epoch %d, # of blocks (including unused BB00): %u, bitset array size: %u (%s)",
4050                    fgCurBBEpoch, fgCurBBEpochSize, epochArrSize, (epochArrSize <= 1) ? "short" : "long");
4051             if ((fgCurBBEpoch != 1) && ((oldEpochArrSize <= 1) != (epochArrSize <= 1)))
4052             {
4053                 // If we're not just establishing the first epoch, and the epoch array size has changed such that we're
4054                 // going to change our bitset representation from short (just a size_t bitset) to long (a pointer to an
4055                 // array of size_t bitsets), then print that out.
4056                 printf("; NOTE: BlockSet size was previously %s!", (oldEpochArrSize <= 1) ? "short" : "long");
4057             }
4058             printf("\n");
4059         }
4060 #endif // DEBUG
4061     }
4062
4063     void EnsureBasicBlockEpoch()
4064     {
4065         if (fgCurBBEpochSize != fgBBNumMax + 1)
4066         {
4067             NewBasicBlockEpoch();
4068         }
4069     }
4070
4071     BasicBlock* fgNewBasicBlock(BBjumpKinds jumpKind);
4072     void fgEnsureFirstBBisScratch();
4073     bool fgFirstBBisScratch();
4074     bool fgBBisScratch(BasicBlock* block);
4075
4076     void fgExtendEHRegionBefore(BasicBlock* block);
4077     void fgExtendEHRegionAfter(BasicBlock* block);
4078
4079     BasicBlock* fgNewBBbefore(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion);
4080
4081     BasicBlock* fgNewBBafter(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion);
4082
4083     BasicBlock* fgNewBBinRegion(BBjumpKinds jumpKind,
4084                                 unsigned    tryIndex,
4085                                 unsigned    hndIndex,
4086                                 BasicBlock* nearBlk,
4087                                 bool        putInFilter = false,
4088                                 bool        runRarely   = false,
4089                                 bool        insertAtEnd = false);
4090
4091     BasicBlock* fgNewBBinRegion(BBjumpKinds jumpKind,
4092                                 BasicBlock* srcBlk,
4093                                 bool        runRarely   = false,
4094                                 bool        insertAtEnd = false);
4095
4096     BasicBlock* fgNewBBinRegion(BBjumpKinds jumpKind);
4097
4098     BasicBlock* fgNewBBinRegionWorker(BBjumpKinds jumpKind,
4099                                       BasicBlock* afterBlk,
4100                                       unsigned    xcptnIndex,
4101                                       bool        putInTryRegion);
4102
4103     void fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk);
4104     void fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk);
4105     void fgUnlinkBlock(BasicBlock* block);
4106
4107     unsigned fgMeasureIR();
4108
4109     bool fgModified;         // True if the flow graph has been modified recently
4110     bool fgComputePredsDone; // Have we computed the bbPreds list
4111     bool fgCheapPredsValid;  // Is the bbCheapPreds list valid?
4112     bool fgDomsComputed;     // Have we computed the dominator sets?
4113     bool fgOptimizedFinally; // Did we optimize any try-finallys?
4114
4115     bool fgHasSwitch; // any BBJ_SWITCH jumps?
4116
4117     BlockSet fgEnterBlks; // Set of blocks which have a special transfer of control; the "entry" blocks plus EH handler
4118                           // begin blocks.
4119
4120 #ifdef DEBUG
4121     bool fgReachabilitySetsValid; // Are the bbReach sets valid?
4122     bool fgEnterBlksSetValid;     // Is the fgEnterBlks set valid?
4123 #endif                            // DEBUG
4124
4125     bool fgRemoveRestOfBlock; // true if we know that we will throw
4126     bool fgStmtRemoved;       // true if we remove statements -> need new DFA
4127
4128     // There are two modes for ordering of the trees.
4129     //  - In FGOrderTree, the dominant ordering is the tree order, and the nodes contained in
4130     //    each tree and sub-tree are contiguous, and can be traversed (in gtNext/gtPrev order)
4131     //    by traversing the tree according to the order of the operands.
4132     //  - In FGOrderLinear, the dominant ordering is the linear order.
4133
4134     enum FlowGraphOrder
4135     {
4136         FGOrderTree,
4137         FGOrderLinear
4138     };
4139     FlowGraphOrder fgOrder;
4140
4141     // The following are boolean flags that keep track of the state of internal data structures
4142
4143     bool                 fgStmtListThreaded;       // true if the node list is now threaded
4144     bool                 fgCanRelocateEHRegions;   // true if we are allowed to relocate the EH regions
4145     bool                 fgEdgeWeightsComputed;    // true after we have called fgComputeEdgeWeights
4146     bool                 fgHaveValidEdgeWeights;   // true if we were successful in computing all of the edge weights
4147     bool                 fgSlopUsedInEdgeWeights;  // true if their was some slop used when computing the edge weights
4148     bool                 fgRangeUsedInEdgeWeights; // true if some of the edgeWeight are expressed in Min..Max form
4149     bool                 fgNeedsUpdateFlowGraph;   // true if we need to run fgUpdateFlowGraph
4150     BasicBlock::weight_t fgCalledCount;            // count of the number of times this method was called
4151                                                    // This is derived from the profile data
4152                                                    // or is BB_UNITY_WEIGHT when we don't have profile data
4153
4154 #if FEATURE_EH_FUNCLETS
4155     bool fgFuncletsCreated; // true if the funclet creation phase has been run
4156 #endif                      // FEATURE_EH_FUNCLETS
4157
4158     bool fgGlobalMorph; // indicates if we are during the global morphing phase
4159                         // since fgMorphTree can be called from several places
4160
4161     bool     impBoxTempInUse; // the temp below is valid and available
4162     unsigned impBoxTemp;      // a temporary that is used for boxing
4163
4164 #ifdef DEBUG
4165     bool jitFallbackCompile; // Are we doing a fallback compile? That is, have we executed a NO_WAY assert,
4166                              //   and we are trying to compile again in a "safer", minopts mode?
4167 #endif
4168
4169 #if defined(DEBUG)
4170     unsigned impInlinedCodeSize;
4171 #endif
4172
4173     //-------------------------------------------------------------------------
4174
4175     void fgInit();
4176
4177     void fgImport();
4178
4179     void fgTransformIndirectCalls();
4180
4181     void fgInline();
4182
4183     void fgRemoveEmptyTry();
4184
4185     void fgRemoveEmptyFinally();
4186
4187     void fgMergeFinallyChains();
4188
4189     void fgCloneFinally();
4190
4191     void fgCleanupContinuation(BasicBlock* continuation);
4192
4193     void fgUpdateFinallyTargetFlags();
4194
4195     void fgClearAllFinallyTargetBits();
4196
4197     void fgAddFinallyTargetFlags();
4198
4199 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
4200     // Sometimes we need to defer updating the BBF_FINALLY_TARGET bit. fgNeedToAddFinallyTargetBits signals
4201     // when this is necessary.
4202     bool fgNeedToAddFinallyTargetBits;
4203 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
4204
4205     bool fgRetargetBranchesToCanonicalCallFinally(BasicBlock*      block,
4206                                                   BasicBlock*      handler,
4207                                                   BlockToBlockMap& continuationMap);
4208
4209     GenTree* fgGetCritSectOfStaticMethod();
4210
4211 #if FEATURE_EH_FUNCLETS
4212
4213     void fgAddSyncMethodEnterExit();
4214
4215     GenTree* fgCreateMonitorTree(unsigned lvaMonitorBool, unsigned lvaThisVar, BasicBlock* block, bool enter);
4216
4217     void fgConvertSyncReturnToLeave(BasicBlock* block);
4218
4219 #endif // FEATURE_EH_FUNCLETS
4220
4221     void fgAddReversePInvokeEnterExit();
4222
4223     bool fgMoreThanOneReturnBlock();
4224
4225     // The number of separate return points in the method.
4226     unsigned fgReturnCount;
4227
4228     void fgAddInternal();
4229
4230     bool fgFoldConditional(BasicBlock* block);
4231
4232     void fgMorphStmts(BasicBlock* block, bool* lnot, bool* loadw);
4233     void fgMorphBlocks();
4234
4235     bool fgMorphBlockStmt(BasicBlock* block, GenTreeStmt* stmt DEBUGARG(const char* msg));
4236
4237     void fgSetOptions();
4238
4239 #ifdef DEBUG
4240     static fgWalkPreFn fgAssertNoQmark;
4241     void fgPreExpandQmarkChecks(GenTree* expr);
4242     void        fgPostExpandQmarkChecks();
4243     static void fgCheckQmarkAllowedForm(GenTree* tree);
4244 #endif
4245
4246     IL_OFFSET fgFindBlockILOffset(BasicBlock* block);
4247
4248     BasicBlock* fgSplitBlockAtBeginning(BasicBlock* curr);
4249     BasicBlock* fgSplitBlockAtEnd(BasicBlock* curr);
4250     BasicBlock* fgSplitBlockAfterStatement(BasicBlock* curr, GenTree* stmt);
4251     BasicBlock* fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node); // for LIR
4252     BasicBlock* fgSplitEdge(BasicBlock* curr, BasicBlock* succ);
4253
4254     GenTreeStmt* fgNewStmtFromTree(GenTree* tree, BasicBlock* block, IL_OFFSETX offs);
4255     GenTreeStmt* fgNewStmtFromTree(GenTree* tree);
4256     GenTreeStmt* fgNewStmtFromTree(GenTree* tree, BasicBlock* block);
4257     GenTreeStmt* fgNewStmtFromTree(GenTree* tree, IL_OFFSETX offs);
4258
4259     GenTree* fgGetTopLevelQmark(GenTree* expr, GenTree** ppDst = nullptr);
4260     void fgExpandQmarkForCastInstOf(BasicBlock* block, GenTree* stmt);
4261     void fgExpandQmarkStmt(BasicBlock* block, GenTree* expr);
4262     void fgExpandQmarkNodes();
4263
4264     void fgMorph();
4265
4266     // Do "simple lowering."  This functionality is (conceptually) part of "general"
4267     // lowering that is distributed between fgMorph and the lowering phase of LSRA.
4268     void fgSimpleLowering();
4269
4270     GenTree* fgInitThisClass();
4271
4272     GenTreeCall* fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfoHelpFunc helper);
4273
4274     GenTreeCall* fgGetSharedCCtor(CORINFO_CLASS_HANDLE cls);
4275
4276     bool backendRequiresLocalVarLifetimes()
4277     {
4278         return !opts.MinOpts() || m_pLinearScan->willEnregisterLocalVars();
4279     }
4280
4281     void fgLocalVarLiveness();
4282
4283     void fgLocalVarLivenessInit();
4284
4285     void fgPerNodeLocalVarLiveness(GenTree* node);
4286     void fgPerBlockLocalVarLiveness();
4287
4288     VARSET_VALRET_TP fgGetHandlerLiveVars(BasicBlock* block);
4289
4290     void fgLiveVarAnalysis(bool updateInternalOnly = false);
4291
4292     void fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call);
4293
4294     void fgComputeLifeTrackedLocalUse(VARSET_TP& life, LclVarDsc& varDsc, GenTreeLclVarCommon* node);
4295     bool fgComputeLifeTrackedLocalDef(VARSET_TP&           life,
4296                                       VARSET_VALARG_TP     keepAliveVars,
4297                                       LclVarDsc&           varDsc,
4298                                       GenTreeLclVarCommon* node);
4299     void fgComputeLifeUntrackedLocal(VARSET_TP&           life,
4300                                      VARSET_VALARG_TP     keepAliveVars,
4301                                      LclVarDsc&           varDsc,
4302                                      GenTreeLclVarCommon* lclVarNode);
4303     bool fgComputeLifeLocal(VARSET_TP& life, VARSET_VALARG_TP keepAliveVars, GenTree* lclVarNode);
4304
4305     void fgComputeLife(VARSET_TP&       life,
4306                        GenTree*         startNode,
4307                        GenTree*         endNode,
4308                        VARSET_VALARG_TP volatileVars,
4309                        bool* pStmtInfoDirty DEBUGARG(bool* treeModf));
4310
4311     void fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALARG_TP volatileVars);
4312
4313     bool fgRemoveDeadStore(GenTree**        pTree,
4314                            LclVarDsc*       varDsc,
4315                            VARSET_VALARG_TP life,
4316                            bool*            doAgain,
4317                            bool* pStmtInfoDirty DEBUGARG(bool* treeModf));
4318
4319     // For updating liveset during traversal AFTER fgComputeLife has completed
4320     VARSET_VALRET_TP fgGetVarBits(GenTree* tree);
4321     VARSET_VALRET_TP fgUpdateLiveSet(VARSET_VALARG_TP liveSet, GenTree* tree);
4322
4323     // Returns the set of live variables after endTree,
4324     // assuming that liveSet is the set of live variables BEFORE tree.
4325     // Requires that fgComputeLife has completed, and that tree is in the same
4326     // statement as endTree, and that it comes before endTree in execution order
4327
4328     VARSET_VALRET_TP fgUpdateLiveSet(VARSET_VALARG_TP liveSet, GenTree* tree, GenTree* endTree)
4329     {
4330         VARSET_TP newLiveSet(VarSetOps::MakeCopy(this, liveSet));
4331         while (tree != nullptr && tree != endTree->gtNext)
4332         {
4333             VarSetOps::AssignNoCopy(this, newLiveSet, fgUpdateLiveSet(newLiveSet, tree));
4334             tree = tree->gtNext;
4335         }
4336         assert(tree == endTree->gtNext);
4337         return newLiveSet;
4338     }
4339
4340     void fgInterBlockLocalVarLiveness();
4341
4342     // The presence of a partial definition presents some difficulties for SSA: this is both a use of some SSA name
4343     // of "x", and a def of a new SSA name for "x".  The tree only has one local variable for "x", so it has to choose
4344     // whether to treat that as the use or def.  It chooses the "use", and thus the old SSA name.  This map allows us
4345     // to record/recover the "def" SSA number, given the lcl var node for "x" in such a tree.
4346     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, unsigned> NodeToUnsignedMap;
4347     NodeToUnsignedMap* m_opAsgnVarDefSsaNums;
4348     NodeToUnsignedMap* GetOpAsgnVarDefSsaNums()
4349     {
4350         if (m_opAsgnVarDefSsaNums == nullptr)
4351         {
4352             m_opAsgnVarDefSsaNums = new (getAllocator()) NodeToUnsignedMap(getAllocator());
4353         }
4354         return m_opAsgnVarDefSsaNums;
4355     }
4356
4357     // Requires value numbering phase to have completed. Returns the value number ("gtVN") of the
4358     // "tree," EXCEPT in the case of GTF_VAR_USEASG, because the tree node's gtVN member is the
4359     // "use" VN. Performs a lookup into the map of (use asg tree -> def VN.) to return the "def's"
4360     // VN.
4361     inline ValueNum GetUseAsgDefVNOrTreeVN(GenTree* tree);
4362
4363     // Requires that "lcl" has the GTF_VAR_DEF flag set.  Returns the SSA number of "lcl".
4364     // Except: assumes that lcl is a def, and if it is
4365     // a partial def (GTF_VAR_USEASG), looks up and returns the SSA number for the "def",
4366     // rather than the "use" SSA number recorded in the tree "lcl".
4367     inline unsigned GetSsaNumForLocalVarDef(GenTree* lcl);
4368
4369     // Performs SSA conversion.
4370     void fgSsaBuild();
4371
4372     // Reset any data structures to the state expected by "fgSsaBuild", so it can be run again.
4373     void fgResetForSsa();
4374
4375     unsigned fgSsaPassesCompleted; // Number of times fgSsaBuild has been run.
4376
4377     // Returns "true" if a struct temp of the given type requires needs zero init in this block
4378     inline bool fgStructTempNeedsExplicitZeroInit(LclVarDsc* varDsc, BasicBlock* block);
4379
4380     // The value numbers for this compilation.
4381     ValueNumStore* vnStore;
4382
4383 public:
4384     ValueNumStore* GetValueNumStore()
4385     {
4386         return vnStore;
4387     }
4388
4389     // Do value numbering (assign a value number to each
4390     // tree node).
4391     void fgValueNumber();
4392
4393     // Computes new GcHeap VN via the assignment H[elemTypeEq][arrVN][inx][fldSeq] = rhsVN.
4394     // Assumes that "elemTypeEq" is the (equivalence class rep) of the array element type.
4395     // The 'indType' is the indirection type of the lhs of the assignment and will typically
4396     // match the element type of the array or fldSeq.  When this type doesn't match
4397     // or if the fldSeq is 'NotAField' we invalidate the array contents H[elemTypeEq][arrVN]
4398     //
4399     ValueNum fgValueNumberArrIndexAssign(CORINFO_CLASS_HANDLE elemTypeEq,
4400                                          ValueNum             arrVN,
4401                                          ValueNum             inxVN,
4402                                          FieldSeqNode*        fldSeq,
4403                                          ValueNum             rhsVN,
4404                                          var_types            indType);
4405
4406     // Requires that "tree" is a GT_IND marked as an array index, and that its address argument
4407     // has been parsed to yield the other input arguments.  If evaluation of the address
4408     // can raise exceptions, those should be captured in the exception set "excVN."
4409     // Assumes that "elemTypeEq" is the (equivalence class rep) of the array element type.
4410     // Marks "tree" with the VN for H[elemTypeEq][arrVN][inx][fldSeq] (for the liberal VN; a new unique
4411     // VN for the conservative VN.)  Also marks the tree's argument as the address of an array element.
4412     // The type tree->TypeGet() will typically match the element type of the array or fldSeq.
4413     // When this type doesn't match or if the fldSeq is 'NotAField' we return a new unique VN
4414     //
4415     ValueNum fgValueNumberArrIndexVal(GenTree*             tree,
4416                                       CORINFO_CLASS_HANDLE elemTypeEq,
4417                                       ValueNum             arrVN,
4418                                       ValueNum             inxVN,
4419                                       ValueNum             excVN,
4420                                       FieldSeqNode*        fldSeq);
4421
4422     // Requires "funcApp" to be a VNF_PtrToArrElem, and "addrXvn" to represent the exception set thrown
4423     // by evaluating the array index expression "tree".  Returns the value number resulting from
4424     // dereferencing the array in the current GcHeap state.  If "tree" is non-null, it must be the
4425     // "GT_IND" that does the dereference, and it is given the returned value number.
4426     ValueNum fgValueNumberArrIndexVal(GenTree* tree, struct VNFuncApp* funcApp, ValueNum addrXvn);
4427
4428     // Compute the value number for a byref-exposed load of the given type via the given pointerVN.
4429     ValueNum fgValueNumberByrefExposedLoad(var_types type, ValueNum pointerVN);
4430
4431     unsigned fgVNPassesCompleted; // Number of times fgValueNumber has been run.
4432
4433     // Utility functions for fgValueNumber.
4434
4435     // Perform value-numbering for the trees in "blk".
4436     void fgValueNumberBlock(BasicBlock* blk);
4437
4438     // Requires that "entryBlock" is the entry block of loop "loopNum", and that "loopNum" is the
4439     // innermost loop of which "entryBlock" is the entry.  Returns the value number that should be
4440     // assumed for the memoryKind at the start "entryBlk".
4441     ValueNum fgMemoryVNForLoopSideEffects(MemoryKind memoryKind, BasicBlock* entryBlock, unsigned loopNum);
4442
4443     // Called when an operation (performed by "tree", described by "msg") may cause the GcHeap to be mutated.
4444     // As GcHeap is a subset of ByrefExposed, this will also annotate the ByrefExposed mutation.
4445     void fgMutateGcHeap(GenTree* tree DEBUGARG(const char* msg));
4446
4447     // Called when an operation (performed by "tree", described by "msg") may cause an address-exposed local to be
4448     // mutated.
4449     void fgMutateAddressExposedLocal(GenTree* tree DEBUGARG(const char* msg));
4450
4451     // For a GC heap store at curTree, record the new curMemoryVN's and update curTree's MemorySsaMap.
4452     // As GcHeap is a subset of ByrefExposed, this will also record the ByrefExposed store.
4453     void recordGcHeapStore(GenTree* curTree, ValueNum gcHeapVN DEBUGARG(const char* msg));
4454
4455     // For a store to an address-exposed local at curTree, record the new curMemoryVN and update curTree's MemorySsaMap.
4456     void recordAddressExposedLocalStore(GenTree* curTree, ValueNum memoryVN DEBUGARG(const char* msg));
4457
4458     // Tree caused an update in the current memory VN.  If "tree" has an associated heap SSA #, record that
4459     // value in that SSA #.
4460     void fgValueNumberRecordMemorySsa(MemoryKind memoryKind, GenTree* tree);
4461
4462     // The input 'tree' is a leaf node that is a constant
4463     // Assign the proper value number to the tree
4464     void fgValueNumberTreeConst(GenTree* tree);
4465
4466     // Assumes that all inputs to "tree" have had value numbers assigned; assigns a VN to tree.
4467     // (With some exceptions: the VN of the lhs of an assignment is assigned as part of the
4468     // assignment.)
4469     void fgValueNumberTree(GenTree* tree);
4470
4471     // Does value-numbering for a block assignment.
4472     void fgValueNumberBlockAssignment(GenTree* tree);
4473
4474     // Does value-numbering for a cast tree.
4475     void fgValueNumberCastTree(GenTree* tree);
4476
4477     // Does value-numbering for an intrinsic tree.
4478     void fgValueNumberIntrinsic(GenTree* tree);
4479
4480     // Does value-numbering for a call.  We interpret some helper calls.
4481     void fgValueNumberCall(GenTreeCall* call);
4482
4483     // The VN of some nodes in "args" may have changed -- reassign VNs to the arg list nodes.
4484     void fgUpdateArgListVNs(GenTreeArgList* args);
4485
4486     // Does value-numbering for a helper "call" that has a VN function symbol "vnf".
4487     void fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueNumPair vnpExc);
4488
4489     // Requires "helpCall" to be a helper call.  Assigns it a value number;
4490     // we understand the semantics of some of the calls.  Returns "true" if
4491     // the call may modify the heap (we assume arbitrary memory side effects if so).
4492     bool fgValueNumberHelperCall(GenTreeCall* helpCall);
4493
4494     // Requires that "helpFunc" is one of the pure Jit Helper methods.
4495     // Returns the corresponding VNFunc to use for value numbering
4496     VNFunc fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc);
4497
4498     // Adds the exception set for the current tree node which has a memory indirection operation
4499     void fgValueNumberAddExceptionSetForIndirection(GenTree* tree, GenTree* baseAddr);
4500
4501     // Adds the exception sets for the current tree node which is performing a division or modulus operation
4502     void fgValueNumberAddExceptionSetForDivision(GenTree* tree);
4503
4504     // Adds the exception set for the current tree node which is performing a overflow checking operation
4505     void fgValueNumberAddExceptionSetForOverflow(GenTree* tree);
4506
4507     // Adds the exception set for the current tree node which is performing a ckfinite operation
4508     void fgValueNumberAddExceptionSetForCkFinite(GenTree* tree);
4509
4510     // Adds the exception sets for the current tree node
4511     void fgValueNumberAddExceptionSet(GenTree* tree);
4512
4513     // These are the current value number for the memory implicit variables while
4514     // doing value numbering.  These are the value numbers under the "liberal" interpretation
4515     // of memory values; the "conservative" interpretation needs no VN, since every access of
4516     // memory yields an unknown value.
4517     ValueNum fgCurMemoryVN[MemoryKindCount];
4518
4519     // Return a "pseudo"-class handle for an array element type.  If "elemType" is TYP_STRUCT,
4520     // requires "elemStructType" to be non-null (and to have a low-order zero).  Otherwise, low order bit
4521     // is 1, and the rest is an encoding of "elemTyp".
4522     static CORINFO_CLASS_HANDLE EncodeElemType(var_types elemTyp, CORINFO_CLASS_HANDLE elemStructType)
4523     {
4524         if (elemStructType != nullptr)
4525         {
4526             assert(varTypeIsStruct(elemTyp) || elemTyp == TYP_REF || elemTyp == TYP_BYREF ||
4527                    varTypeIsIntegral(elemTyp));
4528             assert((size_t(elemStructType) & 0x1) == 0x0); // Make sure the encoding below is valid.
4529             return elemStructType;
4530         }
4531         else
4532         {
4533             assert(elemTyp != TYP_STRUCT);
4534             elemTyp = varTypeUnsignedToSigned(elemTyp);
4535             return CORINFO_CLASS_HANDLE(size_t(elemTyp) << 1 | 0x1);
4536         }
4537     }
4538     // If "clsHnd" is the result of an "EncodePrim" call, returns true and sets "*pPrimType" to the
4539     // var_types it represents.  Otherwise, returns TYP_STRUCT (on the assumption that "clsHnd" is
4540     // the struct type of the element).
4541     static var_types DecodeElemType(CORINFO_CLASS_HANDLE clsHnd)
4542     {
4543         size_t clsHndVal = size_t(clsHnd);
4544         if (clsHndVal & 0x1)
4545         {
4546             return var_types(clsHndVal >> 1);
4547         }
4548         else
4549         {
4550             return TYP_STRUCT;
4551         }
4552     }
4553
4554     // Convert a BYTE which represents the VM's CorInfoGCtype to the JIT's var_types
4555     var_types getJitGCType(BYTE gcType);
4556
4557     enum structPassingKind
4558     {
4559         SPK_Unknown,       // Invalid value, never returned
4560         SPK_PrimitiveType, // The struct is passed/returned using a primitive type.
4561         SPK_EnclosingType, // Like SPK_Primitive type, but used for return types that
4562                            //  require a primitive type temp that is larger than the struct size.
4563                            //  Currently used for structs of size 3, 5, 6, or 7 bytes.
4564         SPK_ByValue,       // The struct is passed/returned by value (using the ABI rules)
4565                            //  for ARM64 and UNIX_X64 in multiple registers. (when all of the
4566                            //   parameters registers are used, then the stack will be used)
4567                            //  for X86 passed on the stack, for ARM32 passed in registers
4568                            //   or the stack or split between registers and the stack.
4569         SPK_ByValueAsHfa,  // The struct is passed/returned as an HFA in multiple registers.
4570         SPK_ByReference
4571     }; // The struct is passed/returned by reference to a copy/buffer.
4572
4573     // Get the "primitive" type that is is used when we are given a struct of size 'structSize'.
4574     // For pointer sized structs the 'clsHnd' is used to determine if the struct contains GC ref.
4575     // A "primitive" type is one of the scalar types: byte, short, int, long, ref, float, double
4576     // If we can't or shouldn't use a "primitive" type then TYP_UNKNOWN is returned.
4577     //
4578     // isVarArg is passed for use on Windows Arm64 to change the decision returned regarding
4579     // hfa types.
4580     //
4581     var_types getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS_HANDLE clsHnd, bool isVarArg);
4582
4583     // Get the type that is used to pass values of the given struct type.
4584     // isVarArg is passed for use on Windows Arm64 to change the decision returned regarding
4585     // hfa types.
4586     //
4587     var_types getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
4588                                   structPassingKind*   wbPassStruct,
4589                                   bool                 isVarArg,
4590                                   unsigned             structSize);
4591
4592     // Get the type that is used to return values of the given struct type.
4593     // If the size is unknown, pass 0 and it will be determined from 'clsHnd'.
4594     var_types getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
4595                                      structPassingKind*   wbPassStruct = nullptr,
4596                                      unsigned             structSize   = 0);
4597
4598 #ifdef DEBUG
4599     // Print a representation of "vnp" or "vn" on standard output.
4600     // If "level" is non-zero, we also print out a partial expansion of the value.
4601     void vnpPrint(ValueNumPair vnp, unsigned level);
4602     void vnPrint(ValueNum vn, unsigned level);
4603 #endif
4604
4605     bool fgDominate(BasicBlock* b1, BasicBlock* b2); // Return true if b1 dominates b2
4606
4607     // Dominator computation member functions
4608     // Not exposed outside Compiler
4609 protected:
4610     bool fgReachable(BasicBlock* b1, BasicBlock* b2); // Returns true if block b1 can reach block b2
4611
4612     void fgComputeDoms(); // Computes the immediate dominators for each basic block in the
4613                           // flow graph.  We first assume the fields bbIDom on each
4614                           // basic block are invalid. This computation is needed later
4615                           // by fgBuildDomTree to build the dominance tree structure.
4616                           // Based on: A Simple, Fast Dominance Algorithm
4617                           // by Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
4618
4619     void fgCompDominatedByExceptionalEntryBlocks();
4620
4621     BlockSet_ValRet_T fgGetDominatorSet(BasicBlock* block); // Returns a set of blocks that dominate the given block.
4622     // Note: this is relatively slow compared to calling fgDominate(),
4623     // especially if dealing with a single block versus block check.
4624
4625     void fgComputeReachabilitySets(); // Compute bbReach sets. (Also sets BBF_GC_SAFE_POINT flag on blocks.)
4626
4627     void fgComputeEnterBlocksSet(); // Compute the set of entry blocks, 'fgEnterBlks'.
4628
4629     bool fgRemoveUnreachableBlocks(); // Remove blocks determined to be unreachable by the bbReach sets.
4630
4631     void fgComputeReachability(); // Perform flow graph node reachability analysis.
4632
4633     BasicBlock* fgIntersectDom(BasicBlock* a, BasicBlock* b); // Intersect two immediate dominator sets.
4634
4635     void fgDfsInvPostOrder(); // In order to compute dominance using fgIntersectDom, the flow graph nodes must be
4636                               // processed in topological sort, this function takes care of that.
4637
4638     void fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, unsigned* count);
4639
4640     BlockSet_ValRet_T fgDomFindStartNodes(); // Computes which basic blocks don't have incoming edges in the flow graph.
4641                                              // Returns this as a set.
4642
4643     BlockSet_ValRet_T fgDomTreeEntryNodes(BasicBlockList** domTree); // Computes which nodes in the dominance forest are
4644                                                                      // root nodes. Returns this as a set.
4645
4646 #ifdef DEBUG
4647     void fgDispDomTree(BasicBlockList** domTree); // Helper that prints out the Dominator Tree in debug builds.
4648 #endif                                            // DEBUG
4649
4650     void fgBuildDomTree(); // Once we compute all the immediate dominator sets for each node in the flow graph
4651                            // (performed by fgComputeDoms), this procedure builds the dominance tree represented
4652                            // adjacency lists.
4653
4654     // In order to speed up the queries of the form 'Does A dominates B', we can perform a DFS preorder and postorder
4655     // traversal of the dominance tree and the dominance query will become A dominates B iif preOrder(A) <= preOrder(B)
4656     // && postOrder(A) >= postOrder(B) making the computation O(1).
4657     void fgTraverseDomTree(unsigned bbNum, BasicBlockList** domTree, unsigned* preNum, unsigned* postNum);
4658
4659     // When the flow graph changes, we need to update the block numbers, predecessor lists, reachability sets, and
4660     // dominators.
4661     void fgUpdateChangedFlowGraph();
4662
4663 public:
4664     // Compute the predecessors of the blocks in the control flow graph.
4665     void fgComputePreds();
4666
4667     // Remove all predecessor information.
4668     void fgRemovePreds();
4669
4670     // Compute the cheap flow graph predecessors lists. This is used in some early phases
4671     // before the full predecessors lists are computed.
4672     void fgComputeCheapPreds();
4673
4674 private:
4675     void fgAddCheapPred(BasicBlock* block, BasicBlock* blockPred);
4676
4677     void fgRemoveCheapPred(BasicBlock* block, BasicBlock* blockPred);
4678
4679 public:
4680     enum GCPollType
4681     {
4682         GCPOLL_NONE,
4683         GCPOLL_CALL,
4684         GCPOLL_INLINE
4685     };
4686
4687     // Initialize the per-block variable sets (used for liveness analysis).
4688     void fgInitBlockVarSets();
4689
4690     // true if we've gone through and created GC Poll calls.
4691     bool fgGCPollsCreated;
4692     void fgMarkGCPollBlocks();
4693     void fgCreateGCPolls();
4694     bool fgCreateGCPoll(GCPollType pollType, BasicBlock* block);
4695
4696     // Requires that "block" is a block that returns from
4697     // a finally.  Returns the number of successors (jump targets of
4698     // of blocks in the covered "try" that did a "LEAVE".)
4699     unsigned fgNSuccsOfFinallyRet(BasicBlock* block);
4700
4701     // Requires that "block" is a block that returns (in the sense of BBJ_EHFINALLYRET) from
4702     // a finally.  Returns its "i"th successor (jump targets of
4703     // of blocks in the covered "try" that did a "LEAVE".)
4704     // Requires that "i" < fgNSuccsOfFinallyRet(block).
4705     BasicBlock* fgSuccOfFinallyRet(BasicBlock* block, unsigned i);
4706
4707 private:
4708     // Factor out common portions of the impls of the methods above.
4709     void fgSuccOfFinallyRetWork(BasicBlock* block, unsigned i, BasicBlock** bres, unsigned* nres);
4710
4711 public:
4712     // For many purposes, it is desirable to be able to enumerate the *distinct* targets of a switch statement,
4713     // skipping duplicate targets.  (E.g., in flow analyses that are only interested in the set of possible targets.)
4714     // SwitchUniqueSuccSet contains the non-duplicated switch targets.
4715     // (Code that modifies the jump table of a switch has an obligation to call Compiler::UpdateSwitchTableTarget,
4716     // which in turn will call the "UpdateTarget" method of this type if a SwitchUniqueSuccSet has already
4717     // been computed for the switch block.  If a switch block is deleted or is transformed into a non-switch,
4718     // we leave the entry associated with the block, but it will no longer be accessed.)
4719     struct SwitchUniqueSuccSet
4720     {
4721         unsigned     numDistinctSuccs; // Number of distinct targets of the switch.
4722         BasicBlock** nonDuplicates;    // Array of "numDistinctSuccs", containing all the distinct switch target
4723                                        // successors.
4724
4725         // The switch block "switchBlk" just had an entry with value "from" modified to the value "to".
4726         // Update "this" as necessary: if "from" is no longer an element of the jump table of "switchBlk",
4727         // remove it from "this", and ensure that "to" is a member.  Use "alloc" to do any required allocation.
4728         void UpdateTarget(CompAllocator alloc, BasicBlock* switchBlk, BasicBlock* from, BasicBlock* to);
4729     };
4730
4731     typedef JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, SwitchUniqueSuccSet> BlockToSwitchDescMap;
4732
4733 private:
4734     // Maps BasicBlock*'s that end in switch statements to SwitchUniqueSuccSets that allow
4735     // iteration over only the distinct successors.
4736     BlockToSwitchDescMap* m_switchDescMap;
4737
4738 public:
4739     BlockToSwitchDescMap* GetSwitchDescMap(bool createIfNull = true)
4740     {
4741         if ((m_switchDescMap == nullptr) && createIfNull)
4742         {
4743             m_switchDescMap = new (getAllocator()) BlockToSwitchDescMap(getAllocator());
4744         }
4745         return m_switchDescMap;
4746     }
4747
4748     // Invalidate the map of unique switch block successors. For example, since the hash key of the map
4749     // depends on block numbers, we must invalidate the map when the blocks are renumbered, to ensure that
4750     // we don't accidentally look up and return the wrong switch data.
4751     void InvalidateUniqueSwitchSuccMap()
4752     {
4753         m_switchDescMap = nullptr;
4754     }
4755
4756     // Requires "switchBlock" to be a block that ends in a switch.  Returns
4757     // the corresponding SwitchUniqueSuccSet.
4758     SwitchUniqueSuccSet GetDescriptorForSwitch(BasicBlock* switchBlk);
4759
4760     // The switch block "switchBlk" just had an entry with value "from" modified to the value "to".
4761     // Update "this" as necessary: if "from" is no longer an element of the jump table of "switchBlk",
4762     // remove it from "this", and ensure that "to" is a member.
4763     void UpdateSwitchTableTarget(BasicBlock* switchBlk, BasicBlock* from, BasicBlock* to);
4764
4765     // Remove the "SwitchUniqueSuccSet" of "switchBlk" in the BlockToSwitchDescMap.
4766     void fgInvalidateSwitchDescMapEntry(BasicBlock* switchBlk);
4767
4768     BasicBlock* fgFirstBlockOfHandler(BasicBlock* block);
4769
4770     flowList* fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred);
4771
4772     flowList* fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, flowList*** ptrToPred);
4773
4774     flowList* fgSpliceOutPred(BasicBlock* block, BasicBlock* blockPred);
4775
4776     flowList* fgRemoveRefPred(BasicBlock* block, BasicBlock* blockPred);
4777
4778     flowList* fgRemoveAllRefPreds(BasicBlock* block, BasicBlock* blockPred);
4779
4780     flowList* fgRemoveAllRefPreds(BasicBlock* block, flowList** ptrToPred);
4781
4782     void fgRemoveBlockAsPred(BasicBlock* block);
4783
4784     void fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSwitchBlock);
4785
4786     void fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* newTarget, BasicBlock* oldTarget);
4787
4788     void fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget);
4789
4790     void fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* newPred);
4791
4792     flowList* fgAddRefPred(BasicBlock* block,
4793                            BasicBlock* blockPred,
4794                            flowList*   oldEdge           = nullptr,
4795                            bool        initializingPreds = false); // Only set to 'true' when we are computing preds in
4796                                                                    // fgComputePreds()
4797
4798     void fgFindBasicBlocks();
4799
4800     bool fgIsBetterFallThrough(BasicBlock* bCur, BasicBlock* bAlt);
4801
4802     bool fgCheckEHCanInsertAfterBlock(BasicBlock* blk, unsigned regionIndex, bool putInTryRegion);
4803
4804     BasicBlock* fgFindInsertPoint(unsigned    regionIndex,
4805                                   bool        putInTryRegion,
4806                                   BasicBlock* startBlk,
4807                                   BasicBlock* endBlk,
4808                                   BasicBlock* nearBlk,
4809                                   BasicBlock* jumpBlk,
4810                                   bool        runRarely);
4811
4812     unsigned fgGetNestingLevel(BasicBlock* block, unsigned* pFinallyNesting = nullptr);
4813
4814     void fgRemoveEmptyBlocks();
4815
4816     void fgRemoveStmt(BasicBlock* block, GenTree* stmt);
4817
4818     bool fgCheckRemoveStmt(BasicBlock* block, GenTree* stmt);
4819
4820     void fgCreateLoopPreHeader(unsigned lnum);
4821
4822     void fgUnreachableBlock(BasicBlock* block);
4823
4824     void fgRemoveConditionalJump(BasicBlock* block);
4825
4826     BasicBlock* fgLastBBInMainFunction();
4827
4828     BasicBlock* fgEndBBAfterMainFunction();
4829
4830     void fgUnlinkRange(BasicBlock* bBeg, BasicBlock* bEnd);
4831
4832     void fgRemoveBlock(BasicBlock* block, bool unreachable);
4833
4834     bool fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext);
4835
4836     void fgCompactBlocks(BasicBlock* block, BasicBlock* bNext);
4837
4838     void fgUpdateLoopsAfterCompacting(BasicBlock* block, BasicBlock* bNext);
4839
4840     BasicBlock* fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst);
4841
4842     bool fgRenumberBlocks();
4843
4844     bool fgExpandRarelyRunBlocks();
4845
4846     bool fgEhAllowsMoveBlock(BasicBlock* bBefore, BasicBlock* bAfter);
4847
4848     void fgMoveBlocksAfter(BasicBlock* bStart, BasicBlock* bEnd, BasicBlock* insertAfterBlk);
4849
4850     enum FG_RELOCATE_TYPE
4851     {
4852         FG_RELOCATE_TRY,    // relocate the 'try' region
4853         FG_RELOCATE_HANDLER // relocate the handler region (including the filter if necessary)
4854     };
4855     BasicBlock* fgRelocateEHRange(unsigned regionIndex, FG_RELOCATE_TYPE relocateType);
4856
4857 #if FEATURE_EH_FUNCLETS
4858 #if defined(_TARGET_ARM_)
4859     void fgClearFinallyTargetBit(BasicBlock* block);
4860 #endif // defined(_TARGET_ARM_)
4861     bool fgIsIntraHandlerPred(BasicBlock* predBlock, BasicBlock* block);
4862     bool fgAnyIntraHandlerPreds(BasicBlock* block);
4863     void fgInsertFuncletPrologBlock(BasicBlock* block);
4864     void fgCreateFuncletPrologBlocks();
4865     void fgCreateFunclets();
4866 #else  // !FEATURE_EH_FUNCLETS
4867     bool fgRelocateEHRegions();
4868 #endif // !FEATURE_EH_FUNCLETS
4869
4870     bool fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* target);
4871
4872     bool fgBlockEndFavorsTailDuplication(BasicBlock* block);
4873
4874     bool fgBlockIsGoodTailDuplicationCandidate(BasicBlock* block);
4875
4876     bool fgOptimizeEmptyBlock(BasicBlock* block);
4877
4878     bool fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBlock* bDest);
4879
4880     bool fgOptimizeBranch(BasicBlock* bJump);
4881
4882     bool fgOptimizeSwitchBranches(BasicBlock* block);
4883
4884     bool fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev);
4885
4886     bool fgOptimizeSwitchJumps();
4887 #ifdef DEBUG
4888     void fgPrintEdgeWeights();
4889 #endif
4890     void                 fgComputeBlockAndEdgeWeights();
4891     BasicBlock::weight_t fgComputeMissingBlockWeights();
4892     void fgComputeCalledCount(BasicBlock::weight_t returnWeight);
4893     void fgComputeEdgeWeights();
4894
4895     void fgReorderBlocks();
4896
4897     void fgDetermineFirstColdBlock();
4898
4899     bool fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc = nullptr);
4900
4901     bool fgUpdateFlowGraph(bool doTailDup = false);
4902
4903     void fgFindOperOrder();
4904
4905     // method that returns if you should split here
4906     typedef bool(fgSplitPredicate)(GenTree* tree, GenTree* parent, fgWalkData* data);
4907
4908     void fgSetBlockOrder();
4909
4910     void fgRemoveReturnBlock(BasicBlock* block);
4911
4912     /* Helper code that has been factored out */
4913     inline void fgConvertBBToThrowBB(BasicBlock* block);
4914
4915     bool fgCastNeeded(GenTree* tree, var_types toType);
4916     GenTree* fgDoNormalizeOnStore(GenTree* tree);
4917     GenTree* fgMakeTmpArgNode(fgArgTabEntry* curArgTabEntry);
4918
4919     // The following check for loops that don't execute calls
4920     bool fgLoopCallMarked;
4921
4922     void fgLoopCallTest(BasicBlock* srcBB, BasicBlock* dstBB);
4923     void fgLoopCallMark();
4924
4925     void fgMarkLoopHead(BasicBlock* block);
4926
4927     unsigned fgGetCodeEstimate(BasicBlock* block);
4928
4929 #if DUMP_FLOWGRAPHS
4930     const char* fgProcessEscapes(const char* nameIn, escapeMapping_t* map);
4931     FILE* fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR type);
4932     bool fgDumpFlowGraph(Phases phase);
4933
4934 #endif // DUMP_FLOWGRAPHS
4935
4936 #ifdef DEBUG
4937     void fgDispDoms();
4938     void fgDispReach();
4939     void fgDispBBLiveness(BasicBlock* block);
4940     void fgDispBBLiveness();
4941     void fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth = 0);
4942     void fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, bool dumpTrees);
4943     void fgDispBasicBlocks(bool dumpTrees = false);
4944     void fgDumpStmtTree(GenTree* stmt, unsigned bbNum);
4945     void fgDumpBlock(BasicBlock* block);
4946     void fgDumpTrees(BasicBlock* firstBlock, BasicBlock* lastBlock);
4947
4948     static fgWalkPreFn fgStress64RsltMulCB;
4949     void               fgStress64RsltMul();
4950     void               fgDebugCheckUpdate();
4951     void fgDebugCheckBBlist(bool checkBBNum = false, bool checkBBRefs = true);
4952     void fgDebugCheckBlockLinks();
4953     void fgDebugCheckLinks(bool morphTrees = false);
4954     void fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees);
4955     void fgDebugCheckNodeLinks(BasicBlock* block, GenTree* stmt);
4956     void fgDebugCheckNodesUniqueness();
4957
4958     void fgDebugCheckFlags(GenTree* tree);
4959     void fgDebugCheckFlagsHelper(GenTree* tree, unsigned treeFlags, unsigned chkFlags);
4960     void fgDebugCheckTryFinallyExits();
4961 #endif
4962
4963     static GenTree* fgGetFirstNode(GenTree* tree);
4964
4965     //--------------------- Walking the trees in the IR -----------------------
4966
4967     struct fgWalkData
4968     {
4969         Compiler*     compiler;
4970         fgWalkPreFn*  wtprVisitorFn;
4971         fgWalkPostFn* wtpoVisitorFn;
4972         void*         pCallbackData; // user-provided data
4973         bool          wtprLclsOnly;  // whether to only visit lclvar nodes
4974         GenTree*      parent;        // parent of current node, provided to callback
4975         GenTreeStack* parentStack;   // stack of parent nodes, if asked for
4976 #ifdef DEBUG
4977         bool printModified; // callback can use this
4978 #endif
4979     };
4980
4981     fgWalkResult fgWalkTreePre(GenTree**    pTree,
4982                                fgWalkPreFn* visitor,
4983                                void*        pCallBackData = nullptr,
4984                                bool         lclVarsOnly   = false,
4985                                bool         computeStack  = false);
4986
4987     fgWalkResult fgWalkTree(GenTree**     pTree,
4988                             fgWalkPreFn*  preVisitor,
4989                             fgWalkPostFn* postVisitor,
4990                             void*         pCallBackData = nullptr);
4991
4992     void fgWalkAllTreesPre(fgWalkPreFn* visitor, void* pCallBackData);
4993
4994     //----- Postorder
4995
4996     fgWalkResult fgWalkTreePost(GenTree**     pTree,
4997                                 fgWalkPostFn* visitor,
4998                                 void*         pCallBackData = nullptr,
4999                                 bool          computeStack  = false);
5000
5001     // An fgWalkPreFn that looks for expressions that have inline throws in
5002     // minopts mode. Basically it looks for tress with gtOverflowEx() or
5003     // GTF_IND_RNGCHK.  It returns WALK_ABORT if one is found.  It
5004     // returns WALK_SKIP_SUBTREES if GTF_EXCEPT is not set (assumes flags
5005     // properly propagated to parent trees).  It returns WALK_CONTINUE
5006     // otherwise.
5007     static fgWalkResult fgChkThrowCB(GenTree** pTree, Compiler::fgWalkData* data);
5008     static fgWalkResult fgChkLocAllocCB(GenTree** pTree, Compiler::fgWalkData* data);
5009     static fgWalkResult fgChkQmarkCB(GenTree** pTree, Compiler::fgWalkData* data);
5010
5011     /**************************************************************************
5012      *                          PROTECTED
5013      *************************************************************************/
5014
5015 protected:
5016     friend class SsaBuilder;
5017     friend struct ValueNumberState;
5018
5019     //--------------------- Detect the basic blocks ---------------------------
5020
5021     BasicBlock** fgBBs; // Table of pointers to the BBs
5022
5023     void        fgInitBBLookup();
5024     BasicBlock* fgLookupBB(unsigned addr);
5025
5026     void fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget);
5027
5028     void fgMarkBackwardJump(BasicBlock* startBlock, BasicBlock* endBlock);
5029
5030     void fgLinkBasicBlocks();
5031
5032     unsigned fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget);
5033
5034     void fgCheckBasicBlockControlFlow();
5035
5036     void fgControlFlowPermitted(BasicBlock* blkSrc,
5037                                 BasicBlock* blkDest,
5038                                 BOOL        IsLeave = false /* is the src a leave block */);
5039
5040     bool fgFlowToFirstBlockOfInnerTry(BasicBlock* blkSrc, BasicBlock* blkDest, bool sibling);
5041
5042     void fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, bool isInlining);
5043
5044     void fgAdjustForAddressExposedOrWrittenThis();
5045
5046     bool                        fgProfileData_ILSizeMismatch;
5047     ICorJitInfo::ProfileBuffer* fgProfileBuffer;
5048     ULONG                       fgProfileBufferCount;
5049     ULONG                       fgNumProfileRuns;
5050
5051     unsigned fgStressBBProf()
5052     {
5053 #ifdef DEBUG
5054         unsigned result = JitConfig.JitStressBBProf();
5055         if (result == 0)
5056         {
5057             if (compStressCompile(STRESS_BB_PROFILE, 15))
5058             {
5059                 result = 1;
5060             }
5061         }
5062         return result;
5063 #else
5064         return 0;
5065 #endif
5066     }
5067
5068     bool fgHaveProfileData();
5069     bool fgGetProfileWeightForBasicBlock(IL_OFFSET offset, unsigned* weight);
5070     void fgInstrumentMethod();
5071
5072 public:
5073     // fgIsUsingProfileWeights - returns true if we have real profile data for this method
5074     //                           or if we have some fake profile data for the stress mode
5075     bool fgIsUsingProfileWeights()
5076     {
5077         return (fgHaveProfileData() || fgStressBBProf());
5078     }
5079
5080     // fgProfileRunsCount - returns total number of scenario runs for the profile data
5081     //                      or BB_UNITY_WEIGHT when we aren't using profile data.
5082     unsigned fgProfileRunsCount()
5083     {
5084         return fgIsUsingProfileWeights() ? fgNumProfileRuns : BB_UNITY_WEIGHT;
5085     }
5086
5087 //-------- Insert a statement at the start or end of a basic block --------
5088
5089 #ifdef DEBUG
5090 public:
5091     static bool fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, bool answerOnBoundExceeded = true);
5092 #endif
5093
5094 public:
5095     GenTreeStmt* fgInsertStmtAtEnd(BasicBlock* block, GenTree* node);
5096
5097 public: // Used by linear scan register allocation
5098     GenTreeStmt* fgInsertStmtNearEnd(BasicBlock* block, GenTree* node);
5099
5100 private:
5101     GenTree* fgInsertStmtAtBeg(BasicBlock* block, GenTree* stmt);
5102     GenTree* fgInsertStmtAfter(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt);
5103
5104 public: // Used by linear scan register allocation
5105     GenTree* fgInsertStmtBefore(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt);
5106
5107 private:
5108     GenTree* fgInsertStmtListAfter(BasicBlock* block, GenTree* stmtAfter, GenTree* stmtList);
5109
5110     //                  Create a new temporary variable to hold the result of *ppTree,
5111     //                  and transform the graph accordingly.
5112     GenTree* fgInsertCommaFormTemp(GenTree** ppTree, CORINFO_CLASS_HANDLE structType = nullptr);
5113     GenTree* fgMakeMultiUse(GenTree** ppTree);
5114
5115 private:
5116     //                  Recognize a bitwise rotation pattern and convert into a GT_ROL or a GT_ROR node.
5117     GenTree* fgRecognizeAndMorphBitwiseRotation(GenTree* tree);
5118     bool fgOperIsBitwiseRotationRoot(genTreeOps oper);
5119
5120     //-------- Determine the order in which the trees will be evaluated -------
5121
5122     unsigned fgTreeSeqNum;
5123     GenTree* fgTreeSeqLst;
5124     GenTree* fgTreeSeqBeg;
5125
5126     GenTree* fgSetTreeSeq(GenTree* tree, GenTree* prev = nullptr, bool isLIR = false);
5127     void fgSetTreeSeqHelper(GenTree* tree, bool isLIR);
5128     void fgSetTreeSeqFinish(GenTree* tree, bool isLIR);
5129     void fgSetStmtSeq(GenTree* tree);
5130     void fgSetBlockOrder(BasicBlock* block);
5131
5132     //------------------------- Morphing --------------------------------------
5133
5134     unsigned fgPtrArgCntMax;
5135
5136 public:
5137     //------------------------------------------------------------------------
5138     // fgGetPtrArgCntMax: Return the maximum number of pointer-sized stack arguments that calls inside this method
5139     // can push on the stack. This value is calculated during morph.
5140     //
5141     // Return Value:
5142     //    Returns fgPtrArgCntMax, that is a private field.
5143     //
5144     unsigned fgGetPtrArgCntMax() const
5145     {
5146         return fgPtrArgCntMax;
5147     }
5148
5149     //------------------------------------------------------------------------
5150     // fgSetPtrArgCntMax: Set the maximum number of pointer-sized stack arguments that calls inside this method
5151     // can push on the stack. This function is used during StackLevelSetter to fix incorrect morph calculations.
5152     //
5153     void fgSetPtrArgCntMax(unsigned argCntMax)
5154     {
5155         fgPtrArgCntMax = argCntMax;
5156     }
5157
5158     bool compCanEncodePtrArgCntMax();
5159
5160 private:
5161     hashBv* fgOutgoingArgTemps;
5162     hashBv* fgCurrentlyInUseArgTemps;
5163
5164     void fgSetRngChkTarget(GenTree* tree, bool delay = true);
5165
5166     BasicBlock* fgSetRngChkTargetInner(SpecialCodeKind kind, bool delay);
5167
5168 #if REARRANGE_ADDS
5169     void fgMoveOpsLeft(GenTree* tree);
5170 #endif
5171
5172     bool fgIsCommaThrow(GenTree* tree, bool forFolding = false);
5173
5174     bool fgIsThrow(GenTree* tree);
5175
5176     bool fgInDifferentRegions(BasicBlock* blk1, BasicBlock* blk2);
5177     bool fgIsBlockCold(BasicBlock* block);
5178
5179     GenTree* fgMorphCastIntoHelper(GenTree* tree, int helper, GenTree* oper);
5180
5181     GenTree* fgMorphIntoHelperCall(GenTree* tree, int helper, GenTreeArgList* args, bool morphArgs = true);
5182
5183     GenTree* fgMorphStackArgForVarArgs(unsigned lclNum, var_types varType, unsigned lclOffs);
5184
5185     // A "MorphAddrContext" carries information from the surrounding context.  If we are evaluating a byref address,
5186     // it is useful to know whether the address will be immediately dereferenced, or whether the address value will
5187     // be used, perhaps by passing it as an argument to a called method.  This affects how null checking is done:
5188     // for sufficiently small offsets, we can rely on OS page protection to implicitly null-check addresses that we
5189     // know will be dereferenced.  To know that reliance on implicit null checking is sound, we must further know that
5190     // all offsets between the top-level indirection and the bottom are constant, and that their sum is sufficiently
5191     // small; hence the other fields of MorphAddrContext.
5192     enum MorphAddrContextKind
5193     {
5194         MACK_Ind,
5195         MACK_Addr,
5196     };
5197     struct MorphAddrContext
5198     {
5199         MorphAddrContextKind m_kind;
5200         bool                 m_allConstantOffsets; // Valid only for "m_kind == MACK_Ind".  True iff all offsets between
5201                                                    // top-level indirection and here have been constants.
5202         size_t m_totalOffset; // Valid only for "m_kind == MACK_Ind", and if "m_allConstantOffsets" is true.
5203                               // In that case, is the sum of those constant offsets.
5204
5205         MorphAddrContext(MorphAddrContextKind kind) : m_kind(kind), m_allConstantOffsets(true), m_totalOffset(0)
5206         {
5207         }
5208     };
5209
5210     // A MACK_CopyBlock context is immutable, so we can just make one of these and share it.
5211     static MorphAddrContext s_CopyBlockMAC;
5212
5213 #ifdef FEATURE_SIMD
5214     GenTree* getSIMDStructFromField(GenTree*   tree,
5215                                     var_types* baseTypeOut,
5216                                     unsigned*  indexOut,
5217                                     unsigned*  simdSizeOut,
5218                                     bool       ignoreUsedInSIMDIntrinsic = false);
5219     GenTree* fgMorphFieldAssignToSIMDIntrinsicSet(GenTree* tree);
5220     GenTree* fgMorphFieldToSIMDIntrinsicGet(GenTree* tree);
5221     bool fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTree* stmt);
5222     void impMarkContiguousSIMDFieldAssignments(GenTree* stmt);
5223
5224     // fgPreviousCandidateSIMDFieldAsgStmt is only used for tracking previous simd field assignment
5225     // in function: Complier::impMarkContiguousSIMDFieldAssignments.
5226     GenTree* fgPreviousCandidateSIMDFieldAsgStmt;
5227
5228 #endif // FEATURE_SIMD
5229     GenTree* fgMorphArrayIndex(GenTree* tree);
5230     GenTree* fgMorphCast(GenTree* tree);
5231     GenTree* fgUnwrapProxy(GenTree* objRef);
5232     GenTreeFieldList* fgMorphLclArgToFieldlist(GenTreeLclVarCommon* lcl);
5233     void fgInitArgInfo(GenTreeCall* call);
5234     GenTreeCall* fgMorphArgs(GenTreeCall* call);
5235     GenTreeArgList* fgMorphArgList(GenTreeArgList* args, MorphAddrContext* mac);
5236
5237     void fgMakeOutgoingStructArgCopy(GenTreeCall*         call,
5238                                      GenTree*             args,
5239                                      unsigned             argIndex,
5240                                      CORINFO_CLASS_HANDLE copyBlkClass);
5241
5242     void fgFixupStructReturn(GenTree* call);
5243     GenTree* fgMorphLocalVar(GenTree* tree, bool forceRemorph);
5244
5245 public:
5246     bool fgAddrCouldBeNull(GenTree* addr);
5247
5248 private:
5249     GenTree* fgMorphField(GenTree* tree, MorphAddrContext* mac);
5250     bool fgCanFastTailCall(GenTreeCall* call);
5251     bool fgCheckStmtAfterTailCall();
5252     void fgMorphTailCall(GenTreeCall* call, void* pfnCopyArgs);
5253     GenTree* fgGetStubAddrArg(GenTreeCall* call);
5254     void fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCall* recursiveTailCall);
5255     GenTree* fgAssignRecursiveCallArgToCallerParam(GenTree*       arg,
5256                                                    fgArgTabEntry* argTabEntry,
5257                                                    BasicBlock*    block,
5258                                                    IL_OFFSETX     callILOffset,
5259                                                    GenTree*       tmpAssignmentInsertionPoint,
5260                                                    GenTree*       paramAssignmentInsertionPoint);
5261     static int fgEstimateCallStackSize(GenTreeCall* call);
5262     GenTree* fgMorphCall(GenTreeCall* call);
5263     void fgMorphCallInline(GenTreeCall* call, InlineResult* result);
5264     void fgMorphCallInlineHelper(GenTreeCall* call, InlineResult* result);
5265 #if DEBUG
5266     void fgNoteNonInlineCandidate(GenTreeStmt* stmt, GenTreeCall* call);
5267     static fgWalkPreFn fgFindNonInlineCandidate;
5268 #endif
5269     GenTree* fgOptimizeDelegateConstructor(GenTreeCall*            call,
5270                                            CORINFO_CONTEXT_HANDLE* ExactContextHnd,
5271                                            CORINFO_RESOLVED_TOKEN* ldftnToken);
5272     GenTree* fgMorphLeaf(GenTree* tree);
5273     void fgAssignSetVarDef(GenTree* tree);
5274     GenTree* fgMorphOneAsgBlockOp(GenTree* tree);
5275     GenTree* fgMorphInitBlock(GenTree* tree);
5276     GenTree* fgMorphPromoteLocalInitBlock(GenTreeLclVar* destLclNode, GenTree* initVal, unsigned blockSize);
5277     GenTree* fgMorphBlkToInd(GenTreeBlk* tree, var_types type);
5278     GenTree* fgMorphGetStructAddr(GenTree** pTree, CORINFO_CLASS_HANDLE clsHnd, bool isRValue = false);
5279     GenTree* fgMorphBlkNode(GenTree* tree, bool isDest);
5280     GenTree* fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigned blockWidth, bool isDest);
5281     void fgMorphUnsafeBlk(GenTreeObj* obj);
5282     GenTree* fgMorphCopyBlock(GenTree* tree);
5283     GenTree* fgMorphForRegisterFP(GenTree* tree);
5284     GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac = nullptr);
5285     GenTree* fgMorphModToSubMulDiv(GenTreeOp* tree);
5286     GenTree* fgMorphSmpOpOptional(GenTreeOp* tree);
5287     GenTree* fgMorphRecognizeBoxNullable(GenTree* compare);
5288
5289     GenTree* fgMorphToEmulatedFP(GenTree* tree);
5290     GenTree* fgMorphConst(GenTree* tree);
5291
5292 public:
5293     GenTree* fgMorphTree(GenTree* tree, MorphAddrContext* mac = nullptr);
5294
5295 private:
5296 #if LOCAL_ASSERTION_PROP
5297     void fgKillDependentAssertionsSingle(unsigned lclNum DEBUGARG(GenTree* tree));
5298     void fgKillDependentAssertions(unsigned lclNum DEBUGARG(GenTree* tree));
5299 #endif
5300     void fgMorphTreeDone(GenTree* tree, GenTree* oldTree = nullptr DEBUGARG(int morphNum = 0));
5301
5302     GenTreeStmt* fgMorphStmt;
5303
5304     unsigned fgGetBigOffsetMorphingTemp(var_types type); // We cache one temp per type to be
5305                                                          // used when morphing big offset.
5306
5307     //----------------------- Liveness analysis -------------------------------
5308
5309     VARSET_TP fgCurUseSet; // vars used     by block (before an assignment)
5310     VARSET_TP fgCurDefSet; // vars assigned by block (before a use)
5311
5312     MemoryKindSet fgCurMemoryUse;   // True iff the current basic block uses memory.
5313     MemoryKindSet fgCurMemoryDef;   // True iff the current basic block modifies memory.
5314     MemoryKindSet fgCurMemoryHavoc; // True if  the current basic block is known to set memory to a "havoc" value.
5315
5316     bool byrefStatesMatchGcHeapStates; // True iff GcHeap and ByrefExposed memory have all the same def points.
5317
5318     void fgMarkUseDef(GenTreeLclVarCommon* tree);
5319
5320     void fgBeginScopeLife(VARSET_TP* inScope, VarScopeDsc* var);
5321     void fgEndScopeLife(VARSET_TP* inScope, VarScopeDsc* var);
5322
5323     void fgMarkInScope(BasicBlock* block, VARSET_VALARG_TP inScope);
5324     void fgUnmarkInScope(BasicBlock* block, VARSET_VALARG_TP unmarkScope);
5325
5326     void fgExtendDbgScopes();
5327     void fgExtendDbgLifetimes();
5328
5329 #ifdef DEBUG
5330     void fgDispDebugScopes();
5331 #endif // DEBUG
5332
5333     //-------------------------------------------------------------------------
5334     //
5335     //  The following keeps track of any code we've added for things like array
5336     //  range checking or explicit calls to enable GC, and so on.
5337     //
5338 public:
5339     struct AddCodeDsc
5340     {
5341         AddCodeDsc*     acdNext;
5342         BasicBlock*     acdDstBlk; // block  to  which we jump
5343         unsigned        acdData;
5344         SpecialCodeKind acdKind; // what kind of a special block is this?
5345 #if !FEATURE_FIXED_OUT_ARGS
5346         bool     acdStkLvlInit; // has acdStkLvl value been already set?
5347         unsigned acdStkLvl;
5348 #endif // !FEATURE_FIXED_OUT_ARGS
5349     };
5350
5351 private:
5352     static unsigned acdHelper(SpecialCodeKind codeKind);
5353
5354     AddCodeDsc* fgAddCodeList;
5355     bool        fgAddCodeModf;
5356     bool        fgRngChkThrowAdded;
5357     AddCodeDsc* fgExcptnTargetCache[SCK_COUNT];
5358
5359     BasicBlock* fgRngChkTarget(BasicBlock* block, SpecialCodeKind kind);
5360
5361     BasicBlock* fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, SpecialCodeKind kind);
5362
5363 public:
5364     AddCodeDsc* fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData);
5365
5366     bool fgUseThrowHelperBlocks();
5367
5368     AddCodeDsc* fgGetAdditionalCodeDescriptors()
5369     {
5370         return fgAddCodeList;
5371     }
5372
5373 private:
5374     bool fgIsCodeAdded();
5375
5376     bool fgIsThrowHlpBlk(BasicBlock* block);
5377
5378 #if !FEATURE_FIXED_OUT_ARGS
5379     unsigned fgThrowHlpBlkStkLevel(BasicBlock* block);
5380 #endif // !FEATURE_FIXED_OUT_ARGS
5381
5382     unsigned fgBigOffsetMorphingTemps[TYP_COUNT];
5383
5384     unsigned fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo);
5385     void fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* result);
5386     void fgInsertInlineeBlocks(InlineInfo* pInlineInfo);
5387     GenTree* fgInlinePrependStatements(InlineInfo* inlineInfo);
5388     void fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTree* stmt);
5389
5390 #if FEATURE_MULTIREG_RET
5391     GenTree* fgGetStructAsStructPtr(GenTree* tree);
5392     GenTree* fgAssignStructInlineeToVar(GenTree* child, CORINFO_CLASS_HANDLE retClsHnd);
5393     void fgAttachStructInlineeToAsg(GenTree* tree, GenTree* child, CORINFO_CLASS_HANDLE retClsHnd);
5394 #endif // FEATURE_MULTIREG_RET
5395
5396     static fgWalkPreFn  fgUpdateInlineReturnExpressionPlaceHolder;
5397     static fgWalkPostFn fgLateDevirtualization;
5398
5399 #ifdef DEBUG
5400     static fgWalkPreFn fgDebugCheckInlineCandidates;
5401
5402     void               CheckNoTransformableIndirectCallsRemain();
5403     static fgWalkPreFn fgDebugCheckForTransformableIndirectCalls;
5404 #endif
5405
5406     void fgPromoteStructs();
5407     void fgMorphStructField(GenTree* tree, GenTree* parent);
5408     void fgMorphLocalField(GenTree* tree, GenTree* parent);
5409
5410     // Identify which parameters are implicit byrefs, and flag their LclVarDscs.
5411     void fgMarkImplicitByRefArgs();
5412
5413     // Change implicit byrefs' types from struct to pointer, and for any that were
5414     // promoted, create new promoted struct temps.
5415     void fgRetypeImplicitByRefArgs();
5416
5417     // Rewrite appearances of implicit byrefs (manifest the implied additional level of indirection).
5418     bool fgMorphImplicitByRefArgs(GenTree* tree);
5419     GenTree* fgMorphImplicitByRefArgs(GenTree* tree, bool isAddr);
5420
5421     // Clear up annotations for any struct promotion temps created for implicit byrefs.
5422     void fgMarkDemotedImplicitByRefArgs();
5423
5424     void fgMarkAddressExposedLocals();
5425
5426     static fgWalkPreFn  fgUpdateSideEffectsPre;
5427     static fgWalkPostFn fgUpdateSideEffectsPost;
5428
5429     // The given local variable, required to be a struct variable, is being assigned via
5430     // a "lclField", to make it masquerade as an integral type in the ABI.  Make sure that
5431     // the variable is not enregistered, and is therefore not promoted independently.
5432     void fgLclFldAssign(unsigned lclNum);
5433
5434     static fgWalkPreFn gtHasLocalsWithAddrOpCB;
5435
5436     enum TypeProducerKind
5437     {
5438         TPK_Unknown = 0, // May not be a RuntimeType
5439         TPK_Handle  = 1, // RuntimeType via handle
5440         TPK_GetType = 2, // RuntimeType via Object.get_Type()
5441         TPK_Null    = 3, // Tree value is null
5442         TPK_Other   = 4  // RuntimeType via other means
5443     };
5444
5445     TypeProducerKind gtGetTypeProducerKind(GenTree* tree);
5446     bool gtIsTypeHandleToRuntimeTypeHelper(GenTreeCall* call);
5447     bool gtIsTypeHandleToRuntimeTypeHandleHelper(GenTreeCall* call, CorInfoHelpFunc* pHelper = nullptr);
5448     bool gtIsActiveCSE_Candidate(GenTree* tree);
5449
5450 #ifdef DEBUG
5451     bool fgPrintInlinedMethods;
5452 #endif
5453
5454     bool fgIsBigOffset(size_t offset);
5455
5456     bool fgNeedReturnSpillTemp();
5457
5458     /*
5459     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5460     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5461     XX                                                                           XX
5462     XX                           Optimizer                                       XX
5463     XX                                                                           XX
5464     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5465     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5466     */
5467
5468 public:
5469     void optInit();
5470
5471     void optRemoveRangeCheck(GenTree* tree, GenTree* stmt);
5472     bool optIsRangeCheckRemovable(GenTree* tree);
5473
5474 protected:
5475     static fgWalkPreFn optValidRangeCheckIndex;
5476
5477     /**************************************************************************
5478      *
5479      *************************************************************************/
5480
5481 protected:
5482     // Do hoisting for all loops.
5483     void optHoistLoopCode();
5484
5485     // To represent sets of VN's that have already been hoisted in outer loops.
5486     typedef JitHashTable<ValueNum, JitSmallPrimitiveKeyFuncs<ValueNum>, bool> VNToBoolMap;
5487     typedef VNToBoolMap VNSet;
5488
5489     struct LoopHoistContext
5490     {
5491     private:
5492         // The set of variables hoisted in the current loop (or nullptr if there are none).
5493         VNSet* m_pHoistedInCurLoop;
5494
5495     public:
5496         // Value numbers of expressions that have been hoisted in parent loops in the loop nest.
5497         VNSet m_hoistedInParentLoops;
5498         // Value numbers of expressions that have been hoisted in the current (or most recent) loop in the nest.
5499         // Previous decisions on loop-invariance of value numbers in the current loop.
5500         VNToBoolMap m_curLoopVnInvariantCache;
5501
5502         VNSet* GetHoistedInCurLoop(Compiler* comp)
5503         {
5504             if (m_pHoistedInCurLoop == nullptr)
5505             {
5506                 m_pHoistedInCurLoop = new (comp->getAllocatorLoopHoist()) VNSet(comp->getAllocatorLoopHoist());
5507             }
5508             return m_pHoistedInCurLoop;
5509         }
5510
5511         VNSet* ExtractHoistedInCurLoop()
5512         {
5513             VNSet* res          = m_pHoistedInCurLoop;
5514             m_pHoistedInCurLoop = nullptr;
5515             return res;
5516         }
5517
5518         LoopHoistContext(Compiler* comp)
5519             : m_pHoistedInCurLoop(nullptr)
5520             , m_hoistedInParentLoops(comp->getAllocatorLoopHoist())
5521             , m_curLoopVnInvariantCache(comp->getAllocatorLoopHoist())
5522         {
5523         }
5524     };
5525
5526     // Do hoisting for loop "lnum" (an index into the optLoopTable), and all loops nested within it.
5527     // Tracks the expressions that have been hoisted by containing loops by temporary recording their
5528     // value numbers in "m_hoistedInParentLoops".  This set is not modified by the call.
5529     void optHoistLoopNest(unsigned lnum, LoopHoistContext* hoistCtxt);
5530
5531     // Do hoisting for a particular loop ("lnum" is an index into the optLoopTable.)
5532     // Assumes that expressions have been hoisted in containing loops if their value numbers are in
5533     // "m_hoistedInParentLoops".
5534     //
5535     void optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt);
5536
5537     // Hoist all expressions in "blk" that are invariant in loop "lnum" (an index into the optLoopTable)
5538     // outside of that loop.  Exempt expressions whose value number is in "m_hoistedInParentLoops"; add VN's of hoisted
5539     // expressions to "hoistInLoop".
5540     void optHoistLoopExprsForBlock(BasicBlock* blk, unsigned lnum, LoopHoistContext* hoistCtxt);
5541
5542     // Return true if the tree looks profitable to hoist out of loop 'lnum'.
5543     bool optIsProfitableToHoistableTree(GenTree* tree, unsigned lnum);
5544
5545     // Hoist all proper sub-expressions of "tree" (which occurs in "stmt", which occurs in "blk")
5546     // that are invariant in loop "lnum" (an index into the optLoopTable)
5547     // outside of that loop.  Exempt expressions whose value number is in "hoistedInParents"; add VN's of hoisted
5548     // expressions to "hoistInLoop".
5549     // Returns "true" iff "tree" is loop-invariant (wrt "lnum").
5550     // Assumes that the value of "*firstBlockAndBeforeSideEffect" indicates that we're in the first block, and before
5551     // any possible globally visible side effects.  Assume is called in evaluation order, and updates this.
5552     bool optHoistLoopExprsForTree(GenTree*          tree,
5553                                   unsigned          lnum,
5554                                   LoopHoistContext* hoistCtxt,
5555                                   bool*             firstBlockAndBeforeSideEffect,
5556                                   bool*             pHoistable,
5557                                   bool*             pCctorDependent);
5558
5559     // Performs the hoisting 'tree' into the PreHeader for loop 'lnum'
5560     void optHoistCandidate(GenTree* tree, unsigned lnum, LoopHoistContext* hoistCtxt);
5561
5562     // Returns true iff the ValueNum "vn" represents a value that is loop-invariant in "lnum".
5563     //   Constants and init values are always loop invariant.
5564     //   VNPhi's connect VN's to the SSA definition, so we can know if the SSA def occurs in the loop.
5565     bool optVNIsLoopInvariant(ValueNum vn, unsigned lnum, VNToBoolMap* recordedVNs);
5566
5567     // Returns "true" iff "tree" is valid at the head of loop "lnum", in the context of the hoist substitution
5568     // "subst".  If "tree" is a local SSA var, it is valid if its SSA definition occurs outside of the loop, or
5569     // if it is in the domain of "subst" (meaning that it's definition has been previously hoisted, with a "standin"
5570     // local.)  If tree is a constant, it is valid.  Otherwise, if it is an operator, it is valid iff its children are.
5571     bool optTreeIsValidAtLoopHead(GenTree* tree, unsigned lnum);
5572
5573     // If "blk" is the entry block of a natural loop, returns true and sets "*pLnum" to the index of the loop
5574     // in the loop table.
5575     bool optBlockIsLoopEntry(BasicBlock* blk, unsigned* pLnum);
5576
5577     // Records the set of "side effects" of all loops: fields (object instance and static)
5578     // written to, and SZ-array element type equivalence classes updated.
5579     void optComputeLoopSideEffects();
5580
5581 private:
5582     // Requires "lnum" to be the index of an outermost loop in the loop table.  Traverses the body of that loop,
5583     // including all nested loops, and records the set of "side effects" of the loop: fields (object instance and
5584     // static) written to, and SZ-array element type equivalence classes updated.
5585     void optComputeLoopNestSideEffects(unsigned lnum);
5586
5587     // Add the side effects of "blk" (which is required to be within a loop) to all loops of which it is a part.
5588     void optComputeLoopSideEffectsOfBlock(BasicBlock* blk);
5589
5590     // Hoist the expression "expr" out of loop "lnum".
5591     void optPerformHoistExpr(GenTree* expr, unsigned lnum);
5592
5593 public:
5594     void optOptimizeBools();
5595
5596 private:
5597     GenTree* optIsBoolCond(GenTree* condBranch, GenTree** compPtr, bool* boolPtr);
5598 #ifdef DEBUG
5599     void optOptimizeBoolsGcStress(BasicBlock* condBlock);
5600 #endif
5601 public:
5602     void optOptimizeLayout(); // Optimize the BasicBlock layout of the method
5603
5604     void optOptimizeLoops(); // for "while-do" loops duplicates simple loop conditions and transforms
5605                              // the loop into a "do-while" loop
5606                              // Also finds all natural loops and records them in the loop table
5607
5608     // Optionally clone loops in the loop table.
5609     void optCloneLoops();
5610
5611     // Clone loop "loopInd" in the loop table.
5612     void optCloneLoop(unsigned loopInd, LoopCloneContext* context);
5613
5614     // Ensure that loop "loopInd" has a unique head block.  (If the existing entry has
5615     // non-loop predecessors other than the head entry, create a new, empty block that goes (only) to the entry,
5616     // and redirects the preds of the entry to this new block.)  Sets the weight of the newly created block to
5617     // "ambientWeight".
5618     void optEnsureUniqueHead(unsigned loopInd, unsigned ambientWeight);
5619
5620     void optUnrollLoops(); // Unrolls loops (needs to have cost info)
5621
5622 protected:
5623     // This enumeration describes what is killed by a call.
5624
5625     enum callInterf
5626     {
5627         CALLINT_NONE,       // no interference                               (most helpers)
5628         CALLINT_REF_INDIRS, // kills GC ref indirections                     (SETFIELD OBJ)
5629         CALLINT_SCL_INDIRS, // kills non GC ref indirections                 (SETFIELD non-OBJ)
5630         CALLINT_ALL_INDIRS, // kills both GC ref and non GC ref indirections (SETFIELD STRUCT)
5631         CALLINT_ALL,        // kills everything                              (normal method call)
5632     };
5633
5634 public:
5635     // A "LoopDsc" describes a ("natural") loop.  We (currently) require the body of a loop to be a contiguous (in
5636     // bbNext order) sequence of basic blocks.  (At times, we may require the blocks in a loop to be "properly numbered"
5637     // in bbNext order; we use comparisons on the bbNum to decide order.)
5638     // The blocks that define the body are
5639     //   first <= top <= entry <= bottom   .
5640     // The "head" of the loop is a block outside the loop that has "entry" as a successor. We only support loops with a
5641     // single 'head' block. The meanings of these blocks are given in the definitions below. Also see the picture at
5642     // Compiler::optFindNaturalLoops().
5643     struct LoopDsc
5644     {
5645         BasicBlock* lpHead;  // HEAD of the loop (not part of the looping of the loop) -- has ENTRY as a successor.
5646         BasicBlock* lpFirst; // FIRST block (in bbNext order) reachable within this loop.  (May be part of a nested
5647                              // loop, but not the outer loop.)
5648         BasicBlock* lpTop;   // loop TOP (the back edge from lpBottom reaches here) (in most cases FIRST and TOP are the
5649                              // same)
5650         BasicBlock* lpEntry; // the ENTRY in the loop (in most cases TOP or BOTTOM)
5651         BasicBlock* lpBottom; // loop BOTTOM (from here we have a back edge to the TOP)
5652         BasicBlock* lpExit;   // if a single exit loop this is the EXIT (in most cases BOTTOM)
5653
5654         callInterf   lpAsgCall;     // "callInterf" for calls in the loop
5655         ALLVARSET_TP lpAsgVars;     // set of vars assigned within the loop (all vars, not just tracked)
5656         varRefKinds  lpAsgInds : 8; // set of inds modified within the loop
5657
5658         unsigned short lpFlags; // Mask of the LPFLG_* constants
5659
5660         unsigned char lpExitCnt; // number of exits from the loop
5661
5662         unsigned char lpParent;  // The index of the most-nested loop that completely contains this one,
5663                                  // or else BasicBlock::NOT_IN_LOOP if no such loop exists.
5664         unsigned char lpChild;   // The index of a nested loop, or else BasicBlock::NOT_IN_LOOP if no child exists.
5665                                  // (Actually, an "immediately" nested loop --
5666                                  // no other child of this loop is a parent of lpChild.)
5667         unsigned char lpSibling; // The index of another loop that is an immediate child of lpParent,
5668                                  // or else BasicBlock::NOT_IN_LOOP.  One can enumerate all the children of a loop
5669                                  // by following "lpChild" then "lpSibling" links.
5670
5671 #define LPFLG_DO_WHILE 0x0001 // it's a do-while loop (i.e ENTRY is at the TOP)
5672 #define LPFLG_ONE_EXIT 0x0002 // the loop has only one exit
5673
5674 #define LPFLG_ITER 0x0004      // for (i = icon or lclVar; test_condition(); i++)
5675 #define LPFLG_HOISTABLE 0x0008 // the loop is in a form that is suitable for hoisting expressions
5676 #define LPFLG_CONST 0x0010     // for (i=icon;i<icon;i++){ ... } - constant loop
5677
5678 #define LPFLG_VAR_INIT 0x0020   // iterator is initialized with a local var (var # found in lpVarInit)
5679 #define LPFLG_CONST_INIT 0x0040 // iterator is initialized with a constant (found in lpConstInit)
5680
5681 #define LPFLG_VAR_LIMIT 0x0100    // iterator is compared with a local var (var # found in lpVarLimit)
5682 #define LPFLG_CONST_LIMIT 0x0200  // iterator is compared with a constant (found in lpConstLimit)
5683 #define LPFLG_ARRLEN_LIMIT 0x0400 // iterator is compared with a.len or a[i].len (found in lpArrLenLimit)
5684 #define LPFLG_SIMD_LIMIT 0x0080   // iterator is compared with Vector<T>.Count (found in lpConstLimit)
5685
5686 #define LPFLG_HAS_PREHEAD 0x0800 // lpHead is known to be a preHead for this loop
5687 #define LPFLG_REMOVED 0x1000     // has been removed from the loop table (unrolled or optimized away)
5688 #define LPFLG_DONT_UNROLL 0x2000 // do not unroll this loop
5689
5690 #define LPFLG_ASGVARS_YES 0x4000 // "lpAsgVars" has been  computed
5691 #define LPFLG_ASGVARS_INC 0x8000 // "lpAsgVars" is incomplete -- vars beyond those representable in an AllVarSet
5692                                  // type are assigned to.
5693
5694         bool lpLoopHasMemoryHavoc[MemoryKindCount]; // The loop contains an operation that we assume has arbitrary
5695                                                     // memory side effects.  If this is set, the fields below
5696                                                     // may not be accurate (since they become irrelevant.)
5697         bool lpContainsCall;                        // True if executing the loop body *may* execute a call
5698
5699         VARSET_TP lpVarInOut;  // The set of variables that are IN or OUT during the execution of this loop
5700         VARSET_TP lpVarUseDef; // The set of variables that are USE or DEF during the execution of this loop
5701
5702         int lpHoistedExprCount; // The register count for the non-FP expressions from inside this loop that have been
5703                                 // hoisted
5704         int lpLoopVarCount;     // The register count for the non-FP LclVars that are read/written inside this loop
5705         int lpVarInOutCount;    // The register count for the non-FP LclVars that are alive inside or accross this loop
5706
5707         int lpHoistedFPExprCount; // The register count for the FP expressions from inside this loop that have been
5708                                   // hoisted
5709         int lpLoopVarFPCount;     // The register count for the FP LclVars that are read/written inside this loop
5710         int lpVarInOutFPCount;    // The register count for the FP LclVars that are alive inside or accross this loop
5711
5712         typedef JitHashTable<CORINFO_FIELD_HANDLE, JitPtrKeyFuncs<struct CORINFO_FIELD_STRUCT_>, bool> FieldHandleSet;
5713         FieldHandleSet* lpFieldsModified; // This has entries (mappings to "true") for all static field and object
5714                                           // instance fields modified
5715                                           // in the loop.
5716
5717         typedef JitHashTable<CORINFO_CLASS_HANDLE, JitPtrKeyFuncs<struct CORINFO_CLASS_STRUCT_>, bool> ClassHandleSet;
5718         ClassHandleSet* lpArrayElemTypesModified; // Bits set indicate the set of sz array element types such that
5719                                                   // arrays of that type are modified
5720                                                   // in the loop.
5721
5722         // Adds the variable liveness information for 'blk' to 'this' LoopDsc
5723         void AddVariableLiveness(Compiler* comp, BasicBlock* blk);
5724
5725         inline void AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd);
5726         // This doesn't *always* take a class handle -- it can also take primitive types, encoded as class handles
5727         // (shifted left, with a low-order bit set to distinguish.)
5728         // Use the {Encode/Decode}ElemType methods to construct/destruct these.
5729         inline void AddModifiedElemType(Compiler* comp, CORINFO_CLASS_HANDLE structHnd);
5730
5731         /* The following values are set only for iterator loops, i.e. has the flag LPFLG_ITER set */
5732
5733         GenTree*   lpIterTree;    // The "i = i <op> const" tree
5734         unsigned   lpIterVar();   // iterator variable #
5735         int        lpIterConst(); // the constant with which the iterator is incremented
5736         genTreeOps lpIterOper();  // the type of the operation on the iterator (ASG_ADD, ASG_SUB, etc.)
5737         void       VERIFY_lpIterTree();
5738
5739         var_types lpIterOperType(); // For overflow instructions
5740
5741         union {
5742             int lpConstInit; // initial constant value of iterator                           : Valid if LPFLG_CONST_INIT
5743             unsigned lpVarInit; // initial local var number to which we initialize the iterator : Valid if
5744                                 // LPFLG_VAR_INIT
5745         };
5746
5747         /* The following is for LPFLG_ITER loops only (i.e. the loop condition is "i RELOP const or var" */
5748
5749         GenTree*   lpTestTree;   // pointer to the node containing the loop test
5750         genTreeOps lpTestOper(); // the type of the comparison between the iterator and the limit (GT_LE, GT_GE, etc.)
5751         void       VERIFY_lpTestTree();
5752
5753         bool     lpIsReversed(); // true if the iterator node is the second operand in the loop condition
5754         GenTree* lpIterator();   // the iterator node in the loop test
5755         GenTree* lpLimit();      // the limit node in the loop test
5756
5757         int lpConstLimit();    // limit   constant value of iterator - loop condition is "i RELOP const" : Valid if
5758                                // LPFLG_CONST_LIMIT
5759         unsigned lpVarLimit(); // the lclVar # in the loop condition ( "i RELOP lclVar" )                : Valid if
5760                                // LPFLG_VAR_LIMIT
5761         bool lpArrLenLimit(Compiler* comp, ArrIndex* index); // The array length in the loop condition ( "i RELOP
5762                                                              // arr.len" or "i RELOP arr[i][j].len" )  : Valid if
5763                                                              // LPFLG_ARRLEN_LIMIT
5764
5765         // Returns "true" iff "*this" contains the blk.
5766         bool lpContains(BasicBlock* blk)
5767         {
5768             return lpFirst->bbNum <= blk->bbNum && blk->bbNum <= lpBottom->bbNum;
5769         }
5770         // Returns "true" iff "*this" (properly) contains the range [first, bottom] (allowing firsts
5771         // to be equal, but requiring bottoms to be different.)
5772         bool lpContains(BasicBlock* first, BasicBlock* bottom)
5773         {
5774             return lpFirst->bbNum <= first->bbNum && bottom->bbNum < lpBottom->bbNum;
5775         }
5776
5777         // Returns "true" iff "*this" (properly) contains "lp2" (allowing firsts to be equal, but requiring
5778         // bottoms to be different.)
5779         bool lpContains(const LoopDsc& lp2)
5780         {
5781             return lpContains(lp2.lpFirst, lp2.lpBottom);
5782         }
5783
5784         // Returns "true" iff "*this" is (properly) contained by the range [first, bottom]
5785         // (allowing firsts to be equal, but requiring bottoms to be different.)
5786         bool lpContainedBy(BasicBlock* first, BasicBlock* bottom)
5787         {
5788             return first->bbNum <= lpFirst->bbNum && lpBottom->bbNum < bottom->bbNum;
5789         }
5790
5791         // Returns "true" iff "*this" is (properly) contained by "lp2"
5792         // (allowing firsts to be equal, but requiring bottoms to be different.)
5793         bool lpContainedBy(const LoopDsc& lp2)
5794         {
5795             return lpContains(lp2.lpFirst, lp2.lpBottom);
5796         }
5797
5798         // Returns "true" iff "*this" is disjoint from the range [top, bottom].
5799         bool lpDisjoint(BasicBlock* first, BasicBlock* bottom)
5800         {
5801             return bottom->bbNum < lpFirst->bbNum || lpBottom->bbNum < first->bbNum;
5802         }
5803         // Returns "true" iff "*this" is disjoint from "lp2".
5804         bool lpDisjoint(const LoopDsc& lp2)
5805         {
5806             return lpDisjoint(lp2.lpFirst, lp2.lpBottom);
5807         }
5808         // Returns "true" iff the loop is well-formed (see code for defn).
5809         bool lpWellFormed()
5810         {
5811             return lpFirst->bbNum <= lpTop->bbNum && lpTop->bbNum <= lpEntry->bbNum &&
5812                    lpEntry->bbNum <= lpBottom->bbNum &&
5813                    (lpHead->bbNum < lpTop->bbNum || lpHead->bbNum > lpBottom->bbNum);
5814         }
5815     };
5816
5817 protected:
5818     bool fgMightHaveLoop(); // returns true if there are any backedges
5819     bool fgHasLoops;        // True if this method has any loops, set in fgComputeReachability
5820
5821 public:
5822     LoopDsc*      optLoopTable; // loop descriptor table
5823     unsigned char optLoopCount; // number of tracked loops
5824
5825     bool optRecordLoop(BasicBlock*   head,
5826                        BasicBlock*   first,
5827                        BasicBlock*   top,
5828                        BasicBlock*   entry,
5829                        BasicBlock*   bottom,
5830                        BasicBlock*   exit,
5831                        unsigned char exitCnt);
5832
5833 protected:
5834     unsigned optCallCount;         // number of calls made in the method
5835     unsigned optIndirectCallCount; // number of virtual, interface and indirect calls made in the method
5836     unsigned optNativeCallCount;   // number of Pinvoke/Native calls made in the method
5837     unsigned optLoopsCloned;       // number of loops cloned in the current method.
5838
5839 #ifdef DEBUG
5840     unsigned optFindLoopNumberFromBeginBlock(BasicBlock* begBlk);
5841     void optPrintLoopInfo(unsigned      loopNum,
5842                           BasicBlock*   lpHead,
5843                           BasicBlock*   lpFirst,
5844                           BasicBlock*   lpTop,
5845                           BasicBlock*   lpEntry,
5846                           BasicBlock*   lpBottom,
5847                           unsigned char lpExitCnt,
5848                           BasicBlock*   lpExit,
5849                           unsigned      parentLoop = BasicBlock::NOT_IN_LOOP);
5850     void optPrintLoopInfo(unsigned lnum);
5851     void optPrintLoopRecording(unsigned lnum);
5852
5853     void optCheckPreds();
5854 #endif
5855
5856     void optSetBlockWeights();
5857
5858     void optMarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk, bool excludeEndBlk);
5859
5860     void optUnmarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk);
5861
5862     void optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmarkLoop = false);
5863
5864     bool optIsLoopTestEvalIntoTemp(GenTree* test, GenTree** newTest);
5865     unsigned optIsLoopIncrTree(GenTree* incr);
5866     bool optCheckIterInLoopTest(unsigned loopInd, GenTree* test, BasicBlock* from, BasicBlock* to, unsigned iterVar);
5867     bool optComputeIterInfo(GenTree* incr, BasicBlock* from, BasicBlock* to, unsigned* pIterVar);
5868     bool optPopulateInitInfo(unsigned loopInd, GenTree* init, unsigned iterVar);
5869     bool optExtractInitTestIncr(
5870         BasicBlock* head, BasicBlock* bottom, BasicBlock* exit, GenTree** ppInit, GenTree** ppTest, GenTree** ppIncr);
5871
5872     void optFindNaturalLoops();
5873
5874     // Ensures that all the loops in the loop nest rooted at "loopInd" (an index into the loop table) are 'canonical' --
5875     // each loop has a unique "top."  Returns "true" iff the flowgraph has been modified.
5876     bool optCanonicalizeLoopNest(unsigned char loopInd);
5877
5878     // Ensures that the loop "loopInd" (an index into the loop table) is 'canonical' -- it has a unique "top,"
5879     // unshared with any other loop.  Returns "true" iff the flowgraph has been modified
5880     bool optCanonicalizeLoop(unsigned char loopInd);
5881
5882     // Requires "l1" to be a valid loop table index, and not "BasicBlock::NOT_IN_LOOP".  Requires "l2" to be
5883     // a valid loop table index, or else "BasicBlock::NOT_IN_LOOP".  Returns true
5884     // iff "l2" is not NOT_IN_LOOP, and "l1" contains "l2".
5885     bool optLoopContains(unsigned l1, unsigned l2);
5886
5887     // Requires "loopInd" to be a valid index into the loop table.
5888     // Updates the loop table by changing loop "loopInd", whose head is required
5889     // to be "from", to be "to".  Also performs this transformation for any
5890     // loop nested in "loopInd" that shares the same head as "loopInd".
5891     void optUpdateLoopHead(unsigned loopInd, BasicBlock* from, BasicBlock* to);
5892
5893     // Updates the successors of "blk": if "blk2" is a successor of "blk", and there is a mapping for "blk2->blk3" in
5894     // "redirectMap", change "blk" so that "blk3" is this successor. Note that the predecessor lists are not updated.
5895     void optRedirectBlock(BasicBlock* blk, BlockToBlockMap* redirectMap);
5896
5897     // Marks the containsCall information to "lnum" and any parent loops.
5898     void AddContainsCallAllContainingLoops(unsigned lnum);
5899     // Adds the variable liveness information from 'blk' to "lnum" and any parent loops.
5900     void AddVariableLivenessAllContainingLoops(unsigned lnum, BasicBlock* blk);
5901     // Adds "fldHnd" to the set of modified fields of "lnum" and any parent loops.
5902     void AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd);
5903     // Adds "elemType" to the set of modified array element types of "lnum" and any parent loops.
5904     void AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLASS_HANDLE elemType);
5905
5906     // Requires that "from" and "to" have the same "bbJumpKind" (perhaps because "to" is a clone
5907     // of "from".)  Copies the jump destination from "from" to "to".
5908     void optCopyBlkDest(BasicBlock* from, BasicBlock* to);
5909
5910     // The depth of the loop described by "lnum" (an index into the loop table.) (0 == top level)
5911     unsigned optLoopDepth(unsigned lnum)
5912     {
5913         unsigned par = optLoopTable[lnum].lpParent;
5914         if (par == BasicBlock::NOT_IN_LOOP)
5915         {
5916             return 0;
5917         }
5918         else
5919         {
5920             return 1 + optLoopDepth(par);
5921         }
5922     }
5923
5924     void fgOptWhileLoop(BasicBlock* block);
5925
5926     bool optComputeLoopRep(int        constInit,
5927                            int        constLimit,
5928                            int        iterInc,
5929                            genTreeOps iterOper,
5930                            var_types  iterType,
5931                            genTreeOps testOper,
5932                            bool       unsignedTest,
5933                            bool       dupCond,
5934                            unsigned*  iterCount);
5935
5936 private:
5937     static fgWalkPreFn optIsVarAssgCB;
5938
5939 protected:
5940     bool optIsVarAssigned(BasicBlock* beg, BasicBlock* end, GenTree* skip, unsigned var);
5941
5942     bool optIsVarAssgLoop(unsigned lnum, unsigned var);
5943
5944     int optIsSetAssgLoop(unsigned lnum, ALLVARSET_VALARG_TP vars, varRefKinds inds = VR_NONE);
5945
5946     bool optNarrowTree(GenTree* tree, var_types srct, var_types dstt, ValueNumPair vnpNarrow, bool doit);
5947
5948     /**************************************************************************
5949      *                       Optimization conditions
5950      *************************************************************************/
5951
5952     bool optFastCodeOrBlendedLoop(BasicBlock::weight_t bbWeight);
5953     bool optPentium4(void);
5954     bool optAvoidIncDec(BasicBlock::weight_t bbWeight);
5955     bool optAvoidIntMult(void);
5956
5957 #if FEATURE_ANYCSE
5958
5959 protected:
5960     //  The following is the upper limit on how many expressions we'll keep track
5961     //  of for the CSE analysis.
5962     //
5963     static const unsigned MAX_CSE_CNT = EXPSET_SZ;
5964
5965     static const int MIN_CSE_COST = 2;
5966
5967     // Keeps tracked cse indices
5968     BitVecTraits* cseTraits;
5969     EXPSET_TP     cseFull;
5970
5971     /* Generic list of nodes - used by the CSE logic */
5972
5973     struct treeLst
5974     {
5975         treeLst* tlNext;
5976         GenTree* tlTree;
5977     };
5978
5979     struct treeStmtLst
5980     {
5981         treeStmtLst* tslNext;
5982         GenTree*     tslTree;  // tree node
5983         GenTree*     tslStmt;  // statement containing the tree
5984         BasicBlock*  tslBlock; // block containing the statement
5985     };
5986
5987     // The following logic keeps track of expressions via a simple hash table.
5988
5989     struct CSEdsc
5990     {
5991         CSEdsc* csdNextInBucket; // used by the hash table
5992
5993         unsigned csdHashKey; // the orginal hashkey
5994
5995         unsigned csdIndex;          // 1..optCSECandidateCount
5996         char     csdLiveAcrossCall; // 0 or 1
5997
5998         unsigned short csdDefCount; // definition   count
5999         unsigned short csdUseCount; // use          count  (excluding the implicit uses at defs)
6000
6001         unsigned csdDefWtCnt; // weighted def count
6002         unsigned csdUseWtCnt; // weighted use count  (excluding the implicit uses at defs)
6003
6004         GenTree*    csdTree;  // treenode containing the 1st occurance
6005         GenTree*    csdStmt;  // stmt containing the 1st occurance
6006         BasicBlock* csdBlock; // block containing the 1st occurance
6007
6008         treeStmtLst* csdTreeList; // list of matching tree nodes: head
6009         treeStmtLst* csdTreeLast; // list of matching tree nodes: tail
6010
6011         ValueNum defExcSetPromise; // The exception set that is now required for all defs of this CSE.
6012                                    // This will be set to NoVN if we decide to abandon this CSE
6013
6014         ValueNum defExcSetCurrent; // The set of exceptions we currently can use for CSE uses.
6015
6016         ValueNum defConservNormVN; // if all def occurrences share the same conservative normal value
6017                                    // number, this will reflect it; otherwise, NoVN.
6018     };
6019
6020     static const size_t s_optCSEhashSize;
6021     CSEdsc**            optCSEhash;
6022     CSEdsc**            optCSEtab;
6023
6024     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, GenTree*> NodeToNodeMap;
6025
6026     NodeToNodeMap* optCseCheckedBoundMap; // Maps bound nodes to ancestor compares that should be
6027                                           // re-numbered with the bound to improve range check elimination
6028
6029     // Given a compare, look for a cse candidate checked bound feeding it and add a map entry if found.
6030     void optCseUpdateCheckedBoundMap(GenTree* compare);
6031
6032     void optCSEstop();
6033
6034     CSEdsc* optCSEfindDsc(unsigned index);
6035     bool optUnmarkCSE(GenTree* tree);
6036
6037     // user defined callback data for the tree walk function optCSE_MaskHelper()
6038     struct optCSE_MaskData
6039     {
6040         EXPSET_TP CSE_defMask;
6041         EXPSET_TP CSE_useMask;
6042     };
6043
6044     // Treewalk helper for optCSE_DefMask and optCSE_UseMask
6045     static fgWalkPreFn optCSE_MaskHelper;
6046
6047     // This function walks all the node for an given tree
6048     // and return the mask of CSE definitions and uses for the tree
6049     //
6050     void optCSE_GetMaskData(GenTree* tree, optCSE_MaskData* pMaskData);
6051
6052     // Given a binary tree node return true if it is safe to swap the order of evaluation for op1 and op2.
6053     bool optCSE_canSwap(GenTree* firstNode, GenTree* secondNode);
6054     bool optCSE_canSwap(GenTree* tree);
6055
6056     static int __cdecl optCSEcostCmpEx(const void* op1, const void* op2);
6057     static int __cdecl optCSEcostCmpSz(const void* op1, const void* op2);
6058
6059     void optCleanupCSEs();
6060
6061 #ifdef DEBUG
6062     void optEnsureClearCSEInfo();
6063 #endif // DEBUG
6064
6065 #endif // FEATURE_ANYCSE
6066
6067 #if FEATURE_VALNUM_CSE
6068     /**************************************************************************
6069      *                   Value Number based CSEs
6070      *************************************************************************/
6071
6072 public:
6073     void optOptimizeValnumCSEs();
6074
6075 protected:
6076     void     optValnumCSE_Init();
6077     unsigned optValnumCSE_Index(GenTree* tree, GenTree* stmt);
6078     unsigned optValnumCSE_Locate();
6079     void     optValnumCSE_InitDataFlow();
6080     void     optValnumCSE_DataFlow();
6081     void     optValnumCSE_Availablity();
6082     void     optValnumCSE_Heuristic();
6083
6084 #endif // FEATURE_VALNUM_CSE
6085
6086 #if FEATURE_ANYCSE
6087     bool     optDoCSE;             // True when we have found a duplicate CSE tree
6088     bool     optValnumCSE_phase;   // True when we are executing the optValnumCSE_phase
6089     unsigned optCSECandidateTotal; // Grand total of CSE candidates for both Lexical and ValNum
6090     unsigned optCSECandidateCount; // Count of CSE's candidates, reset for Lexical and ValNum CSE's
6091     unsigned optCSEstart;          // The first local variable number that is a CSE
6092     unsigned optCSEcount;          // The total count of CSE's introduced.
6093     unsigned optCSEweight;         // The weight of the current block when we are
6094                                    // scanning for CSE expressions
6095
6096     bool optIsCSEcandidate(GenTree* tree);
6097
6098     // lclNumIsTrueCSE returns true if the LclVar was introduced by the CSE phase of the compiler
6099     //
6100     bool lclNumIsTrueCSE(unsigned lclNum) const
6101     {
6102         return ((optCSEcount > 0) && (lclNum >= optCSEstart) && (lclNum < optCSEstart + optCSEcount));
6103     }
6104
6105     //  lclNumIsCSE returns true if the LclVar should be treated like a CSE with regards to constant prop.
6106     //
6107     bool lclNumIsCSE(unsigned lclNum) const
6108     {
6109         return lvaTable[lclNum].lvIsCSE;
6110     }
6111
6112 #ifdef DEBUG
6113     bool optConfigDisableCSE();
6114     bool optConfigDisableCSE2();
6115 #endif
6116     void optOptimizeCSEs();
6117
6118 #endif // FEATURE_ANYCSE
6119
6120     struct isVarAssgDsc
6121     {
6122         GenTree* ivaSkip;
6123 #ifdef DEBUG
6124         void* ivaSelf;
6125 #endif
6126         unsigned     ivaVar;            // Variable we are interested in, or -1
6127         ALLVARSET_TP ivaMaskVal;        // Set of variables assigned to.  This is a set of all vars, not tracked vars.
6128         bool         ivaMaskIncomplete; // Variables not representable in ivaMaskVal were assigned to.
6129         varRefKinds  ivaMaskInd;        // What kind of indirect assignments are there?
6130         callInterf   ivaMaskCall;       // What kind of calls are there?
6131     };
6132
6133     static callInterf optCallInterf(GenTreeCall* call);
6134
6135 public:
6136     // VN based copy propagation.
6137     typedef ArrayStack<GenTree*> GenTreePtrStack;
6138     typedef JitHashTable<unsigned, JitSmallPrimitiveKeyFuncs<unsigned>, GenTreePtrStack*> LclNumToGenTreePtrStack;
6139
6140     // Kill set to track variables with intervening definitions.
6141     VARSET_TP optCopyPropKillSet;
6142
6143     // Copy propagation functions.
6144     void optCopyProp(BasicBlock* block, GenTree* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName);
6145     void optBlockCopyPropPopStacks(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName);
6146     void optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName);
6147     bool optIsSsaLocal(GenTree* tree);
6148     int optCopyProp_LclVarScore(LclVarDsc* lclVarDsc, LclVarDsc* copyVarDsc, bool preferOp2);
6149     void optVnCopyProp();
6150     INDEBUG(void optDumpCopyPropStack(LclNumToGenTreePtrStack* curSsaName));
6151
6152     /**************************************************************************
6153     *               Early value propagation
6154     *************************************************************************/
6155     struct SSAName
6156     {
6157         unsigned m_lvNum;
6158         unsigned m_ssaNum;
6159
6160         SSAName(unsigned lvNum, unsigned ssaNum) : m_lvNum(lvNum), m_ssaNum(ssaNum)
6161         {
6162         }
6163
6164         static unsigned GetHashCode(SSAName ssaNm)
6165         {
6166             return (ssaNm.m_lvNum << 16) | (ssaNm.m_ssaNum);
6167         }
6168
6169         static bool Equals(SSAName ssaNm1, SSAName ssaNm2)
6170         {
6171             return (ssaNm1.m_lvNum == ssaNm2.m_lvNum) && (ssaNm1.m_ssaNum == ssaNm2.m_ssaNum);
6172         }
6173     };
6174
6175 #define OMF_HAS_NEWARRAY 0x00000001      // Method contains 'new' of an array
6176 #define OMF_HAS_NEWOBJ 0x00000002        // Method contains 'new' of an object type.
6177 #define OMF_HAS_ARRAYREF 0x00000004      // Method contains array element loads or stores.
6178 #define OMF_HAS_VTABLEREF 0x00000008     // Method contains method table reference.
6179 #define OMF_HAS_NULLCHECK 0x00000010     // Method contains null check.
6180 #define OMF_HAS_FATPOINTER 0x00000020    // Method contains call, that needs fat pointer transformation.
6181 #define OMF_HAS_OBJSTACKALLOC 0x00000040 // Method contains an object allocated on the stack.
6182 #define OMF_HAS_GUARDEDDEVIRT 0x00000080 // Method contains guarded devirtualization candidate
6183
6184     bool doesMethodHaveFatPointer()
6185     {
6186         return (optMethodFlags & OMF_HAS_FATPOINTER) != 0;
6187     }
6188
6189     void setMethodHasFatPointer()
6190     {
6191         optMethodFlags |= OMF_HAS_FATPOINTER;
6192     }
6193
6194     void clearMethodHasFatPointer()
6195     {
6196         optMethodFlags &= ~OMF_HAS_FATPOINTER;
6197     }
6198
6199     void addFatPointerCandidate(GenTreeCall* call);
6200
6201     bool doesMethodHaveGuardedDevirtualization()
6202     {
6203         return (optMethodFlags & OMF_HAS_GUARDEDDEVIRT) != 0;
6204     }
6205
6206     void setMethodHasGuardedDevirtualization()
6207     {
6208         optMethodFlags |= OMF_HAS_GUARDEDDEVIRT;
6209     }
6210
6211     void clearMethodHasGuardedDevirtualization()
6212     {
6213         optMethodFlags &= ~OMF_HAS_GUARDEDDEVIRT;
6214     }
6215
6216     void addGuardedDevirtualizationCandidate(GenTreeCall*          call,
6217                                              CORINFO_METHOD_HANDLE methodHandle,
6218                                              CORINFO_CLASS_HANDLE  classHandle,
6219                                              unsigned              methodAttr,
6220                                              unsigned              classAttr);
6221
6222     unsigned optMethodFlags;
6223
6224     // Recursion bound controls how far we can go backwards tracking for a SSA value.
6225     // No throughput diff was found with backward walk bound between 3-8.
6226     static const int optEarlyPropRecurBound = 5;
6227
6228     enum class optPropKind
6229     {
6230         OPK_INVALID,
6231         OPK_ARRAYLEN,
6232         OPK_OBJ_GETTYPE,
6233         OPK_NULLCHECK
6234     };
6235
6236     bool gtIsVtableRef(GenTree* tree);
6237     GenTree* getArrayLengthFromAllocation(GenTree* tree);
6238     GenTree* getObjectHandleNodeFromAllocation(GenTree* tree);
6239     GenTree* optPropGetValueRec(unsigned lclNum, unsigned ssaNum, optPropKind valueKind, int walkDepth);
6240     GenTree* optPropGetValue(unsigned lclNum, unsigned ssaNum, optPropKind valueKind);
6241     GenTree* optEarlyPropRewriteTree(GenTree* tree);
6242     bool optDoEarlyPropForBlock(BasicBlock* block);
6243     bool optDoEarlyPropForFunc();
6244     void optEarlyProp();
6245     void optFoldNullCheck(GenTree* tree);
6246     bool optCanMoveNullCheckPastTree(GenTree* tree, bool isInsideTry);
6247
6248 #if ASSERTION_PROP
6249     /**************************************************************************
6250      *               Value/Assertion propagation
6251      *************************************************************************/
6252 public:
6253     // Data structures for assertion prop
6254     BitVecTraits* apTraits;
6255     ASSERT_TP     apFull;
6256
6257     enum optAssertionKind
6258     {
6259         OAK_INVALID,
6260         OAK_EQUAL,
6261         OAK_NOT_EQUAL,
6262         OAK_SUBRANGE,
6263         OAK_NO_THROW,
6264         OAK_COUNT
6265     };
6266
6267     enum optOp1Kind
6268     {
6269         O1K_INVALID,
6270         O1K_LCLVAR,
6271         O1K_ARR_BND,
6272         O1K_BOUND_OPER_BND,
6273         O1K_BOUND_LOOP_BND,
6274         O1K_CONSTANT_LOOP_BND,
6275         O1K_EXACT_TYPE,
6276         O1K_SUBTYPE,
6277         O1K_VALUE_NUMBER,
6278         O1K_COUNT
6279     };
6280
6281     enum optOp2Kind
6282     {
6283         O2K_INVALID,
6284         O2K_LCLVAR_COPY,
6285         O2K_IND_CNS_INT,
6286         O2K_CONST_INT,
6287         O2K_CONST_LONG,
6288         O2K_CONST_DOUBLE,
6289         O2K_ARR_LEN,
6290         O2K_SUBRANGE,
6291         O2K_COUNT
6292     };
6293     struct AssertionDsc
6294     {
6295         optAssertionKind assertionKind;
6296         struct SsaVar
6297         {
6298             unsigned lclNum; // assigned to or property of this local var number
6299             unsigned ssaNum;
6300         };
6301         struct ArrBnd
6302         {
6303             ValueNum vnIdx;
6304             ValueNum vnLen;
6305         };
6306         struct AssertionDscOp1
6307         {
6308             optOp1Kind kind; // a normal LclVar, or Exact-type or Subtype
6309             ValueNum   vn;
6310             union {
6311                 SsaVar lcl;
6312                 ArrBnd bnd;
6313             };
6314         } op1;
6315         struct AssertionDscOp2
6316         {
6317             optOp2Kind kind; // a const or copy assignment
6318             ValueNum   vn;
6319             struct IntVal
6320             {
6321                 ssize_t  iconVal;   // integer
6322                 unsigned iconFlags; // gtFlags
6323             };
6324             struct Range // integer subrange
6325             {
6326                 ssize_t loBound;
6327                 ssize_t hiBound;
6328             };
6329             union {
6330                 SsaVar  lcl;
6331                 IntVal  u1;
6332                 __int64 lconVal;
6333                 double  dconVal;
6334                 Range   u2;
6335             };
6336         } op2;
6337
6338         bool IsCheckedBoundArithBound()
6339         {
6340             return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_BOUND_OPER_BND);
6341         }
6342         bool IsCheckedBoundBound()
6343         {
6344             return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_BOUND_LOOP_BND);
6345         }
6346         bool IsConstantBound()
6347         {
6348             return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) &&
6349                     op1.kind == O1K_CONSTANT_LOOP_BND);
6350         }
6351         bool IsBoundsCheckNoThrow()
6352         {
6353             return ((assertionKind == OAK_NO_THROW) && (op1.kind == O1K_ARR_BND));
6354         }
6355
6356         bool IsCopyAssertion()
6357         {
6358             return ((assertionKind == OAK_EQUAL) && (op1.kind == O1K_LCLVAR) && (op2.kind == O2K_LCLVAR_COPY));
6359         }
6360
6361         static bool SameKind(AssertionDsc* a1, AssertionDsc* a2)
6362         {
6363             return a1->assertionKind == a2->assertionKind && a1->op1.kind == a2->op1.kind &&
6364                    a1->op2.kind == a2->op2.kind;
6365         }
6366
6367         static bool ComplementaryKind(optAssertionKind kind, optAssertionKind kind2)
6368         {
6369             if (kind == OAK_EQUAL)
6370             {
6371                 return kind2 == OAK_NOT_EQUAL;
6372             }
6373             else if (kind == OAK_NOT_EQUAL)
6374             {
6375                 return kind2 == OAK_EQUAL;
6376             }
6377             return false;
6378         }
6379
6380         static ssize_t GetLowerBoundForIntegralType(var_types type)
6381         {
6382             switch (type)
6383             {
6384                 case TYP_BYTE:
6385                     return SCHAR_MIN;
6386                 case TYP_SHORT:
6387                     return SHRT_MIN;
6388                 case TYP_INT:
6389                     return INT_MIN;
6390                 case TYP_BOOL:
6391                 case TYP_UBYTE:
6392                 case TYP_USHORT:
6393                 case TYP_UINT:
6394                     return 0;
6395                 default:
6396                     unreached();
6397             }
6398         }
6399         static ssize_t GetUpperBoundForIntegralType(var_types type)
6400         {
6401             switch (type)
6402             {
6403                 case TYP_BOOL:
6404                     return 1;
6405                 case TYP_BYTE:
6406                     return SCHAR_MAX;
6407                 case TYP_SHORT:
6408                     return SHRT_MAX;
6409                 case TYP_INT:
6410                     return INT_MAX;
6411                 case TYP_UBYTE:
6412                     return UCHAR_MAX;
6413                 case TYP_USHORT:
6414                     return USHRT_MAX;
6415                 case TYP_UINT:
6416                     return UINT_MAX;
6417                 default:
6418                     unreached();
6419             }
6420         }
6421
6422         bool HasSameOp1(AssertionDsc* that, bool vnBased)
6423         {
6424             if (op1.kind != that->op1.kind)
6425             {
6426                 return false;
6427             }
6428             else if (op1.kind == O1K_ARR_BND)
6429             {
6430                 assert(vnBased);
6431                 return (op1.bnd.vnIdx == that->op1.bnd.vnIdx) && (op1.bnd.vnLen == that->op1.bnd.vnLen);
6432             }
6433             else
6434             {
6435                 return ((vnBased && (op1.vn == that->op1.vn)) ||
6436                         (!vnBased && (op1.lcl.lclNum == that->op1.lcl.lclNum)));
6437             }
6438         }
6439
6440         bool HasSameOp2(AssertionDsc* that, bool vnBased)
6441         {
6442             if (op2.kind != that->op2.kind)
6443             {
6444                 return false;
6445             }
6446             switch (op2.kind)
6447             {
6448                 case O2K_IND_CNS_INT:
6449                 case O2K_CONST_INT:
6450                     return ((op2.u1.iconVal == that->op2.u1.iconVal) && (op2.u1.iconFlags == that->op2.u1.iconFlags));
6451
6452                 case O2K_CONST_LONG:
6453                     return (op2.lconVal == that->op2.lconVal);
6454
6455                 case O2K_CONST_DOUBLE:
6456                     // exact match because of positive and negative zero.
6457                     return (memcmp(&op2.dconVal, &that->op2.dconVal, sizeof(double)) == 0);
6458
6459                 case O2K_LCLVAR_COPY:
6460                 case O2K_ARR_LEN:
6461                     return (op2.lcl.lclNum == that->op2.lcl.lclNum) &&
6462                            (!vnBased || op2.lcl.ssaNum == that->op2.lcl.ssaNum);
6463
6464                 case O2K_SUBRANGE:
6465                     return ((op2.u2.loBound == that->op2.u2.loBound) && (op2.u2.hiBound == that->op2.u2.hiBound));
6466
6467                 case O2K_INVALID:
6468                     // we will return false
6469                     break;
6470
6471                 default:
6472                     assert(!"Unexpected value for op2.kind in AssertionDsc.");
6473                     break;
6474             }
6475             return false;
6476         }
6477
6478         bool Complementary(AssertionDsc* that, bool vnBased)
6479         {
6480             return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that, vnBased) &&
6481                    HasSameOp2(that, vnBased);
6482         }
6483
6484         bool Equals(AssertionDsc* that, bool vnBased)
6485         {
6486             if (assertionKind != that->assertionKind)
6487             {
6488                 return false;
6489             }
6490             else if (assertionKind == OAK_NO_THROW)
6491             {
6492                 assert(op2.kind == O2K_INVALID);
6493                 return HasSameOp1(that, vnBased);
6494             }
6495             else
6496             {
6497                 return HasSameOp1(that, vnBased) && HasSameOp2(that, vnBased);
6498             }
6499         }
6500     };
6501
6502 protected:
6503     static fgWalkPreFn optAddCopiesCallback;
6504     static fgWalkPreFn optVNAssertionPropCurStmtVisitor;
6505     unsigned           optAddCopyLclNum;
6506     GenTree*           optAddCopyAsgnNode;
6507
6508     bool optLocalAssertionProp;  // indicates that we are performing local assertion prop
6509     bool optAssertionPropagated; // set to true if we modified the trees
6510     bool optAssertionPropagatedCurrentStmt;
6511 #ifdef DEBUG
6512     GenTree* optAssertionPropCurrentTree;
6513 #endif
6514     AssertionIndex*            optComplementaryAssertionMap;
6515     JitExpandArray<ASSERT_TP>* optAssertionDep; // table that holds dependent assertions (assertions
6516                                                 // using the value of a local var) for each local var
6517     AssertionDsc*  optAssertionTabPrivate;      // table that holds info about value assignments
6518     AssertionIndex optAssertionCount;           // total number of assertions in the assertion table
6519     AssertionIndex optMaxAssertionCount;
6520
6521 public:
6522     void optVnNonNullPropCurStmt(BasicBlock* block, GenTree* stmt, GenTree* tree);
6523     fgWalkResult optVNConstantPropCurStmt(BasicBlock* block, GenTree* stmt, GenTree* tree);
6524     GenTree* optVNConstantPropOnJTrue(BasicBlock* block, GenTree* stmt, GenTree* test);
6525     GenTree* optVNConstantPropOnTree(BasicBlock* block, GenTree* stmt, GenTree* tree);
6526     GenTree* optPrepareTreeForReplacement(GenTree* extractTree, GenTree* replaceTree);
6527
6528     AssertionIndex GetAssertionCount()
6529     {
6530         return optAssertionCount;
6531     }
6532     ASSERT_TP* bbJtrueAssertionOut;
6533     typedef JitHashTable<ValueNum, JitSmallPrimitiveKeyFuncs<ValueNum>, ASSERT_TP> ValueNumToAssertsMap;
6534     ValueNumToAssertsMap* optValueNumToAsserts;
6535
6536     // Assertion prop helpers.
6537     ASSERT_TP& GetAssertionDep(unsigned lclNum);
6538     AssertionDsc* optGetAssertion(AssertionIndex assertIndex);
6539     void optAssertionInit(bool isLocalProp);
6540     void optAssertionTraitsInit(AssertionIndex assertionCount);
6541 #if LOCAL_ASSERTION_PROP
6542     void optAssertionReset(AssertionIndex limit);
6543     void optAssertionRemove(AssertionIndex index);
6544 #endif
6545
6546     // Assertion prop data flow functions.
6547     void     optAssertionPropMain();
6548     GenTree* optVNAssertionPropCurStmt(BasicBlock* block, GenTree* stmt);
6549     bool optIsTreeKnownIntValue(bool vnBased, GenTree* tree, ssize_t* pConstant, unsigned* pIconFlags);
6550     ASSERT_TP* optInitAssertionDataflowFlags();
6551     ASSERT_TP* optComputeAssertionGen();
6552
6553     // Assertion Gen functions.
6554     void optAssertionGen(GenTree* tree);
6555     AssertionIndex optAssertionGenPhiDefn(GenTree* tree);
6556     AssertionInfo optCreateJTrueBoundsAssertion(GenTree* tree);
6557     AssertionInfo optAssertionGenJtrue(GenTree* tree);
6558     AssertionIndex optCreateJtrueAssertions(GenTree* op1, GenTree* op2, Compiler::optAssertionKind assertionKind);
6559     AssertionIndex optFindComplementary(AssertionIndex assertionIndex);
6560     void optMapComplementary(AssertionIndex assertionIndex, AssertionIndex index);
6561
6562     // Assertion creation functions.
6563     AssertionIndex optCreateAssertion(GenTree* op1, GenTree* op2, optAssertionKind assertionKind);
6564     AssertionIndex optCreateAssertion(GenTree*         op1,
6565                                       GenTree*         op2,
6566                                       optAssertionKind assertionKind,
6567                                       AssertionDsc*    assertion);
6568     void optCreateComplementaryAssertion(AssertionIndex assertionIndex, GenTree* op1, GenTree* op2);
6569
6570     bool optAssertionVnInvolvesNan(AssertionDsc* assertion);
6571     AssertionIndex optAddAssertion(AssertionDsc* assertion);
6572     void optAddVnAssertionMapping(ValueNum vn, AssertionIndex index);
6573 #ifdef DEBUG
6574     void optPrintVnAssertionMapping();
6575 #endif
6576     ASSERT_TP optGetVnMappedAssertions(ValueNum vn);
6577
6578     // Used for respective assertion propagations.
6579     AssertionIndex optAssertionIsSubrange(GenTree* tree, var_types toType, ASSERT_VALARG_TP assertions);
6580     AssertionIndex optAssertionIsSubtype(GenTree* tree, GenTree* methodTableArg, ASSERT_VALARG_TP assertions);
6581     AssertionIndex optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions);
6582     bool optAssertionIsNonNull(GenTree*         op,
6583                                ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased) DEBUGARG(AssertionIndex* pIndex));
6584
6585     // Used for Relop propagation.
6586     AssertionIndex optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP assertions, GenTree* op1, GenTree* op2);
6587     AssertionIndex optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_TP assertions, GenTree* op1);
6588     AssertionIndex optLocalAssertionIsEqualOrNotEqual(
6589         optOp1Kind op1Kind, unsigned lclNum, optOp2Kind op2Kind, ssize_t cnsVal, ASSERT_VALARG_TP assertions);
6590
6591     // Assertion prop for lcl var functions.
6592     bool optAssertionProp_LclVarTypeCheck(GenTree* tree, LclVarDsc* lclVarDsc, LclVarDsc* copyVarDsc);
6593     GenTree* optCopyAssertionProp(AssertionDsc* curAssertion,
6594                                   GenTree*      tree,
6595                                   GenTree* stmt DEBUGARG(AssertionIndex index));
6596     GenTree* optConstantAssertionProp(AssertionDsc* curAssertion,
6597                                       GenTree*      tree,
6598                                       GenTree* stmt DEBUGARG(AssertionIndex index));
6599
6600     // Assertion propagation functions.
6601     GenTree* optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6602     GenTree* optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6603     GenTree* optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6604     GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6605     GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, GenTree* stmt);
6606     GenTree* optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6607     GenTree* optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6608     GenTree* optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6609     GenTree* optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6610     GenTree* optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt);
6611     GenTree* optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTree* stmt);
6612     GenTree* optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, GenTree* stmt);
6613
6614     // Implied assertion functions.
6615     void optImpliedAssertions(AssertionIndex assertionIndex, ASSERT_TP& activeAssertions);
6616     void optImpliedByTypeOfAssertions(ASSERT_TP& activeAssertions);
6617     void optImpliedByCopyAssertion(AssertionDsc* copyAssertion, AssertionDsc* depAssertion, ASSERT_TP& result);
6618     void optImpliedByConstAssertion(AssertionDsc* curAssertion, ASSERT_TP& result);
6619
6620 #ifdef DEBUG
6621     void optPrintAssertion(AssertionDsc* newAssertion, AssertionIndex assertionIndex = 0);
6622     void optDebugCheckAssertion(AssertionDsc* assertion);
6623     void optDebugCheckAssertions(AssertionIndex AssertionIndex);
6624 #endif
6625     void optAddCopies();
6626 #endif // ASSERTION_PROP
6627
6628     /**************************************************************************
6629      *                          Range checks
6630      *************************************************************************/
6631
6632 public:
6633     struct LoopCloneVisitorInfo
6634     {
6635         LoopCloneContext* context;
6636         unsigned          loopNum;
6637         GenTree*          stmt;
6638         LoopCloneVisitorInfo(LoopCloneContext* context, unsigned loopNum, GenTree* stmt)
6639             : context(context), loopNum(loopNum), stmt(nullptr)
6640         {
6641         }
6642     };
6643
6644     bool optIsStackLocalInvariant(unsigned loopNum, unsigned lclNum);
6645     bool optExtractArrIndex(GenTree* tree, ArrIndex* result, unsigned lhsNum);
6646     bool optReconstructArrIndex(GenTree* tree, ArrIndex* result, unsigned lhsNum);
6647     bool optIdentifyLoopOptInfo(unsigned loopNum, LoopCloneContext* context);
6648     static fgWalkPreFn optCanOptimizeByLoopCloningVisitor;
6649     fgWalkResult optCanOptimizeByLoopCloning(GenTree* tree, LoopCloneVisitorInfo* info);
6650     void optObtainLoopCloningOpts(LoopCloneContext* context);
6651     bool optIsLoopClonable(unsigned loopInd);
6652
6653     bool optCanCloneLoops();
6654
6655 #ifdef DEBUG
6656     void optDebugLogLoopCloning(BasicBlock* block, GenTree* insertBefore);
6657 #endif
6658     void optPerformStaticOptimizations(unsigned loopNum, LoopCloneContext* context DEBUGARG(bool fastPath));
6659     bool optComputeDerefConditions(unsigned loopNum, LoopCloneContext* context);
6660     bool optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext* context);
6661     BasicBlock* optInsertLoopChoiceConditions(LoopCloneContext* context,
6662                                               unsigned          loopNum,
6663                                               BasicBlock*       head,
6664                                               BasicBlock*       slow);
6665
6666 protected:
6667     ssize_t optGetArrayRefScaleAndIndex(GenTree* mul, GenTree** pIndex DEBUGARG(bool bRngChk));
6668
6669     bool optReachWithoutCall(BasicBlock* srcBB, BasicBlock* dstBB);
6670
6671 protected:
6672     bool optLoopsMarked;
6673
6674     /*
6675     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6676     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6677     XX                                                                           XX
6678     XX                           RegAlloc                                        XX
6679     XX                                                                           XX
6680     XX  Does the register allocation and puts the remaining lclVars on the stack XX
6681     XX                                                                           XX
6682     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6683     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6684     */
6685
6686 public:
6687     regNumber raUpdateRegStateForArg(RegState* regState, LclVarDsc* argDsc);
6688
6689     void raMarkStkVars();
6690
6691 protected:
6692     // Some things are used by both LSRA and regpredict allocators.
6693
6694     FrameType rpFrameType;
6695     bool      rpMustCreateEBPCalled; // Set to true after we have called rpMustCreateEBPFrame once
6696
6697     bool rpMustCreateEBPFrame(INDEBUG(const char** wbReason));
6698
6699 private:
6700     Lowering*            m_pLowering;   // Lowering; needed to Lower IR that's added or modified after Lowering.
6701     LinearScanInterface* m_pLinearScan; // Linear Scan allocator
6702
6703     /* raIsVarargsStackArg is called by raMaskStkVars and by
6704        lvaSortByRefCount.  It identifies the special case
6705        where a varargs function has a parameter passed on the
6706        stack, other than the special varargs handle.  Such parameters
6707        require special treatment, because they cannot be tracked
6708        by the GC (their offsets in the stack are not known
6709        at compile time).
6710     */
6711
6712     bool raIsVarargsStackArg(unsigned lclNum)
6713     {
6714 #ifdef _TARGET_X86_
6715
6716         LclVarDsc* varDsc = &lvaTable[lclNum];
6717
6718         assert(varDsc->lvIsParam);
6719
6720         return (info.compIsVarArgs && !varDsc->lvIsRegArg && (lclNum != lvaVarargsHandleArg));
6721
6722 #else // _TARGET_X86_
6723
6724         return false;
6725
6726 #endif // _TARGET_X86_
6727     }
6728
6729     /*
6730     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6731     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6732     XX                                                                           XX
6733     XX                           EEInterface                                     XX
6734     XX                                                                           XX
6735     XX   Get to the class and method info from the Execution Engine given        XX
6736     XX   tokens for the class and method                                         XX
6737     XX                                                                           XX
6738     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6739     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6740     */
6741
6742 public:
6743     // Get handles
6744
6745     void eeGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
6746                        CORINFO_RESOLVED_TOKEN* pConstrainedToken,
6747                        CORINFO_CALLINFO_FLAGS  flags,
6748                        CORINFO_CALL_INFO*      pResult);
6749     inline CORINFO_CALLINFO_FLAGS addVerifyFlag(CORINFO_CALLINFO_FLAGS flags);
6750
6751     void eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
6752                         CORINFO_ACCESS_FLAGS    flags,
6753                         CORINFO_FIELD_INFO*     pResult);
6754
6755     // Get the flags
6756
6757     BOOL eeIsValueClass(CORINFO_CLASS_HANDLE clsHnd);
6758
6759 #if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) || defined(TRACK_LSRA_STATS)
6760
6761     bool IsSuperPMIException(unsigned code)
6762     {
6763         // Copied from NDP\clr\src\ToolBox\SuperPMI\SuperPMI-Shared\ErrorHandling.h
6764
6765         const unsigned EXCEPTIONCODE_DebugBreakorAV = 0xe0421000;
6766         const unsigned EXCEPTIONCODE_MC             = 0xe0422000;
6767         const unsigned EXCEPTIONCODE_LWM            = 0xe0423000;
6768         const unsigned EXCEPTIONCODE_SASM           = 0xe0424000;
6769         const unsigned EXCEPTIONCODE_SSYM           = 0xe0425000;
6770         const unsigned EXCEPTIONCODE_CALLUTILS      = 0xe0426000;
6771         const unsigned EXCEPTIONCODE_TYPEUTILS      = 0xe0427000;
6772         const unsigned EXCEPTIONCODE_ASSERT         = 0xe0440000;
6773
6774         switch (code)
6775         {
6776             case EXCEPTIONCODE_DebugBreakorAV:
6777             case EXCEPTIONCODE_MC:
6778             case EXCEPTIONCODE_LWM:
6779             case EXCEPTIONCODE_SASM:
6780             case EXCEPTIONCODE_SSYM:
6781             case EXCEPTIONCODE_CALLUTILS:
6782             case EXCEPTIONCODE_TYPEUTILS:
6783             case EXCEPTIONCODE_ASSERT:
6784                 return true;
6785             default:
6786                 return false;
6787         }
6788     }
6789
6790     const char* eeGetMethodName(CORINFO_METHOD_HANDLE hnd, const char** className);
6791     const char* eeGetMethodFullName(CORINFO_METHOD_HANDLE hnd);
6792
6793     bool eeIsNativeMethod(CORINFO_METHOD_HANDLE method);
6794     CORINFO_METHOD_HANDLE eeGetMethodHandleForNative(CORINFO_METHOD_HANDLE method);
6795 #endif
6796
6797     var_types eeGetArgType(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig);
6798     var_types eeGetArgType(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig, bool* isPinned);
6799     unsigned eeGetArgSize(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig);
6800
6801     // VOM info, method sigs
6802
6803     void eeGetSig(unsigned               sigTok,
6804                   CORINFO_MODULE_HANDLE  scope,
6805                   CORINFO_CONTEXT_HANDLE context,
6806                   CORINFO_SIG_INFO*      retSig);
6807
6808     void eeGetCallSiteSig(unsigned               sigTok,
6809                           CORINFO_MODULE_HANDLE  scope,
6810                           CORINFO_CONTEXT_HANDLE context,
6811                           CORINFO_SIG_INFO*      retSig);
6812
6813     void eeGetMethodSig(CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* retSig, CORINFO_CLASS_HANDLE owner = nullptr);
6814
6815     // Method entry-points, instrs
6816
6817     CORINFO_METHOD_HANDLE eeMarkNativeTarget(CORINFO_METHOD_HANDLE method);
6818
6819     CORINFO_EE_INFO eeInfo;
6820     bool            eeInfoInitialized;
6821
6822     CORINFO_EE_INFO* eeGetEEInfo();
6823
6824     // Gets the offset of a SDArray's first element
6825     unsigned eeGetArrayDataOffset(var_types type);
6826     // Gets the offset of a MDArray's first element
6827     unsigned eeGetMDArrayDataOffset(var_types type, unsigned rank);
6828
6829     GenTree* eeGetPInvokeCookie(CORINFO_SIG_INFO* szMetaSig);
6830
6831     // Returns the page size for the target machine as reported by the EE.
6832     target_size_t eeGetPageSize()
6833     {
6834         return (target_size_t)eeGetEEInfo()->osPageSize;
6835     }
6836
6837     // Returns the frame size at which we will generate a loop to probe the stack.
6838     target_size_t getVeryLargeFrameSize()
6839     {
6840 #ifdef _TARGET_ARM_
6841         // The looping probe code is 40 bytes, whereas the straight-line probing for
6842         // the (0x2000..0x3000) case is 44, so use looping for anything 0x2000 bytes
6843         // or greater, to generate smaller code.
6844         return 2 * eeGetPageSize();
6845 #else
6846         return 3 * eeGetPageSize();
6847 #endif
6848     }
6849
6850     //------------------------------------------------------------------------
6851     // VirtualStubParam: virtual stub dispatch extra parameter (slot address).
6852     //
6853     // It represents Abi and target specific registers for the parameter.
6854     //
6855     class VirtualStubParamInfo
6856     {
6857     public:
6858         VirtualStubParamInfo(bool isCoreRTABI)
6859         {
6860 #if defined(_TARGET_X86_)
6861             reg     = REG_EAX;
6862             regMask = RBM_EAX;
6863 #elif defined(_TARGET_AMD64_)
6864             if (isCoreRTABI)
6865             {
6866                 reg     = REG_R10;
6867                 regMask = RBM_R10;
6868             }
6869             else
6870             {
6871                 reg     = REG_R11;
6872                 regMask = RBM_R11;
6873             }
6874 #elif defined(_TARGET_ARM_)
6875             if (isCoreRTABI)
6876             {
6877                 reg     = REG_R12;
6878                 regMask = RBM_R12;
6879             }
6880             else
6881             {
6882                 reg     = REG_R4;
6883                 regMask = RBM_R4;
6884             }
6885 #elif defined(_TARGET_ARM64_)
6886             reg     = REG_R11;
6887             regMask = RBM_R11;
6888 #else
6889 #error Unsupported or unset target architecture
6890 #endif
6891         }
6892
6893         regNumber GetReg() const
6894         {
6895             return reg;
6896         }
6897
6898         _regMask_enum GetRegMask() const
6899         {
6900             return regMask;
6901         }
6902
6903     private:
6904         regNumber     reg;
6905         _regMask_enum regMask;
6906     };
6907
6908     VirtualStubParamInfo* virtualStubParamInfo;
6909
6910     bool IsTargetAbi(CORINFO_RUNTIME_ABI abi)
6911     {
6912         return eeGetEEInfo()->targetAbi == abi;
6913     }
6914
6915     bool generateCFIUnwindCodes()
6916     {
6917 #if defined(_TARGET_UNIX_)
6918         return IsTargetAbi(CORINFO_CORERT_ABI);
6919 #else
6920         return false;
6921 #endif
6922     }
6923
6924     // Debugging support - Line number info
6925
6926     void eeGetStmtOffsets();
6927
6928     unsigned eeBoundariesCount;
6929
6930     struct boundariesDsc
6931     {
6932         UNATIVE_OFFSET nativeIP;
6933         IL_OFFSET      ilOffset;
6934         unsigned       sourceReason;
6935     } * eeBoundaries; // Boundaries to report to EE
6936     void eeSetLIcount(unsigned count);
6937     void eeSetLIinfo(unsigned which, UNATIVE_OFFSET offs, unsigned srcIP, bool stkEmpty, bool callInstruction);
6938     void eeSetLIdone();
6939
6940 #ifdef DEBUG
6941     static void eeDispILOffs(IL_OFFSET offs);
6942     static void eeDispLineInfo(const boundariesDsc* line);
6943     void eeDispLineInfos();
6944 #endif // DEBUG
6945
6946     // Debugging support - Local var info
6947
6948     void eeGetVars();
6949
6950     unsigned eeVarsCount;
6951
6952     struct VarResultInfo
6953     {
6954         UNATIVE_OFFSET             startOffset;
6955         UNATIVE_OFFSET             endOffset;
6956         DWORD                      varNumber;
6957         CodeGenInterface::siVarLoc loc;
6958     } * eeVars;
6959     void eeSetLVcount(unsigned count);
6960     void eeSetLVinfo(unsigned                          which,
6961                      UNATIVE_OFFSET                    startOffs,
6962                      UNATIVE_OFFSET                    length,
6963                      unsigned                          varNum,
6964                      unsigned                          LVnum,
6965                      VarName                           namex,
6966                      bool                              avail,
6967                      const CodeGenInterface::siVarLoc* loc);
6968     void eeSetLVdone();
6969
6970 #ifdef DEBUG
6971     void eeDispVar(ICorDebugInfo::NativeVarInfo* var);
6972     void eeDispVars(CORINFO_METHOD_HANDLE ftn, ULONG32 cVars, ICorDebugInfo::NativeVarInfo* vars);
6973 #endif // DEBUG
6974
6975     // ICorJitInfo wrappers
6976
6977     void eeReserveUnwindInfo(BOOL isFunclet, BOOL isColdCode, ULONG unwindSize);
6978
6979     void eeAllocUnwindInfo(BYTE*          pHotCode,
6980                            BYTE*          pColdCode,
6981                            ULONG          startOffset,
6982                            ULONG          endOffset,
6983                            ULONG          unwindSize,
6984                            BYTE*          pUnwindBlock,
6985                            CorJitFuncKind funcKind);
6986
6987     void eeSetEHcount(unsigned cEH);
6988
6989     void eeSetEHinfo(unsigned EHnumber, const CORINFO_EH_CLAUSE* clause);
6990
6991     WORD eeGetRelocTypeHint(void* target);
6992
6993     // ICorStaticInfo wrapper functions
6994
6995     bool eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken);
6996
6997 #if defined(UNIX_AMD64_ABI)
6998 #ifdef DEBUG
6999     static void dumpSystemVClassificationType(SystemVClassificationType ct);
7000 #endif // DEBUG
7001
7002     void eeGetSystemVAmd64PassStructInRegisterDescriptor(
7003         /*IN*/ CORINFO_CLASS_HANDLE                                  structHnd,
7004         /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr);
7005 #endif // UNIX_AMD64_ABI
7006
7007     template <typename ParamType>
7008     bool eeRunWithErrorTrap(void (*function)(ParamType*), ParamType* param)
7009     {
7010         return eeRunWithErrorTrapImp(reinterpret_cast<void (*)(void*)>(function), reinterpret_cast<void*>(param));
7011     }
7012
7013     bool eeRunWithErrorTrapImp(void (*function)(void*), void* param);
7014
7015     // Utility functions
7016
7017     const char* eeGetFieldName(CORINFO_FIELD_HANDLE fieldHnd, const char** classNamePtr = nullptr);
7018
7019 #if defined(DEBUG)
7020     const wchar_t* eeGetCPString(size_t stringHandle);
7021 #endif
7022
7023     const char* eeGetClassName(CORINFO_CLASS_HANDLE clsHnd);
7024
7025     static CORINFO_METHOD_HANDLE eeFindHelper(unsigned helper);
7026     static CorInfoHelpFunc eeGetHelperNum(CORINFO_METHOD_HANDLE method);
7027
7028     static fgWalkPreFn CountSharedStaticHelper;
7029     static bool IsSharedStaticHelper(GenTree* tree);
7030     static bool IsTreeAlwaysHoistable(GenTree* tree);
7031     static bool IsGcSafePoint(GenTree* tree);
7032
7033     static CORINFO_FIELD_HANDLE eeFindJitDataOffs(unsigned jitDataOffs);
7034     // returns true/false if 'field' is a Jit Data offset
7035     static bool eeIsJitDataOffs(CORINFO_FIELD_HANDLE field);
7036     // returns a number < 0 if 'field' is not a Jit Data offset, otherwise the data offset (limited to 2GB)
7037     static int eeGetJitDataOffs(CORINFO_FIELD_HANDLE field);
7038
7039     /*****************************************************************************/
7040
7041     /*
7042     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7043     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7044     XX                                                                           XX
7045     XX                           CodeGenerator                                   XX
7046     XX                                                                           XX
7047     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7048     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7049     */
7050
7051 public:
7052     CodeGenInterface* codeGen;
7053
7054     //  The following holds information about instr offsets in terms of generated code.
7055
7056     struct IPmappingDsc
7057     {
7058         IPmappingDsc* ipmdNext;      // next line# record
7059         IL_OFFSETX    ipmdILoffsx;   // the instr offset
7060         emitLocation  ipmdNativeLoc; // the emitter location of the native code corresponding to the IL offset
7061         bool          ipmdIsLabel;   // Can this code be a branch label?
7062     };
7063
7064     // Record the instr offset mapping to the generated code
7065
7066     IPmappingDsc* genIPmappingList;
7067     IPmappingDsc* genIPmappingLast;
7068
7069     // Managed RetVal - A side hash table meant to record the mapping from a
7070     // GT_CALL node to its IL offset.  This info is used to emit sequence points
7071     // that can be used by debugger to determine the native offset at which the
7072     // managed RetVal will be available.
7073     //
7074     // In fact we can store IL offset in a GT_CALL node.  This was ruled out in
7075     // favor of a side table for two reasons: 1) We need IL offset for only those
7076     // GT_CALL nodes (created during importation) that correspond to an IL call and
7077     // whose return type is other than TYP_VOID. 2) GT_CALL node is a frequently used
7078     // structure and IL offset is needed only when generating debuggable code. Therefore
7079     // it is desirable to avoid memory size penalty in retail scenarios.
7080     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, IL_OFFSETX> CallSiteILOffsetTable;
7081     CallSiteILOffsetTable* genCallSite2ILOffsetMap;
7082
7083     unsigned    genReturnLocal; // Local number for the return value when applicable.
7084     BasicBlock* genReturnBB;    // jumped to when not optimizing for speed.
7085
7086     // The following properties are part of CodeGenContext.  Getters are provided here for
7087     // convenience and backward compatibility, but the properties can only be set by invoking
7088     // the setter on CodeGenContext directly.
7089
7090     __declspec(property(get = getEmitter)) emitter* genEmitter;
7091     emitter* getEmitter()
7092     {
7093         return codeGen->getEmitter();
7094     }
7095
7096     bool isFramePointerUsed() const
7097     {
7098         return codeGen->isFramePointerUsed();
7099     }
7100
7101     __declspec(property(get = getInterruptible, put = setInterruptible)) bool genInterruptible;
7102     bool getInterruptible()
7103     {
7104         return codeGen->genInterruptible;
7105     }
7106     void setInterruptible(bool value)
7107     {
7108         codeGen->setInterruptible(value);
7109     }
7110
7111 #ifdef _TARGET_ARMARCH_
7112     __declspec(property(get = getHasTailCalls, put = setHasTailCalls)) bool hasTailCalls;
7113     bool getHasTailCalls()
7114     {
7115         return codeGen->hasTailCalls;
7116     }
7117     void setHasTailCalls(bool value)
7118     {
7119         codeGen->setHasTailCalls(value);
7120     }
7121 #endif // _TARGET_ARMARCH_
7122
7123 #if DOUBLE_ALIGN
7124     const bool genDoubleAlign()
7125     {
7126         return codeGen->doDoubleAlign();
7127     }
7128     DWORD getCanDoubleAlign();
7129     bool shouldDoubleAlign(unsigned refCntStk,
7130                            unsigned refCntReg,
7131                            unsigned refCntWtdReg,
7132                            unsigned refCntStkParam,
7133                            unsigned refCntWtdStkDbl);
7134 #endif // DOUBLE_ALIGN
7135
7136     __declspec(property(get = getFullPtrRegMap, put = setFullPtrRegMap)) bool genFullPtrRegMap;
7137     bool getFullPtrRegMap()
7138     {
7139         return codeGen->genFullPtrRegMap;
7140     }
7141     void setFullPtrRegMap(bool value)
7142     {
7143         codeGen->setFullPtrRegMap(value);
7144     }
7145
7146 // Things that MAY belong either in CodeGen or CodeGenContext
7147
7148 #if FEATURE_EH_FUNCLETS
7149     FuncInfoDsc*   compFuncInfos;
7150     unsigned short compCurrFuncIdx;
7151     unsigned short compFuncInfoCount;
7152
7153     unsigned short compFuncCount()
7154     {
7155         assert(fgFuncletsCreated);
7156         return compFuncInfoCount;
7157     }
7158
7159 #else // !FEATURE_EH_FUNCLETS
7160
7161     // This is a no-op when there are no funclets!
7162     void genUpdateCurrentFunclet(BasicBlock* block)
7163     {
7164         return;
7165     }
7166
7167     FuncInfoDsc compFuncInfoRoot;
7168
7169     static const unsigned compCurrFuncIdx = 0;
7170
7171     unsigned short compFuncCount()
7172     {
7173         return 1;
7174     }
7175
7176 #endif // !FEATURE_EH_FUNCLETS
7177
7178     FuncInfoDsc* funCurrentFunc();
7179     void funSetCurrentFunc(unsigned funcIdx);
7180     FuncInfoDsc* funGetFunc(unsigned funcIdx);
7181     unsigned int funGetFuncIdx(BasicBlock* block);
7182
7183     // LIVENESS
7184
7185     VARSET_TP compCurLife;     // current live variables
7186     GenTree*  compCurLifeTree; // node after which compCurLife has been computed
7187
7188     template <bool ForCodeGen>
7189     void compChangeLife(VARSET_VALARG_TP newLife);
7190
7191     template <bool ForCodeGen>
7192     inline void compUpdateLife(VARSET_VALARG_TP newLife);
7193
7194     // Gets a register mask that represent the kill set for a helper call since
7195     // not all JIT Helper calls follow the standard ABI on the target architecture.
7196     regMaskTP compHelperCallKillSet(CorInfoHelpFunc helper);
7197
7198     // Gets a register mask that represent the kill set for a NoGC helper call.
7199     regMaskTP compNoGCHelperCallKillSet(CorInfoHelpFunc helper);
7200
7201 #ifdef _TARGET_ARM_
7202     // Requires that "varDsc" be a promoted struct local variable being passed as an argument, beginning at
7203     // "firstArgRegNum", which is assumed to have already been aligned to the register alignment restriction of the
7204     // struct type. Adds bits to "*pArgSkippedRegMask" for any argument registers *not* used in passing "varDsc" --
7205     // i.e., internal "holes" caused by internal alignment constraints.  For example, if the struct contained an int and
7206     // a double, and we at R0 (on ARM), then R1 would be skipped, and the bit for R1 would be added to the mask.
7207     void fgAddSkippedRegsInPromotedStructArg(LclVarDsc* varDsc, unsigned firstArgRegNum, regMaskTP* pArgSkippedRegMask);
7208 #endif // _TARGET_ARM_
7209
7210     // If "tree" is a indirection (GT_IND, or GT_OBJ) whose arg is an ADDR, whose arg is a LCL_VAR, return that LCL_VAR
7211     // node, else NULL.
7212     static GenTree* fgIsIndirOfAddrOfLocal(GenTree* tree);
7213
7214     // This map is indexed by GT_OBJ nodes that are address of promoted struct variables, which
7215     // have been annotated with the GTF_VAR_DEATH flag.  If such a node is *not* mapped in this
7216     // table, one may assume that all the (tracked) field vars die at this GT_OBJ.  Otherwise,
7217     // the node maps to a pointer to a VARSET_TP, containing set bits for each of the tracked field
7218     // vars of the promoted struct local that go dead at the given node (the set bits are the bits
7219     // for the tracked var indices of the field vars, as in a live var set).
7220     //
7221     // The map is allocated on demand so all map operations should use one of the following three
7222     // wrapper methods.
7223
7224     NodeToVarsetPtrMap* m_promotedStructDeathVars;
7225
7226     NodeToVarsetPtrMap* GetPromotedStructDeathVars()
7227     {
7228         if (m_promotedStructDeathVars == nullptr)
7229         {
7230             m_promotedStructDeathVars = new (getAllocator()) NodeToVarsetPtrMap(getAllocator());
7231         }
7232         return m_promotedStructDeathVars;
7233     }
7234
7235     void ClearPromotedStructDeathVars()
7236     {
7237         if (m_promotedStructDeathVars != nullptr)
7238         {
7239             m_promotedStructDeathVars->RemoveAll();
7240         }
7241     }
7242
7243     bool LookupPromotedStructDeathVars(GenTree* tree, VARSET_TP** bits)
7244     {
7245         bits        = nullptr;
7246         bool result = false;
7247
7248         if (m_promotedStructDeathVars != nullptr)
7249         {
7250             result = m_promotedStructDeathVars->Lookup(tree, bits);
7251         }
7252
7253         return result;
7254     }
7255
7256 /*
7257 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7258 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7259 XX                                                                           XX
7260 XX                           UnwindInfo                                      XX
7261 XX                                                                           XX
7262 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7263 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7264 */
7265
7266 #if !defined(__GNUC__)
7267 #pragma region Unwind information
7268 #endif
7269
7270 public:
7271     //
7272     // Infrastructure functions: start/stop/reserve/emit.
7273     //
7274
7275     void unwindBegProlog();
7276     void unwindEndProlog();
7277     void unwindBegEpilog();
7278     void unwindEndEpilog();
7279     void unwindReserve();
7280     void unwindEmit(void* pHotCode, void* pColdCode);
7281
7282     //
7283     // Specific unwind information functions: called by code generation to indicate a particular
7284     // prolog or epilog unwindable instruction has been generated.
7285     //
7286
7287     void unwindPush(regNumber reg);
7288     void unwindAllocStack(unsigned size);
7289     void unwindSetFrameReg(regNumber reg, unsigned offset);
7290     void unwindSaveReg(regNumber reg, unsigned offset);
7291
7292 #if defined(_TARGET_ARM_)
7293     void unwindPushMaskInt(regMaskTP mask);
7294     void unwindPushMaskFloat(regMaskTP mask);
7295     void unwindPopMaskInt(regMaskTP mask);
7296     void unwindPopMaskFloat(regMaskTP mask);
7297     void unwindBranch16();                    // The epilog terminates with a 16-bit branch (e.g., "bx lr")
7298     void unwindNop(unsigned codeSizeInBytes); // Generate unwind NOP code. 'codeSizeInBytes' is 2 or 4 bytes. Only
7299                                               // called via unwindPadding().
7300     void unwindPadding(); // Generate a sequence of unwind NOP codes representing instructions between the last
7301                           // instruction and the current location.
7302 #endif                    // _TARGET_ARM_
7303
7304 #if defined(_TARGET_ARM64_)
7305     void unwindNop();
7306     void unwindPadding(); // Generate a sequence of unwind NOP codes representing instructions between the last
7307                           // instruction and the current location.
7308     void unwindSaveReg(regNumber reg, int offset);                                // str reg, [sp, #offset]
7309     void unwindSaveRegPreindexed(regNumber reg, int offset);                      // str reg, [sp, #offset]!
7310     void unwindSaveRegPair(regNumber reg1, regNumber reg2, int offset);           // stp reg1, reg2, [sp, #offset]
7311     void unwindSaveRegPairPreindexed(regNumber reg1, regNumber reg2, int offset); // stp reg1, reg2, [sp, #offset]!
7312     void unwindSaveNext();                                                        // unwind code: save_next
7313     void unwindReturn(regNumber reg);                                             // ret lr
7314 #endif                                                                            // defined(_TARGET_ARM64_)
7315
7316     //
7317     // Private "helper" functions for the unwind implementation.
7318     //
7319
7320 private:
7321 #if FEATURE_EH_FUNCLETS
7322     void unwindGetFuncLocations(FuncInfoDsc*             func,
7323                                 bool                     getHotSectionData,
7324                                 /* OUT */ emitLocation** ppStartLoc,
7325                                 /* OUT */ emitLocation** ppEndLoc);
7326 #endif // FEATURE_EH_FUNCLETS
7327
7328     void unwindReserveFunc(FuncInfoDsc* func);
7329     void unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode);
7330
7331 #if defined(_TARGET_AMD64_) || (defined(_TARGET_X86_) && FEATURE_EH_FUNCLETS)
7332
7333     void unwindReserveFuncHelper(FuncInfoDsc* func, bool isHotCode);
7334     void unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode);
7335
7336 #endif // _TARGET_AMD64_ || (_TARGET_X86_ && FEATURE_EH_FUNCLETS)
7337
7338     UNATIVE_OFFSET unwindGetCurrentOffset(FuncInfoDsc* func);
7339
7340 #if defined(_TARGET_AMD64_)
7341
7342     void unwindBegPrologWindows();
7343     void unwindPushWindows(regNumber reg);
7344     void unwindAllocStackWindows(unsigned size);
7345     void unwindSetFrameRegWindows(regNumber reg, unsigned offset);
7346     void unwindSaveRegWindows(regNumber reg, unsigned offset);
7347
7348 #ifdef UNIX_AMD64_ABI
7349     void unwindSaveRegCFI(regNumber reg, unsigned offset);
7350 #endif // UNIX_AMD64_ABI
7351 #elif defined(_TARGET_ARM_)
7352
7353     void unwindPushPopMaskInt(regMaskTP mask, bool useOpsize16);
7354     void unwindPushPopMaskFloat(regMaskTP mask);
7355
7356 #endif // _TARGET_ARM_
7357
7358 #if defined(_TARGET_UNIX_)
7359     int mapRegNumToDwarfReg(regNumber reg);
7360     void createCfiCode(FuncInfoDsc* func, UCHAR codeOffset, UCHAR opcode, USHORT dwarfReg, INT offset = 0);
7361     void unwindPushPopCFI(regNumber reg);
7362     void unwindBegPrologCFI();
7363     void unwindPushPopMaskCFI(regMaskTP regMask, bool isFloat);
7364     void unwindAllocStackCFI(unsigned size);
7365     void unwindSetFrameRegCFI(regNumber reg, unsigned offset);
7366     void unwindEmitFuncCFI(FuncInfoDsc* func, void* pHotCode, void* pColdCode);
7367 #ifdef DEBUG
7368     void DumpCfiInfo(bool                  isHotCode,
7369                      UNATIVE_OFFSET        startOffset,
7370                      UNATIVE_OFFSET        endOffset,
7371                      DWORD                 cfiCodeBytes,
7372                      const CFI_CODE* const pCfiCode);
7373 #endif
7374
7375 #endif // _TARGET_UNIX_
7376
7377 #if !defined(__GNUC__)
7378 #pragma endregion // Note: region is NOT under !defined(__GNUC__)
7379 #endif
7380
7381     /*
7382     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7383     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7384     XX                                                                           XX
7385     XX                               SIMD                                        XX
7386     XX                                                                           XX
7387     XX   Info about SIMD types, methods and the SIMD assembly (i.e. the assembly XX
7388     XX   that contains the distinguished, well-known SIMD type definitions).     XX
7389     XX                                                                           XX
7390     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7391     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7392     */
7393
7394     // Get highest available level for SIMD codegen
7395     SIMDLevel getSIMDSupportLevel()
7396     {
7397 #if defined(_TARGET_XARCH_)
7398         if (compSupports(InstructionSet_AVX2))
7399         {
7400             return SIMD_AVX2_Supported;
7401         }
7402
7403         if (compSupports(InstructionSet_SSE42))
7404         {
7405             return SIMD_SSE4_Supported;
7406         }
7407
7408         // min bar is SSE2
7409         return SIMD_SSE2_Supported;
7410 #else
7411         assert(!"Available instruction set(s) for SIMD codegen is not defined for target arch");
7412         unreached();
7413         return SIMD_Not_Supported;
7414 #endif
7415     }
7416
7417 #ifdef FEATURE_SIMD
7418
7419     // Should we support SIMD intrinsics?
7420     bool featureSIMD;
7421
7422     // Have we identified any SIMD types?
7423     // This is currently used by struct promotion to avoid getting type information for a struct
7424     // field to see if it is a SIMD type, if we haven't seen any SIMD types or operations in
7425     // the method.
7426     bool _usesSIMDTypes;
7427     bool usesSIMDTypes()
7428     {
7429         return _usesSIMDTypes;
7430     }
7431     void setUsesSIMDTypes(bool value)
7432     {
7433         _usesSIMDTypes = value;
7434     }
7435
7436     // This is a temp lclVar allocated on the stack as TYP_SIMD.  It is used to implement intrinsics
7437     // that require indexed access to the individual fields of the vector, which is not well supported
7438     // by the hardware.  It is allocated when/if such situations are encountered during Lowering.
7439     unsigned lvaSIMDInitTempVarNum;
7440
7441     struct SIMDHandlesCache
7442     {
7443         // SIMD Types
7444         CORINFO_CLASS_HANDLE SIMDFloatHandle;
7445         CORINFO_CLASS_HANDLE SIMDDoubleHandle;
7446         CORINFO_CLASS_HANDLE SIMDIntHandle;
7447         CORINFO_CLASS_HANDLE SIMDUShortHandle;
7448         CORINFO_CLASS_HANDLE SIMDUByteHandle;
7449         CORINFO_CLASS_HANDLE SIMDShortHandle;
7450         CORINFO_CLASS_HANDLE SIMDByteHandle;
7451         CORINFO_CLASS_HANDLE SIMDLongHandle;
7452         CORINFO_CLASS_HANDLE SIMDUIntHandle;
7453         CORINFO_CLASS_HANDLE SIMDULongHandle;
7454         CORINFO_CLASS_HANDLE SIMDVector2Handle;
7455         CORINFO_CLASS_HANDLE SIMDVector3Handle;
7456         CORINFO_CLASS_HANDLE SIMDVector4Handle;
7457         CORINFO_CLASS_HANDLE SIMDVectorHandle;
7458
7459 #ifdef FEATURE_HW_INTRINSICS
7460 #if defined(_TARGET_ARM64_)
7461         CORINFO_CLASS_HANDLE Vector64FloatHandle;
7462         CORINFO_CLASS_HANDLE Vector64IntHandle;
7463         CORINFO_CLASS_HANDLE Vector64UShortHandle;
7464         CORINFO_CLASS_HANDLE Vector64UByteHandle;
7465         CORINFO_CLASS_HANDLE Vector64ShortHandle;
7466         CORINFO_CLASS_HANDLE Vector64ByteHandle;
7467         CORINFO_CLASS_HANDLE Vector64UIntHandle;
7468 #endif // defined(_TARGET_ARM64_)
7469         CORINFO_CLASS_HANDLE Vector128FloatHandle;
7470         CORINFO_CLASS_HANDLE Vector128DoubleHandle;
7471         CORINFO_CLASS_HANDLE Vector128IntHandle;
7472         CORINFO_CLASS_HANDLE Vector128UShortHandle;
7473         CORINFO_CLASS_HANDLE Vector128UByteHandle;
7474         CORINFO_CLASS_HANDLE Vector128ShortHandle;
7475         CORINFO_CLASS_HANDLE Vector128ByteHandle;
7476         CORINFO_CLASS_HANDLE Vector128LongHandle;
7477         CORINFO_CLASS_HANDLE Vector128UIntHandle;
7478         CORINFO_CLASS_HANDLE Vector128ULongHandle;
7479 #if defined(_TARGET_XARCH_)
7480         CORINFO_CLASS_HANDLE Vector256FloatHandle;
7481         CORINFO_CLASS_HANDLE Vector256DoubleHandle;
7482         CORINFO_CLASS_HANDLE Vector256IntHandle;
7483         CORINFO_CLASS_HANDLE Vector256UShortHandle;
7484         CORINFO_CLASS_HANDLE Vector256UByteHandle;
7485         CORINFO_CLASS_HANDLE Vector256ShortHandle;
7486         CORINFO_CLASS_HANDLE Vector256ByteHandle;
7487         CORINFO_CLASS_HANDLE Vector256LongHandle;
7488         CORINFO_CLASS_HANDLE Vector256UIntHandle;
7489         CORINFO_CLASS_HANDLE Vector256ULongHandle;
7490 #endif // defined(_TARGET_XARCH_)
7491 #endif // FEATURE_HW_INTRINSICS
7492
7493         SIMDHandlesCache()
7494         {
7495             memset(this, 0, sizeof(*this));
7496         }
7497     };
7498
7499     SIMDHandlesCache* m_simdHandleCache;
7500
7501     // Get an appropriate "zero" for the given type and class handle.
7502     GenTree* gtGetSIMDZero(var_types simdType, var_types baseType, CORINFO_CLASS_HANDLE simdHandle);
7503
7504     // Get the handle for a SIMD type.
7505     CORINFO_CLASS_HANDLE gtGetStructHandleForSIMD(var_types simdType, var_types simdBaseType)
7506     {
7507         if (m_simdHandleCache == nullptr)
7508         {
7509             // This may happen if the JIT generates SIMD node on its own, without importing them.
7510             // Otherwise getBaseTypeAndSizeOfSIMDType should have created the cache.
7511             return NO_CLASS_HANDLE;
7512         }
7513
7514         if (simdBaseType == TYP_FLOAT)
7515         {
7516             switch (simdType)
7517             {
7518                 case TYP_SIMD8:
7519                     return m_simdHandleCache->SIMDVector2Handle;
7520                 case TYP_SIMD12:
7521                     return m_simdHandleCache->SIMDVector3Handle;
7522                 case TYP_SIMD16:
7523                     if ((getSIMDVectorType() == TYP_SIMD32) ||
7524                         (m_simdHandleCache->SIMDVector4Handle != NO_CLASS_HANDLE))
7525                     {
7526                         return m_simdHandleCache->SIMDVector4Handle;
7527                     }
7528                     break;
7529                 case TYP_SIMD32:
7530                     break;
7531                 default:
7532                     unreached();
7533             }
7534         }
7535         assert(emitTypeSize(simdType) <= maxSIMDStructBytes());
7536         switch (simdBaseType)
7537         {
7538             case TYP_FLOAT:
7539                 return m_simdHandleCache->SIMDFloatHandle;
7540             case TYP_DOUBLE:
7541                 return m_simdHandleCache->SIMDDoubleHandle;
7542             case TYP_INT:
7543                 return m_simdHandleCache->SIMDIntHandle;
7544             case TYP_USHORT:
7545                 return m_simdHandleCache->SIMDUShortHandle;
7546             case TYP_UBYTE:
7547                 return m_simdHandleCache->SIMDUByteHandle;
7548             case TYP_SHORT:
7549                 return m_simdHandleCache->SIMDShortHandle;
7550             case TYP_BYTE:
7551                 return m_simdHandleCache->SIMDByteHandle;
7552             case TYP_LONG:
7553                 return m_simdHandleCache->SIMDLongHandle;
7554             case TYP_UINT:
7555                 return m_simdHandleCache->SIMDUIntHandle;
7556             case TYP_ULONG:
7557                 return m_simdHandleCache->SIMDULongHandle;
7558             default:
7559                 assert(!"Didn't find a class handle for simdType");
7560         }
7561         return NO_CLASS_HANDLE;
7562     }
7563
7564     // Returns true if this is a SIMD type that should be considered an opaque
7565     // vector type (i.e. do not analyze or promote its fields).
7566     // Note that all but the fixed vector types are opaque, even though they may
7567     // actually be declared as having fields.
7568     bool isOpaqueSIMDType(CORINFO_CLASS_HANDLE structHandle)
7569     {
7570         return ((m_simdHandleCache != nullptr) && (structHandle != m_simdHandleCache->SIMDVector2Handle) &&
7571                 (structHandle != m_simdHandleCache->SIMDVector3Handle) &&
7572                 (structHandle != m_simdHandleCache->SIMDVector4Handle));
7573     }
7574
7575     // Returns true if the tree corresponds to a TYP_SIMD lcl var.
7576     // Note that both SIMD vector args and locals are mared as lvSIMDType = true, but
7577     // type of an arg node is TYP_BYREF and a local node is TYP_SIMD or TYP_STRUCT.
7578     bool isSIMDTypeLocal(GenTree* tree)
7579     {
7580         return tree->OperIsLocal() && lvaTable[tree->AsLclVarCommon()->gtLclNum].lvSIMDType;
7581     }
7582
7583     // Returns true if the lclVar is an opaque SIMD type.
7584     bool isOpaqueSIMDLclVar(LclVarDsc* varDsc)
7585     {
7586         if (!varDsc->lvSIMDType)
7587         {
7588             return false;
7589         }
7590         return isOpaqueSIMDType(varDsc->lvVerTypeInfo.GetClassHandle());
7591     }
7592
7593     // Returns true if the type of the tree is a byref of TYP_SIMD
7594     bool isAddrOfSIMDType(GenTree* tree)
7595     {
7596         if (tree->TypeGet() == TYP_BYREF || tree->TypeGet() == TYP_I_IMPL)
7597         {
7598             switch (tree->OperGet())
7599             {
7600                 case GT_ADDR:
7601                     return varTypeIsSIMD(tree->gtGetOp1());
7602
7603                 case GT_LCL_VAR_ADDR:
7604                     return lvaTable[tree->AsLclVarCommon()->gtLclNum].lvSIMDType;
7605
7606                 default:
7607                     return isSIMDTypeLocal(tree);
7608             }
7609         }
7610
7611         return false;
7612     }
7613
7614     static bool isRelOpSIMDIntrinsic(SIMDIntrinsicID intrinsicId)
7615     {
7616         return (intrinsicId == SIMDIntrinsicEqual || intrinsicId == SIMDIntrinsicLessThan ||
7617                 intrinsicId == SIMDIntrinsicLessThanOrEqual || intrinsicId == SIMDIntrinsicGreaterThan ||
7618                 intrinsicId == SIMDIntrinsicGreaterThanOrEqual);
7619     }
7620
7621     // Returns base type of a TYP_SIMD local.
7622     // Returns TYP_UNKNOWN if the local is not TYP_SIMD.
7623     var_types getBaseTypeOfSIMDLocal(GenTree* tree)
7624     {
7625         if (isSIMDTypeLocal(tree))
7626         {
7627             return lvaTable[tree->AsLclVarCommon()->gtLclNum].lvBaseType;
7628         }
7629
7630         return TYP_UNKNOWN;
7631     }
7632
7633     bool isSIMDClass(CORINFO_CLASS_HANDLE clsHnd)
7634     {
7635         return info.compCompHnd->isInSIMDModule(clsHnd);
7636     }
7637
7638     bool isIntrinsicType(CORINFO_CLASS_HANDLE clsHnd)
7639     {
7640         return (info.compCompHnd->getClassAttribs(clsHnd) & CORINFO_FLG_INTRINSIC_TYPE) != 0;
7641     }
7642
7643     const char* getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName)
7644     {
7645         return info.compCompHnd->getClassNameFromMetadata(cls, namespaceName);
7646     }
7647
7648     CORINFO_CLASS_HANDLE getTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index)
7649     {
7650         return info.compCompHnd->getTypeInstantiationArgument(cls, index);
7651     }
7652
7653     bool isSIMDClass(typeInfo* pTypeInfo)
7654     {
7655         return pTypeInfo->IsStruct() && isSIMDClass(pTypeInfo->GetClassHandleForValueClass());
7656     }
7657
7658     bool isHWSIMDClass(CORINFO_CLASS_HANDLE clsHnd)
7659     {
7660 #ifdef FEATURE_HW_INTRINSICS
7661         if (isIntrinsicType(clsHnd))
7662         {
7663             const char* namespaceName = nullptr;
7664             (void)getClassNameFromMetadata(clsHnd, &namespaceName);
7665             return strcmp(namespaceName, "System.Runtime.Intrinsics") == 0;
7666         }
7667 #endif // FEATURE_HW_INTRINSICS
7668         return false;
7669     }
7670
7671     bool isHWSIMDClass(typeInfo* pTypeInfo)
7672     {
7673 #ifdef FEATURE_HW_INTRINSICS
7674         return pTypeInfo->IsStruct() && isHWSIMDClass(pTypeInfo->GetClassHandleForValueClass());
7675 #else
7676         return false;
7677 #endif
7678     }
7679
7680     bool isSIMDorHWSIMDClass(CORINFO_CLASS_HANDLE clsHnd)
7681     {
7682         return isSIMDClass(clsHnd) || isHWSIMDClass(clsHnd);
7683     }
7684
7685     bool isSIMDorHWSIMDClass(typeInfo* pTypeInfo)
7686     {
7687         return isSIMDClass(pTypeInfo) || isHWSIMDClass(pTypeInfo);
7688     }
7689
7690     // Get the base (element) type and size in bytes for a SIMD type. Returns TYP_UNKNOWN
7691     // if it is not a SIMD type or is an unsupported base type.
7692     var_types getBaseTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd, unsigned* sizeBytes = nullptr);
7693
7694     var_types getBaseTypeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd)
7695     {
7696         return getBaseTypeAndSizeOfSIMDType(typeHnd, nullptr);
7697     }
7698
7699     // Get SIMD Intrinsic info given the method handle.
7700     // Also sets typeHnd, argCount, baseType and sizeBytes out params.
7701     const SIMDIntrinsicInfo* getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* typeHnd,
7702                                                   CORINFO_METHOD_HANDLE methodHnd,
7703                                                   CORINFO_SIG_INFO*     sig,
7704                                                   bool                  isNewObj,
7705                                                   unsigned*             argCount,
7706                                                   var_types*            baseType,
7707                                                   unsigned*             sizeBytes);
7708
7709     // Pops and returns GenTree node from importers type stack.
7710     // Normalizes TYP_STRUCT value in case of GT_CALL, GT_RET_EXPR and arg nodes.
7711     GenTree* impSIMDPopStack(var_types type, bool expectAddr = false, CORINFO_CLASS_HANDLE structType = nullptr);
7712
7713     // Create a GT_SIMD tree for a Get property of SIMD vector with a fixed index.
7714     GenTreeSIMD* impSIMDGetFixed(var_types simdType, var_types baseType, unsigned simdSize, int index);
7715
7716     // Creates a GT_SIMD tree for Select operation
7717     GenTree* impSIMDSelect(CORINFO_CLASS_HANDLE typeHnd,
7718                            var_types            baseType,
7719                            unsigned             simdVectorSize,
7720                            GenTree*             op1,
7721                            GenTree*             op2,
7722                            GenTree*             op3);
7723
7724     // Creates a GT_SIMD tree for Min/Max operation
7725     GenTree* impSIMDMinMax(SIMDIntrinsicID      intrinsicId,
7726                            CORINFO_CLASS_HANDLE typeHnd,
7727                            var_types            baseType,
7728                            unsigned             simdVectorSize,
7729                            GenTree*             op1,
7730                            GenTree*             op2);
7731
7732     // Transforms operands and returns the SIMD intrinsic to be applied on
7733     // transformed operands to obtain given relop result.
7734     SIMDIntrinsicID impSIMDRelOp(SIMDIntrinsicID      relOpIntrinsicId,
7735                                  CORINFO_CLASS_HANDLE typeHnd,
7736                                  unsigned             simdVectorSize,
7737                                  var_types*           baseType,
7738                                  GenTree**            op1,
7739                                  GenTree**            op2);
7740
7741     // Creates a GT_SIMD tree for Abs intrinsic.
7742     GenTree* impSIMDAbs(CORINFO_CLASS_HANDLE typeHnd, var_types baseType, unsigned simdVectorSize, GenTree* op1);
7743
7744 #if defined(_TARGET_XARCH_)
7745
7746     // Transforms operands and returns the SIMD intrinsic to be applied on
7747     // transformed operands to obtain == comparison result.
7748     SIMDIntrinsicID impSIMDLongRelOpEqual(CORINFO_CLASS_HANDLE typeHnd,
7749                                           unsigned             simdVectorSize,
7750                                           GenTree**            op1,
7751                                           GenTree**            op2);
7752
7753     // Transforms operands and returns the SIMD intrinsic to be applied on
7754     // transformed operands to obtain > comparison result.
7755     SIMDIntrinsicID impSIMDLongRelOpGreaterThan(CORINFO_CLASS_HANDLE typeHnd,
7756                                                 unsigned             simdVectorSize,
7757                                                 GenTree**            op1,
7758                                                 GenTree**            op2);
7759
7760     // Transforms operands and returns the SIMD intrinsic to be applied on
7761     // transformed operands to obtain >= comparison result.
7762     SIMDIntrinsicID impSIMDLongRelOpGreaterThanOrEqual(CORINFO_CLASS_HANDLE typeHnd,
7763                                                        unsigned             simdVectorSize,
7764                                                        GenTree**            op1,
7765                                                        GenTree**            op2);
7766
7767     // Transforms operands and returns the SIMD intrinsic to be applied on
7768     // transformed operands to obtain >= comparison result in case of int32
7769     // and small int base type vectors.
7770     SIMDIntrinsicID impSIMDIntegralRelOpGreaterThanOrEqual(
7771         CORINFO_CLASS_HANDLE typeHnd, unsigned simdVectorSize, var_types baseType, GenTree** op1, GenTree** op2);
7772
7773 #endif // defined(_TARGET_XARCH_)
7774
7775     void setLclRelatedToSIMDIntrinsic(GenTree* tree);
7776     bool areFieldsContiguous(GenTree* op1, GenTree* op2);
7777     bool areArrayElementsContiguous(GenTree* op1, GenTree* op2);
7778     bool areArgumentsContiguous(GenTree* op1, GenTree* op2);
7779     GenTree* createAddressNodeForSIMDInit(GenTree* tree, unsigned simdSize);
7780
7781     // check methodHnd to see if it is a SIMD method that is expanded as an intrinsic in the JIT.
7782     GenTree* impSIMDIntrinsic(OPCODE                opcode,
7783                               GenTree*              newobjThis,
7784                               CORINFO_CLASS_HANDLE  clsHnd,
7785                               CORINFO_METHOD_HANDLE method,
7786                               CORINFO_SIG_INFO*     sig,
7787                               unsigned              methodFlags,
7788                               int                   memberRef);
7789
7790     GenTree* getOp1ForConstructor(OPCODE opcode, GenTree* newobjThis, CORINFO_CLASS_HANDLE clsHnd);
7791
7792     // Whether SIMD vector occupies part of SIMD register.
7793     // SSE2: vector2f/3f are considered sub register SIMD types.
7794     // AVX: vector2f, 3f and 4f are all considered sub register SIMD types.
7795     bool isSubRegisterSIMDType(CORINFO_CLASS_HANDLE typeHnd)
7796     {
7797         unsigned  sizeBytes = 0;
7798         var_types baseType  = getBaseTypeAndSizeOfSIMDType(typeHnd, &sizeBytes);
7799         return (baseType == TYP_FLOAT) && (sizeBytes < getSIMDVectorRegisterByteLength());
7800     }
7801
7802     bool isSubRegisterSIMDType(GenTreeSIMD* simdNode)
7803     {
7804         return (simdNode->gtSIMDSize < getSIMDVectorRegisterByteLength());
7805     }
7806
7807     // Get the type for the hardware SIMD vector.
7808     // This is the maximum SIMD type supported for this target.
7809     var_types getSIMDVectorType()
7810     {
7811 #if defined(_TARGET_XARCH_)
7812         if (getSIMDSupportLevel() == SIMD_AVX2_Supported)
7813         {
7814             return TYP_SIMD32;
7815         }
7816         else
7817         {
7818             assert(getSIMDSupportLevel() >= SIMD_SSE2_Supported);
7819             return TYP_SIMD16;
7820         }
7821 #elif defined(_TARGET_ARM64_)
7822         return TYP_SIMD16;
7823 #else
7824         assert(!"getSIMDVectorType() unimplemented on target arch");
7825         unreached();
7826 #endif
7827     }
7828
7829     // Get the size of the SIMD type in bytes
7830     int getSIMDTypeSizeInBytes(CORINFO_CLASS_HANDLE typeHnd)
7831     {
7832         unsigned sizeBytes = 0;
7833         (void)getBaseTypeAndSizeOfSIMDType(typeHnd, &sizeBytes);
7834         return sizeBytes;
7835     }
7836
7837     // Get the the number of elements of basetype of SIMD vector given by its size and baseType
7838     static int getSIMDVectorLength(unsigned simdSize, var_types baseType);
7839
7840     // Get the the number of elements of basetype of SIMD vector given by its type handle
7841     int getSIMDVectorLength(CORINFO_CLASS_HANDLE typeHnd);
7842
7843     // Get preferred alignment of SIMD type.
7844     int getSIMDTypeAlignment(var_types simdType);
7845
7846     // Get the number of bytes in a System.Numeric.Vector<T> for the current compilation.
7847     // Note - cannot be used for System.Runtime.Intrinsic
7848     unsigned getSIMDVectorRegisterByteLength()
7849     {
7850 #if defined(_TARGET_XARCH_)
7851         if (getSIMDSupportLevel() == SIMD_AVX2_Supported)
7852         {
7853             return YMM_REGSIZE_BYTES;
7854         }
7855         else
7856         {
7857             assert(getSIMDSupportLevel() >= SIMD_SSE2_Supported);
7858             return XMM_REGSIZE_BYTES;
7859         }
7860 #elif defined(_TARGET_ARM64_)
7861         return FP_REGSIZE_BYTES;
7862 #else
7863         assert(!"getSIMDVectorRegisterByteLength() unimplemented on target arch");
7864         unreached();
7865 #endif
7866     }
7867
7868     // The minimum and maximum possible number of bytes in a SIMD vector.
7869
7870     // maxSIMDStructBytes
7871     // The minimum SIMD size supported by System.Numeric.Vectors or System.Runtime.Intrinsic
7872     // SSE:  16-byte Vector<T> and Vector128<T>
7873     // AVX:  32-byte Vector256<T> (Vector<T> is 16-byte)
7874     // AVX2: 32-byte Vector<T> and Vector256<T>
7875     unsigned int maxSIMDStructBytes()
7876     {
7877 #if defined(FEATURE_HW_INTRINSICS) && defined(_TARGET_XARCH_)
7878         if (compSupports(InstructionSet_AVX))
7879         {
7880             return YMM_REGSIZE_BYTES;
7881         }
7882         else
7883         {
7884             assert(getSIMDSupportLevel() >= SIMD_SSE2_Supported);
7885             return XMM_REGSIZE_BYTES;
7886         }
7887 #else
7888         return getSIMDVectorRegisterByteLength();
7889 #endif
7890     }
7891     unsigned int minSIMDStructBytes()
7892     {
7893         return emitTypeSize(TYP_SIMD8);
7894     }
7895
7896     // Returns the codegen type for a given SIMD size.
7897     var_types getSIMDTypeForSize(unsigned size)
7898     {
7899         var_types simdType = TYP_UNDEF;
7900         if (size == 8)
7901         {
7902             simdType = TYP_SIMD8;
7903         }
7904         else if (size == 12)
7905         {
7906             simdType = TYP_SIMD12;
7907         }
7908         else if (size == 16)
7909         {
7910             simdType = TYP_SIMD16;
7911         }
7912         else if (size == 32)
7913         {
7914             simdType = TYP_SIMD32;
7915         }
7916         else
7917         {
7918             noway_assert(!"Unexpected size for SIMD type");
7919         }
7920         return simdType;
7921     }
7922
7923     unsigned getSIMDInitTempVarNum()
7924     {
7925         if (lvaSIMDInitTempVarNum == BAD_VAR_NUM)
7926         {
7927             lvaSIMDInitTempVarNum                  = lvaGrabTempWithImplicitUse(false DEBUGARG("SIMDInitTempVar"));
7928             lvaTable[lvaSIMDInitTempVarNum].lvType = getSIMDVectorType();
7929         }
7930         return lvaSIMDInitTempVarNum;
7931     }
7932
7933 #else  // !FEATURE_SIMD
7934     bool isOpaqueSIMDLclVar(LclVarDsc* varDsc)
7935     {
7936         return false;
7937     }
7938 #endif // FEATURE_SIMD
7939
7940 public:
7941     //------------------------------------------------------------------------
7942     // largestEnregisterableStruct: The size in bytes of the largest struct that can be enregistered.
7943     //
7944     // Notes: It is not guaranteed that the struct of this size or smaller WILL be a
7945     //        candidate for enregistration.
7946
7947     unsigned largestEnregisterableStructSize()
7948     {
7949 #ifdef FEATURE_SIMD
7950         unsigned vectorRegSize = getSIMDVectorRegisterByteLength();
7951         if (vectorRegSize > TARGET_POINTER_SIZE)
7952         {
7953             return vectorRegSize;
7954         }
7955         else
7956 #endif // FEATURE_SIMD
7957         {
7958             return TARGET_POINTER_SIZE;
7959         }
7960     }
7961
7962 private:
7963     // These routines need not be enclosed under FEATURE_SIMD since lvIsSIMDType()
7964     // is defined for both FEATURE_SIMD and !FEATURE_SIMD apropriately. The use
7965     // of this routines also avoids the need of #ifdef FEATURE_SIMD specific code.
7966
7967     // Is this var is of type simd struct?
7968     bool lclVarIsSIMDType(unsigned varNum)
7969     {
7970         LclVarDsc* varDsc = lvaTable + varNum;
7971         return varDsc->lvIsSIMDType();
7972     }
7973
7974     // Is this Local node a SIMD local?
7975     bool lclVarIsSIMDType(GenTreeLclVarCommon* lclVarTree)
7976     {
7977         return lclVarIsSIMDType(lclVarTree->gtLclNum);
7978     }
7979
7980     // Returns true if the TYP_SIMD locals on stack are aligned at their
7981     // preferred byte boundary specified by getSIMDTypeAlignment().
7982     //
7983     // As per the Intel manual, the preferred alignment for AVX vectors is 32-bytes. On Amd64,
7984     // RSP/EBP is aligned at 16-bytes, therefore to align SIMD types at 32-bytes we need even
7985     // RSP/EBP to be 32-byte aligned. It is not clear whether additional stack space used in
7986     // aligning stack is worth the benefit and for now will use 16-byte alignment for AVX
7987     // 256-bit vectors with unaligned load/stores to/from memory. On x86, the stack frame
7988     // is aligned to 4 bytes. We need to extend existing support for double (8-byte) alignment
7989     // to 16 or 32 byte alignment for frames with local SIMD vars, if that is determined to be
7990     // profitable.
7991     //
7992     bool isSIMDTypeLocalAligned(unsigned varNum)
7993     {
7994 #if defined(FEATURE_SIMD) && ALIGN_SIMD_TYPES
7995         if (lclVarIsSIMDType(varNum) && lvaTable[varNum].lvType != TYP_BYREF)
7996         {
7997             bool ebpBased;
7998             int  off = lvaFrameAddress(varNum, &ebpBased);
7999             // TODO-Cleanup: Can't this use the lvExactSize on the varDsc?
8000             int  alignment = getSIMDTypeAlignment(lvaTable[varNum].lvType);
8001             bool isAligned = (alignment <= STACK_ALIGN) && ((off % alignment) == 0);
8002             return isAligned;
8003         }
8004 #endif // FEATURE_SIMD
8005
8006         return false;
8007     }
8008
8009     bool compSupports(InstructionSet isa) const
8010     {
8011 #if defined(_TARGET_XARCH_) || defined(_TARGET_ARM64_)
8012         return (opts.compSupportsISA & (1ULL << isa)) != 0;
8013 #else
8014         return false;
8015 #endif
8016     }
8017
8018     bool canUseVexEncoding() const
8019     {
8020 #ifdef _TARGET_XARCH_
8021         return compSupports(InstructionSet_AVX);
8022 #else
8023         return false;
8024 #endif
8025     }
8026
8027     /*
8028     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8029     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8030     XX                                                                           XX
8031     XX                           Compiler                                        XX
8032     XX                                                                           XX
8033     XX   Generic info about the compilation and the method being compiled.       XX
8034     XX   It is responsible for driving the other phases.                         XX
8035     XX   It is also responsible for all the memory management.                   XX
8036     XX                                                                           XX
8037     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8038     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8039     */
8040
8041 public:
8042     Compiler* InlineeCompiler; // The Compiler instance for the inlinee
8043
8044     InlineResult* compInlineResult; // The result of importing the inlinee method.
8045
8046     bool compDoAggressiveInlining; // If true, mark every method as CORINFO_FLG_FORCEINLINE
8047     bool compJmpOpUsed;            // Does the method do a JMP
8048     bool compLongUsed;             // Does the method use TYP_LONG
8049     bool compFloatingPointUsed;    // Does the method use TYP_FLOAT or TYP_DOUBLE
8050     bool compTailCallUsed;         // Does the method do a tailcall
8051     bool compLocallocUsed;         // Does the method use localloc.
8052     bool compLocallocOptimized;    // Does the method have an optimized localloc
8053     bool compQmarkUsed;            // Does the method use GT_QMARK/GT_COLON
8054     bool compQmarkRationalized;    // Is it allowed to use a GT_QMARK/GT_COLON node.
8055     bool compUnsafeCastUsed;       // Does the method use LDIND/STIND to cast between scalar/refernce types
8056
8057 // NOTE: These values are only reliable after
8058 //       the importing is completely finished.
8059
8060 #ifdef DEBUG
8061     // State information - which phases have completed?
8062     // These are kept together for easy discoverability
8063
8064     bool    bRangeAllowStress;
8065     bool    compCodeGenDone;
8066     int64_t compNumStatementLinksTraversed; // # of links traversed while doing debug checks
8067     bool    fgNormalizeEHDone;              // Has the flowgraph EH normalization phase been done?
8068     size_t  compSizeEstimate;               // The estimated size of the method as per `gtSetEvalOrder`.
8069     size_t  compCycleEstimate;              // The estimated cycle count of the method as per `gtSetEvalOrder`
8070 #endif                                      // DEBUG
8071
8072     bool fgLocalVarLivenessDone; // Note that this one is used outside of debug.
8073     bool fgLocalVarLivenessChanged;
8074     bool compLSRADone;
8075     bool compRationalIRForm;
8076
8077     bool compUsesThrowHelper; // There is a call to a THOROW_HELPER for the compiled method.
8078
8079     bool compGeneratingProlog;
8080     bool compGeneratingEpilog;
8081     bool compNeedsGSSecurityCookie; // There is an unsafe buffer (or localloc) on the stack.
8082                                     // Insert cookie on frame and code to check the cookie, like VC++ -GS.
8083     bool compGSReorderStackLayout;  // There is an unsafe buffer on the stack, reorder locals and make local
8084     // copies of susceptible parameters to avoid buffer overrun attacks through locals/params
8085     bool getNeedsGSSecurityCookie() const
8086     {
8087         return compNeedsGSSecurityCookie;
8088     }
8089     void setNeedsGSSecurityCookie()
8090     {
8091         compNeedsGSSecurityCookie = true;
8092     }
8093
8094     FrameLayoutState lvaDoneFrameLayout; // The highest frame layout state that we've completed. During
8095                                          // frame layout calculations, this is the level we are currently
8096                                          // computing.
8097
8098     //---------------------------- JITing options -----------------------------
8099
8100     enum codeOptimize
8101     {
8102         BLENDED_CODE,
8103         SMALL_CODE,
8104         FAST_CODE,
8105
8106         COUNT_OPT_CODE
8107     };
8108
8109     struct Options
8110     {
8111         JitFlags* jitFlags;  // all flags passed from the EE
8112         unsigned  compFlags; // method attributes
8113
8114         codeOptimize compCodeOpt; // what type of code optimizations
8115
8116         bool compUseFCOMI;
8117         bool compUseCMOV;
8118
8119 #if defined(_TARGET_XARCH_) || defined(_TARGET_ARM64_)
8120         uint64_t compSupportsISA;
8121         void setSupportedISA(InstructionSet isa)
8122         {
8123             compSupportsISA |= 1ULL << isa;
8124         }
8125 #endif
8126
8127 // optimize maximally and/or favor speed over size?
8128
8129 #define DEFAULT_MIN_OPTS_CODE_SIZE 60000
8130 #define DEFAULT_MIN_OPTS_INSTR_COUNT 20000
8131 #define DEFAULT_MIN_OPTS_BB_COUNT 2000
8132 #define DEFAULT_MIN_OPTS_LV_NUM_COUNT 2000
8133 #define DEFAULT_MIN_OPTS_LV_REF_COUNT 8000
8134
8135 // Maximun number of locals before turning off the inlining
8136 #define MAX_LV_NUM_COUNT_FOR_INLINING 512
8137
8138         bool     compMinOpts;
8139         unsigned instrCount;
8140         unsigned lvRefCount;
8141         bool     compMinOptsIsSet;
8142 #ifdef DEBUG
8143         bool compMinOptsIsUsed;
8144
8145         bool MinOpts()
8146         {
8147             assert(compMinOptsIsSet);
8148             compMinOptsIsUsed = true;
8149             return compMinOpts;
8150         }
8151         bool IsMinOptsSet()
8152         {
8153             return compMinOptsIsSet;
8154         }
8155 #else  // !DEBUG
8156         bool MinOpts()
8157         {
8158             return compMinOpts;
8159         }
8160         bool IsMinOptsSet()
8161         {
8162             return compMinOptsIsSet;
8163         }
8164 #endif // !DEBUG
8165
8166         bool OptimizationDisabled()
8167         {
8168             return MinOpts() || compDbgCode;
8169         }
8170         bool OptimizationEnabled()
8171         {
8172             return !OptimizationDisabled();
8173         }
8174
8175         void SetMinOpts(bool val)
8176         {
8177             assert(!compMinOptsIsUsed);
8178             assert(!compMinOptsIsSet || (compMinOpts == val));
8179             compMinOpts      = val;
8180             compMinOptsIsSet = true;
8181         }
8182
8183         // true if the CLFLG_* for an optimization is set.
8184         bool OptEnabled(unsigned optFlag)
8185         {
8186             return !!(compFlags & optFlag);
8187         }
8188
8189 #ifdef FEATURE_READYTORUN_COMPILER
8190         bool IsReadyToRun()
8191         {
8192             return jitFlags->IsSet(JitFlags::JIT_FLAG_READYTORUN);
8193         }
8194 #else
8195         bool IsReadyToRun()
8196         {
8197             return false;
8198         }
8199 #endif
8200
8201         // true if we should use the PINVOKE_{BEGIN,END} helpers instead of generating
8202         // PInvoke transitions inline (e.g. when targeting CoreRT).
8203         bool ShouldUsePInvokeHelpers()
8204         {
8205             return jitFlags->IsSet(JitFlags::JIT_FLAG_USE_PINVOKE_HELPERS);
8206         }
8207
8208         // true if we should use insert the REVERSE_PINVOKE_{ENTER,EXIT} helpers in the method
8209         // prolog/epilog
8210         bool IsReversePInvoke()
8211         {
8212             return jitFlags->IsSet(JitFlags::JIT_FLAG_REVERSE_PINVOKE);
8213         }
8214
8215         // true if we must generate code compatible with JIT32 quirks
8216         bool IsJit32Compat()
8217         {
8218 #if defined(_TARGET_X86_)
8219             return jitFlags->IsSet(JitFlags::JIT_FLAG_DESKTOP_QUIRKS);
8220 #else
8221             return false;
8222 #endif
8223         }
8224
8225         // true if we must generate code compatible with Jit64 quirks
8226         bool IsJit64Compat()
8227         {
8228 #if defined(_TARGET_AMD64_)
8229             return jitFlags->IsSet(JitFlags::JIT_FLAG_DESKTOP_QUIRKS);
8230 #elif !defined(FEATURE_CORECLR)
8231             return true;
8232 #else
8233             return false;
8234 #endif
8235         }
8236
8237         bool compScopeInfo; // Generate the LocalVar info ?
8238         bool compDbgCode;   // Generate debugger-friendly code?
8239         bool compDbgInfo;   // Gather debugging info?
8240         bool compDbgEnC;
8241
8242 #ifdef PROFILING_SUPPORTED
8243         bool compNoPInvokeInlineCB;
8244 #else
8245         static const bool compNoPInvokeInlineCB;
8246 #endif
8247
8248 #ifdef DEBUG
8249         bool compGcChecks; // Check arguments and return values to ensure they are sane
8250 #endif
8251
8252 #if defined(DEBUG) && defined(_TARGET_XARCH_)
8253
8254         bool compStackCheckOnRet; // Check stack pointer on return to ensure it is correct.
8255
8256 #endif // defined(DEBUG) && defined(_TARGET_XARCH_)
8257
8258 #if defined(DEBUG) && defined(_TARGET_X86_)
8259
8260         bool compStackCheckOnCall; // Check stack pointer after call to ensure it is correct. Only for x86.
8261
8262 #endif // defined(DEBUG) && defined(_TARGET_X86_)
8263
8264         bool compNeedSecurityCheck; // This flag really means where or not a security object needs
8265                                     // to be allocated on the stack.
8266                                     // It will be set to true in the following cases:
8267                                     //   1. When the method being compiled has a declarative security
8268                                     //        (i.e. when CORINFO_FLG_NOSECURITYWRAP is reset for the current method).
8269                                     //        This is also the case when we inject a prolog and epilog in the method.
8270                                     //   (or)
8271                                     //   2. When the method being compiled has imperative security (i.e. the method
8272                                     //        calls into another method that has CORINFO_FLG_SECURITYCHECK flag set).
8273                                     //   (or)
8274                                     //   3. When opts.compDbgEnC is true. (See also Compiler::compCompile).
8275                                     //
8276         // When this flag is set, jit will allocate a gc-reference local variable (lvaSecurityObject),
8277         // which gets reported as a GC root to stackwalker.
8278         // (See also ICodeManager::GetAddrOfSecurityObject.)
8279
8280         bool compReloc; // Generate relocs for pointers in code, true for all ngen/prejit codegen
8281
8282 #ifdef DEBUG
8283 #if defined(_TARGET_XARCH_)
8284         bool compEnablePCRelAddr; // Whether absolute addr be encoded as PC-rel offset by RyuJIT where possible
8285 #endif
8286 #endif // DEBUG
8287
8288 #ifdef UNIX_AMD64_ABI
8289         // This flag  is indicating if there is a need to align the frame.
8290         // On AMD64-Windows, if there are calls, 4 slots for the outgoing ars are allocated, except for
8291         // FastTailCall. This slots makes the frame size non-zero, so alignment logic will be called.
8292         // On AMD64-Unix, there are no such slots. There is a possibility to have calls in the method with frame size of
8293         // 0. The frame alignment logic won't kick in. This flags takes care of the AMD64-Unix case by remembering that
8294         // there are calls and making sure the frame alignment logic is executed.
8295         bool compNeedToAlignFrame;
8296 #endif // UNIX_AMD64_ABI
8297
8298         bool compProcedureSplitting; // Separate cold code from hot code
8299
8300         bool genFPorder; // Preserve FP order (operations are non-commutative)
8301         bool genFPopt;   // Can we do frame-pointer-omission optimization?
8302         bool altJit;     // True if we are an altjit and are compiling this method
8303
8304 #ifdef OPT_CONFIG
8305         bool optRepeat; // Repeat optimizer phases k times
8306 #endif
8307
8308 #ifdef DEBUG
8309         bool compProcedureSplittingEH; // Separate cold code from hot code for functions with EH
8310         bool dspCode;                  // Display native code generated
8311         bool dspEHTable;               // Display the EH table reported to the VM
8312         bool dspDebugInfo;             // Display the Debug info reported to the VM
8313         bool dspInstrs;                // Display the IL instructions intermixed with the native code output
8314         bool dspEmit;                  // Display emitter output
8315         bool dspLines;                 // Display source-code lines intermixed with native code output
8316         bool dmpHex;                   // Display raw bytes in hex of native code output
8317         bool varNames;                 // Display variables names in native code output
8318         bool disAsm;                   // Display native code as it is generated
8319         bool disAsmSpilled;            // Display native code when any register spilling occurs
8320         bool disDiffable;              // Makes the Disassembly code 'diff-able'
8321         bool disAsm2;                  // Display native code after it is generated using external disassembler
8322         bool dspOrder;                 // Display names of each of the methods that we ngen/jit
8323         bool dspUnwind;                // Display the unwind info output
8324         bool dspDiffable;     // Makes the Jit Dump 'diff-able' (currently uses same COMPlus_* flag as disDiffable)
8325         bool compLongAddress; // Force using large pseudo instructions for long address
8326                               // (IF_LARGEJMP/IF_LARGEADR/IF_LARGLDC)
8327         bool dspGCtbls;       // Display the GC tables
8328 #endif
8329
8330 #ifdef LATE_DISASM
8331         bool doLateDisasm; // Run the late disassembler
8332 #endif                     // LATE_DISASM
8333
8334 #if DUMP_GC_TABLES && !defined(DEBUG) && defined(JIT32_GCENCODER)
8335 // Only the JIT32_GCENCODER implements GC dumping in non-DEBUG code.
8336 #pragma message("NOTE: this non-debug build has GC ptr table dumping always enabled!")
8337         static const bool dspGCtbls = true;
8338 #endif
8339
8340 #ifdef PROFILING_SUPPORTED
8341         // Whether to emit Enter/Leave/TailCall hooks using a dummy stub (DummyProfilerELTStub()).
8342         // This option helps make the JIT behave as if it is running under a profiler.
8343         bool compJitELTHookEnabled;
8344 #endif // PROFILING_SUPPORTED
8345
8346 #if FEATURE_TAILCALL_OPT
8347         // Whether opportunistic or implicit tail call optimization is enabled.
8348         bool compTailCallOpt;
8349         // Whether optimization of transforming a recursive tail call into a loop is enabled.
8350         bool compTailCallLoopOpt;
8351 #endif
8352
8353 #if defined(_TARGET_ARM64_)
8354         // Decision about whether to save FP/LR registers with callee-saved registers (see
8355         // COMPlus_JitSaveFpLrWithCalleSavedRegisters).
8356         int compJitSaveFpLrWithCalleeSavedRegisters;
8357 #endif // defined(_TARGET_ARM64_)
8358
8359 #ifdef ARM_SOFTFP
8360         static const bool compUseSoftFP = true;
8361 #else // !ARM_SOFTFP
8362         static const bool compUseSoftFP = false;
8363 #endif
8364
8365         GCPollType compGCPollType;
8366     } opts;
8367
8368 #ifdef ALT_JIT
8369     static bool                s_pAltJitExcludeAssembliesListInitialized;
8370     static AssemblyNamesList2* s_pAltJitExcludeAssembliesList;
8371 #endif // ALT_JIT
8372
8373 #ifdef DEBUG
8374     static bool                s_pJitDisasmIncludeAssembliesListInitialized;
8375     static AssemblyNamesList2* s_pJitDisasmIncludeAssembliesList;
8376
8377     static bool       s_pJitFunctionFileInitialized;
8378     static MethodSet* s_pJitMethodSet;
8379 #endif // DEBUG
8380
8381 #ifdef DEBUG
8382 // silence warning of cast to greater size. It is easier to silence than construct code the compiler is happy with, and
8383 // it is safe in this case
8384 #pragma warning(push)
8385 #pragma warning(disable : 4312)
8386
8387     template <typename T>
8388     T dspPtr(T p)
8389     {
8390         return (p == ZERO) ? ZERO : (opts.dspDiffable ? T(0xD1FFAB1E) : p);
8391     }
8392
8393     template <typename T>
8394     T dspOffset(T o)
8395     {
8396         return (o == ZERO) ? ZERO : (opts.dspDiffable ? T(0xD1FFAB1E) : o);
8397     }
8398 #pragma warning(pop)
8399
8400     static int dspTreeID(GenTree* tree)
8401     {
8402         return tree->gtTreeID;
8403     }
8404     static void printTreeID(GenTree* tree)
8405     {
8406         if (tree == nullptr)
8407         {
8408             printf("[------]");
8409         }
8410         else
8411         {
8412             printf("[%06d]", dspTreeID(tree));
8413         }
8414     }
8415
8416 #endif // DEBUG
8417
8418 // clang-format off
8419 #define STRESS_MODES                                                                            \
8420                                                                                                 \
8421         STRESS_MODE(NONE)                                                                       \
8422                                                                                                 \
8423         /* "Variations" stress areas which we try to mix up with each other. */                 \
8424         /* These should not be exhaustively used as they might */                               \
8425         /* hide/trivialize other areas */                                                       \
8426                                                                                                 \
8427         STRESS_MODE(REGS)                                                                       \
8428         STRESS_MODE(DBL_ALN)                                                                    \
8429         STRESS_MODE(LCL_FLDS)                                                                   \
8430         STRESS_MODE(UNROLL_LOOPS)                                                               \
8431         STRESS_MODE(MAKE_CSE)                                                                   \
8432         STRESS_MODE(LEGACY_INLINE)                                                              \
8433         STRESS_MODE(CLONE_EXPR)                                                                 \
8434         STRESS_MODE(USE_FCOMI)                                                                  \
8435         STRESS_MODE(USE_CMOV)                                                                   \
8436         STRESS_MODE(FOLD)                                                                       \
8437         STRESS_MODE(BB_PROFILE)                                                                 \
8438         STRESS_MODE(OPT_BOOLS_GC)                                                               \
8439         STRESS_MODE(REMORPH_TREES)                                                              \
8440         STRESS_MODE(64RSLT_MUL)                                                                 \
8441         STRESS_MODE(DO_WHILE_LOOPS)                                                             \
8442         STRESS_MODE(MIN_OPTS)                                                                   \
8443         STRESS_MODE(REVERSE_FLAG)     /* Will set GTF_REVERSE_OPS whenever we can */            \
8444         STRESS_MODE(REVERSE_COMMA)    /* Will reverse commas created  with gtNewCommaNode */    \
8445         STRESS_MODE(TAILCALL)         /* Will make the call as a tailcall whenever legal */     \
8446         STRESS_MODE(CATCH_ARG)        /* Will spill catch arg */                                \
8447         STRESS_MODE(UNSAFE_BUFFER_CHECKS)                                                       \
8448         STRESS_MODE(NULL_OBJECT_CHECK)                                                          \
8449         STRESS_MODE(PINVOKE_RESTORE_ESP)                                                        \
8450         STRESS_MODE(RANDOM_INLINE)                                                              \
8451         STRESS_MODE(SWITCH_CMP_BR_EXPANSION)                                                    \
8452         STRESS_MODE(GENERIC_VARN)                                                               \
8453                                                                                                 \
8454         /* After COUNT_VARN, stress level 2 does all of these all the time */                   \
8455                                                                                                 \
8456         STRESS_MODE(COUNT_VARN)                                                                 \
8457                                                                                                 \
8458         /* "Check" stress areas that can be exhaustively used if we */                          \
8459         /*  dont care about performance at all */                                               \
8460                                                                                                 \
8461         STRESS_MODE(FORCE_INLINE) /* Treat every method as AggressiveInlining */                \
8462         STRESS_MODE(CHK_FLOW_UPDATE)                                                            \
8463         STRESS_MODE(EMITTER)                                                                    \
8464         STRESS_MODE(CHK_REIMPORT)                                                               \
8465         STRESS_MODE(FLATFP)                                                                     \
8466         STRESS_MODE(GENERIC_CHECK)                                                              \
8467         STRESS_MODE(COUNT)
8468
8469     enum                compStressArea
8470     {
8471 #define STRESS_MODE(mode) STRESS_##mode,
8472         STRESS_MODES
8473 #undef STRESS_MODE
8474     };
8475 // clang-format on
8476
8477 #ifdef DEBUG
8478     static const LPCWSTR s_compStressModeNames[STRESS_COUNT + 1];
8479     BYTE                 compActiveStressModes[STRESS_COUNT];
8480 #endif // DEBUG
8481
8482 #define MAX_STRESS_WEIGHT 100
8483
8484     bool compStressCompile(compStressArea stressArea, unsigned weightPercentage);
8485
8486 #ifdef DEBUG
8487
8488     bool compInlineStress()
8489     {
8490         return compStressCompile(STRESS_LEGACY_INLINE, 50);
8491     }
8492
8493     bool compRandomInlineStress()
8494     {
8495         return compStressCompile(STRESS_RANDOM_INLINE, 50);
8496     }
8497
8498 #endif // DEBUG
8499
8500     bool compTailCallStress()
8501     {
8502 #ifdef DEBUG
8503         return (JitConfig.TailcallStress() != 0 || compStressCompile(STRESS_TAILCALL, 5));
8504 #else
8505         return false;
8506 #endif
8507     }
8508
8509     codeOptimize compCodeOpt()
8510     {
8511 #if 0
8512         // Switching between size & speed has measurable throughput impact
8513         // (3.5% on NGen mscorlib when measured). It used to be enabled for
8514         // DEBUG, but should generate identical code between CHK & RET builds,
8515         // so that's not acceptable.
8516         // TODO-Throughput: Figure out what to do about size vs. speed & throughput.
8517         //                  Investigate the cause of the throughput regression.
8518
8519         return opts.compCodeOpt;
8520 #else
8521         return BLENDED_CODE;
8522 #endif
8523     }
8524
8525     //--------------------- Info about the procedure --------------------------
8526
8527     struct Info
8528     {
8529         COMP_HANDLE           compCompHnd;
8530         CORINFO_MODULE_HANDLE compScopeHnd;
8531         CORINFO_CLASS_HANDLE  compClassHnd;
8532         CORINFO_METHOD_HANDLE compMethodHnd;
8533         CORINFO_METHOD_INFO*  compMethodInfo;
8534
8535         BOOL hasCircularClassConstraints;
8536         BOOL hasCircularMethodConstraints;
8537
8538 #if defined(DEBUG) || defined(LATE_DISASM)
8539         const char* compMethodName;
8540         const char* compClassName;
8541         const char* compFullName;
8542 #endif // defined(DEBUG) || defined(LATE_DISASM)
8543
8544 #if defined(DEBUG) || defined(INLINE_DATA)
8545         // Method hash is logcally const, but computed
8546         // on first demand.
8547         mutable unsigned compMethodHashPrivate;
8548         unsigned         compMethodHash() const;
8549 #endif // defined(DEBUG) || defined(INLINE_DATA)
8550
8551 #ifdef PSEUDORANDOM_NOP_INSERTION
8552         // things for pseudorandom nop insertion
8553         unsigned  compChecksum;
8554         CLRRandom compRNG;
8555 #endif
8556
8557         // The following holds the FLG_xxxx flags for the method we're compiling.
8558         unsigned compFlags;
8559
8560         // The following holds the class attributes for the method we're compiling.
8561         unsigned compClassAttr;
8562
8563         const BYTE*    compCode;
8564         IL_OFFSET      compILCodeSize;     // The IL code size
8565         IL_OFFSET      compILImportSize;   // Estimated amount of IL actually imported
8566         UNATIVE_OFFSET compNativeCodeSize; // The native code size, after instructions are issued. This
8567                                            // is less than (compTotalHotCodeSize + compTotalColdCodeSize) only if:
8568         // (1) the code is not hot/cold split, and we issued less code than we expected, or
8569         // (2) the code is hot/cold split, and we issued less code than we expected
8570         // in the cold section (the hot section will always be padded out to compTotalHotCodeSize).
8571
8572         bool compIsStatic : 1;         // Is the method static (no 'this' pointer)?
8573         bool compIsVarArgs : 1;        // Does the method have varargs parameters?
8574         bool compIsContextful : 1;     // contextful method
8575         bool compInitMem : 1;          // Is the CORINFO_OPT_INIT_LOCALS bit set in the method info options?
8576         bool compUnwrapContextful : 1; // JIT should unwrap proxies when possible
8577         bool compProfilerCallback : 1; // JIT inserted a profiler Enter callback
8578         bool compPublishStubParam : 1; // EAX captured in prolog will be available through an instrinsic
8579         bool compRetBuffDefStack : 1;  // The ret buff argument definitely points into the stack.
8580
8581         var_types compRetType;       // Return type of the method as declared in IL
8582         var_types compRetNativeType; // Normalized return type as per target arch ABI
8583         unsigned  compILargsCount;   // Number of arguments (incl. implicit but not hidden)
8584         unsigned  compArgsCount;     // Number of arguments (incl. implicit and     hidden)
8585
8586 #if FEATURE_FASTTAILCALL
8587         size_t compArgStackSize;     // Incoming argument stack size in bytes
8588         bool   compHasMultiSlotArgs; // Caller has >8 byte sized struct parameter
8589 #endif                               // FEATURE_FASTTAILCALL
8590
8591         unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present);
8592         int compTypeCtxtArg; // position of hidden param for type context for generic code (CORINFO_CALLCONV_PARAMTYPE)
8593         unsigned       compThisArg; // position of implicit this pointer param (not to be confused with lvaArg0Var)
8594         unsigned       compILlocalsCount; // Number of vars : args + locals (incl. implicit but not hidden)
8595         unsigned       compLocalsCount;   // Number of vars : args + locals (incl. implicit and     hidden)
8596         unsigned       compMaxStack;
8597         UNATIVE_OFFSET compTotalHotCodeSize;  // Total number of bytes of Hot Code in the method
8598         UNATIVE_OFFSET compTotalColdCodeSize; // Total number of bytes of Cold Code in the method
8599
8600         unsigned compCallUnmanaged;   // count of unmanaged calls
8601         unsigned compLvFrameListRoot; // lclNum for the Frame root
8602         unsigned compXcptnsCount;     // Number of exception-handling clauses read in the method's IL.
8603                                       // You should generally use compHndBBtabCount instead: it is the
8604                                       // current number of EH clauses (after additions like synchronized
8605                                       // methods and funclets, and removals like unreachable code deletion).
8606
8607         bool compMatchedVM; // true if the VM is "matched": either the JIT is a cross-compiler
8608                             // and the VM expects that, or the JIT is a "self-host" compiler
8609                             // (e.g., x86 hosted targeting x86) and the VM expects that.
8610
8611         /*  The following holds IL scope information about local variables.
8612          */
8613
8614         unsigned     compVarScopesCount;
8615         VarScopeDsc* compVarScopes;
8616
8617         /* The following holds information about instr offsets for
8618          * which we need to report IP-mappings
8619          */
8620
8621         IL_OFFSET*                   compStmtOffsets; // sorted
8622         unsigned                     compStmtOffsetsCount;
8623         ICorDebugInfo::BoundaryTypes compStmtOffsetsImplicit;
8624
8625 #define CPU_X86 0x0100 // The generic X86 CPU
8626 #define CPU_X86_PENTIUM_4 0x0110
8627
8628 #define CPU_X64 0x0200       // The generic x64 CPU
8629 #define CPU_AMD_X64 0x0210   // AMD x64 CPU
8630 #define CPU_INTEL_X64 0x0240 // Intel x64 CPU
8631
8632 #define CPU_ARM 0x0300   // The generic ARM CPU
8633 #define CPU_ARM64 0x0400 // The generic ARM64 CPU
8634
8635         unsigned genCPU; // What CPU are we running on
8636     } info;
8637
8638     // Returns true if the method being compiled returns a non-void and non-struct value.
8639     // Note that lvaInitTypeRef() normalizes compRetNativeType for struct returns in a
8640     // single register as per target arch ABI (e.g on Amd64 Windows structs of size 1, 2,
8641     // 4 or 8 gets normalized to TYP_BYTE/TYP_SHORT/TYP_INT/TYP_LONG; On Arm HFA structs).
8642     // Methods returning such structs are considered to return non-struct return value and
8643     // this method returns true in that case.
8644     bool compMethodReturnsNativeScalarType()
8645     {
8646         return (info.compRetType != TYP_VOID) && !varTypeIsStruct(info.compRetNativeType);
8647     }
8648
8649     // Returns true if the method being compiled returns RetBuf addr as its return value
8650     bool compMethodReturnsRetBufAddr()
8651     {
8652         // There are cases where implicit RetBuf argument should be explicitly returned in a register.
8653         // In such cases the return type is changed to TYP_BYREF and appropriate IR is generated.
8654         // These cases are:
8655         // 1. Profiler Leave calllback expects the address of retbuf as return value for
8656         //    methods with hidden RetBuf argument.  impReturnInstruction() when profiler
8657         //    callbacks are needed creates GT_RETURN(TYP_BYREF, op1 = Addr of RetBuf) for
8658         //    methods with hidden RetBufArg.
8659         //
8660         // 2. As per the System V ABI, the address of RetBuf needs to be returned by
8661         //    methods with hidden RetBufArg in RAX. In such case GT_RETURN is of TYP_BYREF,
8662         //    returning the address of RetBuf.
8663         //
8664         // 3. Windows 64-bit native calling convention also requires the address of RetBuff
8665         //    to be returned in RAX.
8666         CLANG_FORMAT_COMMENT_ANCHOR;
8667
8668 #ifdef _TARGET_AMD64_
8669         return (info.compRetBuffArg != BAD_VAR_NUM);
8670 #else  // !_TARGET_AMD64_
8671         return (compIsProfilerHookNeeded()) && (info.compRetBuffArg != BAD_VAR_NUM);
8672 #endif // !_TARGET_AMD64_
8673     }
8674
8675     // Returns true if the method returns a value in more than one return register
8676     // TODO-ARM-Bug: Deal with multi-register genReturnLocaled structs?
8677     // TODO-ARM64: Does this apply for ARM64 too?
8678     bool compMethodReturnsMultiRegRetType()
8679     {
8680 #if FEATURE_MULTIREG_RET
8681 #if defined(_TARGET_X86_)
8682         // On x86 only 64-bit longs are returned in multiple registers
8683         return varTypeIsLong(info.compRetNativeType);
8684 #else  // targets: X64-UNIX, ARM64 or ARM32
8685         // On all other targets that support multireg return values:
8686         // Methods returning a struct in multiple registers have a return value of TYP_STRUCT.
8687         // Such method's compRetNativeType is TYP_STRUCT without a hidden RetBufArg
8688         return varTypeIsStruct(info.compRetNativeType) && (info.compRetBuffArg == BAD_VAR_NUM);
8689 #endif // TARGET_XXX
8690
8691 #else // not FEATURE_MULTIREG_RET
8692
8693         // For this architecture there are no multireg returns
8694         return false;
8695
8696 #endif // FEATURE_MULTIREG_RET
8697     }
8698
8699 #if FEATURE_MULTIREG_ARGS
8700     // Given a GenTree node of TYP_STRUCT that represents a pass by value argument
8701     // return the gcPtr layout for the pointers sized fields
8702     void getStructGcPtrsFromOp(GenTree* op, BYTE* gcPtrsOut);
8703 #endif // FEATURE_MULTIREG_ARGS
8704
8705     // Returns true if the method being compiled returns a value
8706     bool compMethodHasRetVal()
8707     {
8708         return compMethodReturnsNativeScalarType() || compMethodReturnsRetBufAddr() ||
8709                compMethodReturnsMultiRegRetType();
8710     }
8711
8712 #if defined(DEBUG)
8713
8714     void compDispLocalVars();
8715
8716 #endif // DEBUG
8717
8718 //-------------------------- Global Compiler Data ------------------------------------
8719
8720 #ifdef DEBUG
8721     static unsigned s_compMethodsCount; // to produce unique label names
8722     unsigned        compGenTreeID;
8723     unsigned        compBasicBlockID;
8724 #endif
8725
8726     BasicBlock* compCurBB;   // the current basic block in process
8727     GenTree*    compCurStmt; // the current statement in process
8728 #ifdef DEBUG
8729     unsigned compCurStmtNum; // to give all statements an increasing StmtNum when printing dumps
8730 #endif
8731
8732     //  The following is used to create the 'method JIT info' block.
8733     size_t compInfoBlkSize;
8734     BYTE*  compInfoBlkAddr;
8735
8736     EHblkDsc* compHndBBtab;           // array of EH data
8737     unsigned  compHndBBtabCount;      // element count of used elements in EH data array
8738     unsigned  compHndBBtabAllocCount; // element count of allocated elements in EH data array
8739
8740 #if defined(_TARGET_X86_)
8741
8742     //-------------------------------------------------------------------------
8743     //  Tracking of region covered by the monitor in synchronized methods
8744     void* syncStartEmitCookie; // the emitter cookie for first instruction after the call to MON_ENTER
8745     void* syncEndEmitCookie;   // the emitter cookie for first instruction after the call to MON_EXIT
8746
8747 #endif // !_TARGET_X86_
8748
8749     Phases previousCompletedPhase; // the most recently completed phase
8750
8751     //-------------------------------------------------------------------------
8752     //  The following keeps track of how many bytes of local frame space we've
8753     //  grabbed so far in the current function, and how many argument bytes we
8754     //  need to pop when we return.
8755     //
8756
8757     unsigned compLclFrameSize; // secObject+lclBlk+locals+temps
8758
8759     // Count of callee-saved regs we pushed in the prolog.
8760     // Does not include EBP for isFramePointerUsed() and double-aligned frames.
8761     // In case of Amd64 this doesn't include float regs saved on stack.
8762     unsigned compCalleeRegsPushed;
8763
8764 #if defined(_TARGET_XARCH_)
8765     // Mask of callee saved float regs on stack.
8766     regMaskTP compCalleeFPRegsSavedMask;
8767 #endif
8768 #ifdef _TARGET_AMD64_
8769 // Quirk for VS debug-launch scenario to work:
8770 // Bytes of padding between save-reg area and locals.
8771 #define VSQUIRK_STACK_PAD (2 * REGSIZE_BYTES)
8772     unsigned compVSQuirkStackPaddingNeeded;
8773     bool     compQuirkForPPPflag;
8774 #endif
8775
8776     unsigned compArgSize; // total size of arguments in bytes (including register args (lvIsRegArg))
8777
8778     unsigned compMapILargNum(unsigned ILargNum); // map accounting for hidden args
8779     unsigned compMapILvarNum(unsigned ILvarNum); // map accounting for hidden args
8780     unsigned compMap2ILvarNum(unsigned varNum);  // map accounting for hidden args
8781
8782     //-------------------------------------------------------------------------
8783
8784     static void compStartup();  // One-time initialization
8785     static void compShutdown(); // One-time finalization
8786
8787     void compInit(ArenaAllocator* pAlloc, InlineInfo* inlineInfo);
8788     void compDone();
8789
8790     static void compDisplayStaticSizes(FILE* fout);
8791
8792     //------------ Some utility functions --------------
8793
8794     void* compGetHelperFtn(CorInfoHelpFunc ftnNum,         /* IN  */
8795                            void**          ppIndirection); /* OUT */
8796
8797     // Several JIT/EE interface functions return a CorInfoType, and also return a
8798     // class handle as an out parameter if the type is a value class.  Returns the
8799     // size of the type these describe.
8800     unsigned compGetTypeSize(CorInfoType cit, CORINFO_CLASS_HANDLE clsHnd);
8801
8802 #ifdef DEBUG
8803     // Components used by the compiler may write unit test suites, and
8804     // have them run within this method.  They will be run only once per process, and only
8805     // in debug.  (Perhaps should be under the control of a COMPlus_ flag.)
8806     // These should fail by asserting.
8807     void compDoComponentUnitTestsOnce();
8808 #endif // DEBUG
8809
8810     int compCompile(CORINFO_METHOD_HANDLE methodHnd,
8811                     CORINFO_MODULE_HANDLE classPtr,
8812                     COMP_HANDLE           compHnd,
8813                     CORINFO_METHOD_INFO*  methodInfo,
8814                     void**                methodCodePtr,
8815                     ULONG*                methodCodeSize,
8816                     JitFlags*             compileFlags);
8817     void compCompileFinish();
8818     int compCompileHelper(CORINFO_MODULE_HANDLE            classPtr,
8819                           COMP_HANDLE                      compHnd,
8820                           CORINFO_METHOD_INFO*             methodInfo,
8821                           void**                           methodCodePtr,
8822                           ULONG*                           methodCodeSize,
8823                           JitFlags*                        compileFlags,
8824                           CorInfoInstantiationVerification instVerInfo);
8825
8826     ArenaAllocator* compGetArenaAllocator();
8827
8828 #if MEASURE_MEM_ALLOC
8829     static bool s_dspMemStats; // Display per-phase memory statistics for every function
8830 #endif                         // MEASURE_MEM_ALLOC
8831
8832 #if LOOP_HOIST_STATS
8833     unsigned m_loopsConsidered;
8834     bool     m_curLoopHasHoistedExpression;
8835     unsigned m_loopsWithHoistedExpressions;
8836     unsigned m_totalHoistedExpressions;
8837
8838     void AddLoopHoistStats();
8839     void PrintPerMethodLoopHoistStats();
8840
8841     static CritSecObject s_loopHoistStatsLock; // This lock protects the data structures below.
8842     static unsigned      s_loopsConsidered;
8843     static unsigned      s_loopsWithHoistedExpressions;
8844     static unsigned      s_totalHoistedExpressions;
8845
8846     static void PrintAggregateLoopHoistStats(FILE* f);
8847 #endif // LOOP_HOIST_STATS
8848
8849     bool compIsForImportOnly();
8850     bool compIsForInlining();
8851     bool compDonotInline();
8852
8853 #ifdef DEBUG
8854     // Get the default fill char value we randomize this value when JitStress is enabled.
8855     static unsigned char compGetJitDefaultFill(Compiler* comp);
8856
8857     const char* compLocalVarName(unsigned varNum, unsigned offs);
8858     VarName compVarName(regNumber reg, bool isFloatReg = false);
8859     const char* compRegVarName(regNumber reg, bool displayVar = false, bool isFloatReg = false);
8860     const char* compRegNameForSize(regNumber reg, size_t size);
8861     const char* compFPregVarName(unsigned fpReg, bool displayVar = false);
8862     void compDspSrcLinesByNativeIP(UNATIVE_OFFSET curIP);
8863     void compDspSrcLinesByLineNum(unsigned line, bool seek = false);
8864 #endif // DEBUG
8865
8866     //-------------------------------------------------------------------------
8867
8868     struct VarScopeListNode
8869     {
8870         VarScopeDsc*             data;
8871         VarScopeListNode*        next;
8872         static VarScopeListNode* Create(VarScopeDsc* value, CompAllocator alloc)
8873         {
8874             VarScopeListNode* node = new (alloc) VarScopeListNode;
8875             node->data             = value;
8876             node->next             = nullptr;
8877             return node;
8878         }
8879     };
8880
8881     struct VarScopeMapInfo
8882     {
8883         VarScopeListNode*       head;
8884         VarScopeListNode*       tail;
8885         static VarScopeMapInfo* Create(VarScopeListNode* node, CompAllocator alloc)
8886         {
8887             VarScopeMapInfo* info = new (alloc) VarScopeMapInfo;
8888             info->head            = node;
8889             info->tail            = node;
8890             return info;
8891         }
8892     };
8893
8894     // Max value of scope count for which we would use linear search; for larger values we would use hashtable lookup.
8895     static const unsigned MAX_LINEAR_FIND_LCL_SCOPELIST = 32;
8896
8897     typedef JitHashTable<unsigned, JitSmallPrimitiveKeyFuncs<unsigned>, VarScopeMapInfo*> VarNumToScopeDscMap;
8898
8899     // Map to keep variables' scope indexed by varNum containing it's scope dscs at the index.
8900     VarNumToScopeDscMap* compVarScopeMap;
8901
8902     VarScopeDsc* compFindLocalVar(unsigned varNum, unsigned lifeBeg, unsigned lifeEnd);
8903
8904     VarScopeDsc* compFindLocalVar(unsigned varNum, unsigned offs);
8905
8906     VarScopeDsc* compFindLocalVarLinear(unsigned varNum, unsigned offs);
8907
8908     void compInitVarScopeMap();
8909
8910     VarScopeDsc** compEnterScopeList; // List has the offsets where variables
8911                                       // enter scope, sorted by instr offset
8912     unsigned compNextEnterScope;
8913
8914     VarScopeDsc** compExitScopeList; // List has the offsets where variables
8915                                      // go out of scope, sorted by instr offset
8916     unsigned compNextExitScope;
8917
8918     void compInitScopeLists();
8919
8920     void compResetScopeLists();
8921
8922     VarScopeDsc* compGetNextEnterScope(unsigned offs, bool scan = false);
8923
8924     VarScopeDsc* compGetNextExitScope(unsigned offs, bool scan = false);
8925
8926     void compProcessScopesUntil(unsigned   offset,
8927                                 VARSET_TP* inScope,
8928                                 void (Compiler::*enterScopeFn)(VARSET_TP* inScope, VarScopeDsc*),
8929                                 void (Compiler::*exitScopeFn)(VARSET_TP* inScope, VarScopeDsc*));
8930
8931 #ifdef DEBUG
8932     void compDispScopeLists();
8933 #endif // DEBUG
8934
8935     bool compIsProfilerHookNeeded();
8936
8937     //-------------------------------------------------------------------------
8938     /*               Statistical Data Gathering                               */
8939
8940     void compJitStats(); // call this function and enable
8941                          // various ifdef's below for statistical data
8942
8943 #if CALL_ARG_STATS
8944     void        compCallArgStats();
8945     static void compDispCallArgStats(FILE* fout);
8946 #endif
8947
8948     //-------------------------------------------------------------------------
8949
8950 protected:
8951 #ifdef DEBUG
8952     bool skipMethod();
8953 #endif
8954
8955     ArenaAllocator* compArenaAllocator;
8956
8957 public:
8958     void compFunctionTraceStart();
8959     void compFunctionTraceEnd(void* methodCodePtr, ULONG methodCodeSize, bool isNYI);
8960
8961 protected:
8962     size_t compMaxUncheckedOffsetForNullObject;
8963
8964     void compInitOptions(JitFlags* compileFlags);
8965
8966     void compSetProcessor();
8967     void compInitDebuggingInfo();
8968     void compSetOptimizationLevel();
8969 #ifdef _TARGET_ARMARCH_
8970     bool compRsvdRegCheck(FrameLayoutState curState);
8971 #endif
8972     void compCompile(void** methodCodePtr, ULONG* methodCodeSize, JitFlags* compileFlags);
8973
8974     // Clear annotations produced during optimizations; to be used between iterations when repeating opts.
8975     void ResetOptAnnotations();
8976
8977     // Regenerate loop descriptors; to be used between iterations when repeating opts.
8978     void RecomputeLoopInfo();
8979
8980 #ifdef PROFILING_SUPPORTED
8981     // Data required for generating profiler Enter/Leave/TailCall hooks
8982
8983     bool  compProfilerHookNeeded; // Whether profiler Enter/Leave/TailCall hook needs to be generated for the method
8984     void* compProfilerMethHnd;    // Profiler handle of the method being compiled. Passed as param to ELT callbacks
8985     bool  compProfilerMethHndIndirected; // Whether compProfilerHandle is pointer to the handle or is an actual handle
8986 #endif
8987
8988 #ifdef _TARGET_AMD64_
8989     bool compQuirkForPPP(); // Check if this method should be Quirked for the PPP issue
8990 #endif
8991 public:
8992     // Assumes called as part of process shutdown; does any compiler-specific work associated with that.
8993     static void ProcessShutdownWork(ICorStaticInfo* statInfo);
8994
8995     CompAllocator getAllocator(CompMemKind cmk = CMK_Generic)
8996     {
8997         return CompAllocator(compArenaAllocator, cmk);
8998     }
8999
9000     CompAllocator getAllocatorGC()
9001     {
9002         return getAllocator(CMK_GC);
9003     }
9004
9005     CompAllocator getAllocatorLoopHoist()
9006     {
9007         return getAllocator(CMK_LoopHoist);
9008     }
9009
9010 #ifdef DEBUG
9011     CompAllocator getAllocatorDebugOnly()
9012     {
9013         return getAllocator(CMK_DebugOnly);
9014     }
9015 #endif // DEBUG
9016
9017     /*
9018     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9019     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9020     XX                                                                           XX
9021     XX                           typeInfo                                        XX
9022     XX                                                                           XX
9023     XX   Checks for type compatibility and merges types                          XX
9024     XX                                                                           XX
9025     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9026     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9027     */
9028
9029 public:
9030     // Set to TRUE if verification cannot be skipped for this method
9031     // If we detect unverifiable code, we will lazily check
9032     // canSkipMethodVerification() to see if verification is REALLY needed.
9033     BOOL tiVerificationNeeded;
9034
9035     // It it initially TRUE, and it gets set to FALSE if we run into unverifiable code
9036     // Note that this is valid only if tiVerificationNeeded was ever TRUE.
9037     BOOL tiIsVerifiableCode;
9038
9039     // Set to TRUE if runtime callout is needed for this method
9040     BOOL tiRuntimeCalloutNeeded;
9041
9042     // Set to TRUE if security prolog/epilog callout is needed for this method
9043     // Note: This flag is different than compNeedSecurityCheck.
9044     //     compNeedSecurityCheck means whether or not a security object needs
9045     //         to be allocated on the stack, which is currently true for EnC as well.
9046     //     tiSecurityCalloutNeeded means whether or not security callouts need
9047     //         to be inserted in the jitted code.
9048     BOOL tiSecurityCalloutNeeded;
9049
9050     // Returns TRUE if child is equal to or a subtype of parent for merge purposes
9051     // This support is necessary to suport attributes that are not described in
9052     // for example, signatures. For example, the permanent home byref (byref that
9053     // points to the gc heap), isn't a property of method signatures, therefore,
9054     // it is safe to have mismatches here (that tiCompatibleWith will not flag),
9055     // but when deciding if we need to reimport a block, we need to take these
9056     // in account
9057     BOOL tiMergeCompatibleWith(const typeInfo& pChild, const typeInfo& pParent, bool normalisedForStack) const;
9058
9059     // Returns TRUE if child is equal to or a subtype of parent.
9060     // normalisedForStack indicates that both types are normalised for the stack
9061     BOOL tiCompatibleWith(const typeInfo& pChild, const typeInfo& pParent, bool normalisedForStack) const;
9062
9063     // Merges pDest and pSrc. Returns FALSE if merge is undefined.
9064     // *pDest is modified to represent the merged type.  Sets "*changed" to true
9065     // if this changes "*pDest".
9066     BOOL tiMergeToCommonParent(typeInfo* pDest, const typeInfo* pSrc, bool* changed) const;
9067
9068 #ifdef DEBUG
9069     // <BUGNUM> VSW 471305
9070     // IJW allows assigning REF to BYREF. The following allows us to temporarily
9071     // bypass the assert check in gcMarkRegSetGCref and gcMarkRegSetByref
9072     // We use a "short" as we need to push/pop this scope.
9073     // </BUGNUM>
9074     short compRegSetCheckLevel;
9075 #endif
9076
9077     /*
9078     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9079     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9080     XX                                                                           XX
9081     XX                           IL verification stuff                           XX
9082     XX                                                                           XX
9083     XX                                                                           XX
9084     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9085     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9086     */
9087
9088 public:
9089     // The following is used to track liveness of local variables, initialization
9090     // of valueclass constructors, and type safe use of IL instructions.
9091
9092     // dynamic state info needed for verification
9093     EntryState verCurrentState;
9094
9095     // this ptr of object type .ctors are considered intited only after
9096     // the base class ctor is called, or an alternate ctor is called.
9097     // An uninited this ptr can be used to access fields, but cannot
9098     // be used to call a member function.
9099     BOOL verTrackObjCtorInitState;
9100
9101     void verInitBBEntryState(BasicBlock* block, EntryState* currentState);
9102
9103     // Requires that "tis" is not TIS_Bottom -- it's a definite init/uninit state.
9104     void verSetThisInit(BasicBlock* block, ThisInitState tis);
9105     void verInitCurrentState();
9106     void verResetCurrentState(BasicBlock* block, EntryState* currentState);
9107
9108     // Merges the current verification state into the entry state of "block", return FALSE if that merge fails,
9109     // TRUE if it succeeds.  Further sets "*changed" to true if this changes the entry state of "block".
9110     BOOL verMergeEntryStates(BasicBlock* block, bool* changed);
9111
9112     void verConvertBBToThrowVerificationException(BasicBlock* block DEBUGARG(bool logMsg));
9113     void verHandleVerificationFailure(BasicBlock* block DEBUGARG(bool logMsg));
9114     typeInfo verMakeTypeInfo(CORINFO_CLASS_HANDLE clsHnd,
9115                              bool bashStructToRef = false); // converts from jit type representation to typeInfo
9116     typeInfo verMakeTypeInfo(CorInfoType          ciType,
9117                              CORINFO_CLASS_HANDLE clsHnd); // converts from jit type representation to typeInfo
9118     BOOL verIsSDArray(typeInfo ti);
9119     typeInfo verGetArrayElemType(typeInfo ti);
9120
9121     typeInfo verParseArgSigToTypeInfo(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args);
9122     BOOL verNeedsVerification();
9123     BOOL verIsByRefLike(const typeInfo& ti);
9124     BOOL verIsSafeToReturnByRef(const typeInfo& ti);
9125
9126     // generic type variables range over types that satisfy IsBoxable
9127     BOOL verIsBoxable(const typeInfo& ti);
9128
9129     void DECLSPEC_NORETURN verRaiseVerifyException(INDEBUG(const char* reason) DEBUGARG(const char* file)
9130                                                        DEBUGARG(unsigned line));
9131     void verRaiseVerifyExceptionIfNeeded(INDEBUG(const char* reason) DEBUGARG(const char* file)
9132                                              DEBUGARG(unsigned line));
9133     bool verCheckTailCallConstraint(OPCODE                  opcode,
9134                                     CORINFO_RESOLVED_TOKEN* pResolvedToken,
9135                                     CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, // Is this a "constrained." call
9136                                                                                        // on a type parameter?
9137                                     bool speculative // If true, won't throw if verificatoin fails. Instead it will
9138                                                      // return false to the caller.
9139                                                      // If false, it will throw.
9140                                     );
9141     bool verIsBoxedValueType(typeInfo ti);
9142
9143     void verVerifyCall(OPCODE                  opcode,
9144                        CORINFO_RESOLVED_TOKEN* pResolvedToken,
9145                        CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
9146                        bool                    tailCall,
9147                        bool                    readonlyCall, // is this a "readonly." call?
9148                        const BYTE*             delegateCreateStart,
9149                        const BYTE*             codeAddr,
9150                        CORINFO_CALL_INFO* callInfo DEBUGARG(const char* methodName));
9151
9152     BOOL verCheckDelegateCreation(const BYTE* delegateCreateStart, const BYTE* codeAddr, mdMemberRef& targetMemberRef);
9153
9154     typeInfo verVerifySTIND(const typeInfo& ptr, const typeInfo& value, const typeInfo& instrType);
9155     typeInfo verVerifyLDIND(const typeInfo& ptr, const typeInfo& instrType);
9156     void verVerifyField(CORINFO_RESOLVED_TOKEN*   pResolvedToken,
9157                         const CORINFO_FIELD_INFO& fieldInfo,
9158                         const typeInfo*           tiThis,
9159                         BOOL                      mutator,
9160                         BOOL                      allowPlainStructAsThis = FALSE);
9161     void verVerifyCond(const typeInfo& tiOp1, const typeInfo& tiOp2, unsigned opcode);
9162     void verVerifyThisPtrInitialised();
9163     BOOL verIsCallToInitThisPtr(CORINFO_CLASS_HANDLE context, CORINFO_CLASS_HANDLE target);
9164
9165 #ifdef DEBUG
9166
9167     // One line log function. Default level is 0. Increasing it gives you
9168     // more log information
9169
9170     // levels are currently unused: #define JITDUMP(level,...)                     ();
9171     void JitLogEE(unsigned level, const char* fmt, ...);
9172
9173     bool compDebugBreak;
9174
9175     bool compJitHaltMethod();
9176
9177 #endif
9178
9179     /*
9180     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9181     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9182     XX                                                                           XX
9183     XX                   GS Security checks for unsafe buffers                   XX
9184     XX                                                                           XX
9185     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9186     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9187     */
9188 public:
9189     struct ShadowParamVarInfo
9190     {
9191         FixedBitVect* assignGroup; // the closure set of variables whose values depend on each other
9192         unsigned      shadowCopy;  // Lcl var num, valid only if not set to NO_SHADOW_COPY
9193
9194         static bool mayNeedShadowCopy(LclVarDsc* varDsc)
9195         {
9196 #if defined(_TARGET_AMD64_)
9197             // GS cookie logic to create shadow slots, create trees to copy reg args to shadow
9198             // slots and update all trees to refer to shadow slots is done immediately after
9199             // fgMorph().  Lsra could potentially mark a param as DoNotEnregister after JIT determines
9200             // not to shadow a parameter.  Also, LSRA could potentially spill a param which is passed
9201             // in register. Therefore, conservatively all params may need a shadow copy.  Note that
9202             // GS cookie logic further checks whether the param is a ptr or an unsafe buffer before
9203             // creating a shadow slot even though this routine returns true.
9204             //
9205             // TODO-AMD64-CQ: Revisit this conservative approach as it could create more shadow slots than
9206             // required. There are two cases under which a reg arg could potentially be used from its
9207             // home location:
9208             //   a) LSRA marks it as DoNotEnregister (see LinearScan::identifyCandidates())
9209             //   b) LSRA spills it
9210             //
9211             // Possible solution to address case (a)
9212             //   - The conditions under which LSRA marks a varDsc as DoNotEnregister could be checked
9213             //     in this routine.  Note that live out of exception handler is something we may not be
9214             //     able to do it here since GS cookie logic is invoked ahead of liveness computation.
9215             //     Therefore, for methods with exception handling and need GS cookie check we might have
9216             //     to take conservative approach.
9217             //
9218             // Possible solution to address case (b)
9219             //   - Whenver a parameter passed in an argument register needs to be spilled by LSRA, we
9220             //     create a new spill temp if the method needs GS cookie check.
9221             return varDsc->lvIsParam;
9222 #else // !defined(_TARGET_AMD64_)
9223             return varDsc->lvIsParam && !varDsc->lvIsRegArg;
9224 #endif
9225         }
9226
9227 #ifdef DEBUG
9228         void Print()
9229         {
9230             printf("assignGroup [%p]; shadowCopy: [%d];\n", assignGroup, shadowCopy);
9231         }
9232 #endif
9233     };
9234
9235     GSCookie*           gsGlobalSecurityCookieAddr; // Address of global cookie for unsafe buffer checks
9236     GSCookie            gsGlobalSecurityCookieVal;  // Value of global cookie if addr is NULL
9237     ShadowParamVarInfo* gsShadowVarInfo;            // Table used by shadow param analysis code
9238
9239     void gsGSChecksInitCookie();   // Grabs cookie variable
9240     void gsCopyShadowParams();     // Identify vulnerable params and create dhadow copies
9241     bool gsFindVulnerableParams(); // Shadow param analysis code
9242     void gsParamsToShadows();      // Insert copy code and replave param uses by shadow
9243
9244     static fgWalkPreFn gsMarkPtrsAndAssignGroups; // Shadow param analysis tree-walk
9245     static fgWalkPreFn gsReplaceShadowParams;     // Shadow param replacement tree-walk
9246
9247 #define DEFAULT_MAX_INLINE_SIZE 100 // Methods with >  DEFAULT_MAX_INLINE_SIZE IL bytes will never be inlined.
9248                                     // This can be overwritten by setting complus_JITInlineSize env variable.
9249
9250 #define DEFAULT_MAX_INLINE_DEPTH 20 // Methods at more than this level deep will not be inlined
9251
9252 #define DEFAULT_MAX_LOCALLOC_TO_LOCAL_SIZE 32 // fixed locallocs of this size or smaller will convert to local buffers
9253
9254 private:
9255 #ifdef FEATURE_JIT_METHOD_PERF
9256     JitTimer*                  pCompJitTimer;         // Timer data structure (by phases) for current compilation.
9257     static CompTimeSummaryInfo s_compJitTimerSummary; // Summary of the Timer information for the whole run.
9258
9259     static LPCWSTR JitTimeLogCsv();        // Retrieve the file name for CSV from ConfigDWORD.
9260     static LPCWSTR compJitTimeLogFilename; // If a log file for JIT time is desired, filename to write it to.
9261 #endif
9262     inline void EndPhase(Phases phase); // Indicate the end of the given phase.
9263
9264 #if MEASURE_CLRAPI_CALLS
9265     // Thin wrappers that call into JitTimer (if present).
9266     inline void CLRApiCallEnter(unsigned apix);
9267     inline void CLRApiCallLeave(unsigned apix);
9268
9269 public:
9270     inline void CLR_API_Enter(API_ICorJitInfo_Names ename);
9271     inline void CLR_API_Leave(API_ICorJitInfo_Names ename);
9272
9273 private:
9274 #endif
9275
9276 #if defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
9277     // These variables are associated with maintaining SQM data about compile time.
9278     unsigned __int64 m_compCyclesAtEndOfInlining; // The thread-virtualized cycle count at the end of the inlining phase
9279                                                   // in the current compilation.
9280     unsigned __int64 m_compCycles;                // Net cycle count for current compilation
9281     DWORD m_compTickCountAtEndOfInlining; // The result of GetTickCount() (# ms since some epoch marker) at the end of
9282                                           // the inlining phase in the current compilation.
9283 #endif                                    // defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
9284
9285     // Records the SQM-relevant (cycles and tick count).  Should be called after inlining is complete.
9286     // (We do this after inlining because this marks the last point at which the JIT is likely to cause
9287     // type-loading and class initialization).
9288     void RecordStateAtEndOfInlining();
9289     // Assumes being called at the end of compilation.  Update the SQM state.
9290     void RecordStateAtEndOfCompilation();
9291
9292 #ifdef FEATURE_CLRSQM
9293     // Does anything SQM related necessary at process shutdown time.
9294     static void ProcessShutdownSQMWork(ICorStaticInfo* statInfo);
9295 #endif // FEATURE_CLRSQM
9296
9297 public:
9298 #if FUNC_INFO_LOGGING
9299     static LPCWSTR compJitFuncInfoFilename; // If a log file for per-function information is required, this is the
9300                                             // filename to write it to.
9301     static FILE* compJitFuncInfoFile;       // And this is the actual FILE* to write to.
9302 #endif                                      // FUNC_INFO_LOGGING
9303
9304     Compiler* prevCompiler; // Previous compiler on stack for TLS Compiler* linked list for reentrant compilers.
9305
9306     // Is the compilation in a full trust context?
9307     bool compIsFullTrust();
9308
9309 #if MEASURE_NOWAY
9310     void RecordNowayAssert(const char* filename, unsigned line, const char* condStr);
9311 #endif // MEASURE_NOWAY
9312
9313 #ifndef FEATURE_TRACELOGGING
9314     // Should we actually fire the noway assert body and the exception handler?
9315     bool compShouldThrowOnNoway();
9316 #else  // FEATURE_TRACELOGGING
9317     // Should we actually fire the noway assert body and the exception handler?
9318     bool compShouldThrowOnNoway(const char* filename, unsigned line);
9319
9320     // Telemetry instance to use per method compilation.
9321     JitTelemetry compJitTelemetry;
9322
9323     // Get common parameters that have to be logged with most telemetry data.
9324     void compGetTelemetryDefaults(const char** assemblyName,
9325                                   const char** scopeName,
9326                                   const char** methodName,
9327                                   unsigned*    methodHash);
9328 #endif // !FEATURE_TRACELOGGING
9329
9330 #ifdef DEBUG
9331 private:
9332     NodeToTestDataMap* m_nodeTestData;
9333
9334     static const unsigned FIRST_LOOP_HOIST_CSE_CLASS = 1000;
9335     unsigned              m_loopHoistCSEClass; // LoopHoist test annotations turn into CSE requirements; we
9336                                                // label them with CSE Class #'s starting at FIRST_LOOP_HOIST_CSE_CLASS.
9337                                                // Current kept in this.
9338 public:
9339     NodeToTestDataMap* GetNodeTestData()
9340     {
9341         Compiler* compRoot = impInlineRoot();
9342         if (compRoot->m_nodeTestData == nullptr)
9343         {
9344             compRoot->m_nodeTestData = new (getAllocatorDebugOnly()) NodeToTestDataMap(getAllocatorDebugOnly());
9345         }
9346         return compRoot->m_nodeTestData;
9347     }
9348
9349     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, int> NodeToIntMap;
9350
9351     // Returns the set (i.e., the domain of the result map) of nodes that are keys in m_nodeTestData, and
9352     // currently occur in the AST graph.
9353     NodeToIntMap* FindReachableNodesInNodeTestData();
9354
9355     // Node "from" is being eliminated, and being replaced by node "to".  If "from" had any associated
9356     // test data, associate that data with "to".
9357     void TransferTestDataToNode(GenTree* from, GenTree* to);
9358
9359     // Requires that "to" is a clone of "from".  If any nodes in the "from" tree
9360     // have annotations, attach similar annotations to the corresponding nodes in "to".
9361     void CopyTestDataToCloneTree(GenTree* from, GenTree* to);
9362
9363     // These are the methods that test that the various conditions implied by the
9364     // test attributes are satisfied.
9365     void JitTestCheckSSA(); // SSA builder tests.
9366     void JitTestCheckVN();  // Value numbering tests.
9367 #endif                      // DEBUG
9368
9369     // The "FieldSeqStore", for canonicalizing field sequences.  See the definition of FieldSeqStore for
9370     // operations.
9371     FieldSeqStore* m_fieldSeqStore;
9372
9373     FieldSeqStore* GetFieldSeqStore()
9374     {
9375         Compiler* compRoot = impInlineRoot();
9376         if (compRoot->m_fieldSeqStore == nullptr)
9377         {
9378             // Create a CompAllocator that labels sub-structure with CMK_FieldSeqStore, and use that for allocation.
9379             CompAllocator ialloc(getAllocator(CMK_FieldSeqStore));
9380             compRoot->m_fieldSeqStore = new (ialloc) FieldSeqStore(ialloc);
9381         }
9382         return compRoot->m_fieldSeqStore;
9383     }
9384
9385     typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, FieldSeqNode*> NodeToFieldSeqMap;
9386
9387     // Some nodes of "TYP_BYREF" or "TYP_I_IMPL" actually represent the address of a field within a struct, but since
9388     // the offset of the field is zero, there's no "GT_ADD" node.  We normally attach a field sequence to the constant
9389     // that is added, but what do we do when that constant is zero, and is thus not present?  We use this mechanism to
9390     // attach the field sequence directly to the address node.
9391     NodeToFieldSeqMap* m_zeroOffsetFieldMap;
9392
9393     NodeToFieldSeqMap* GetZeroOffsetFieldMap()
9394     {
9395         // Don't need to worry about inlining here
9396         if (m_zeroOffsetFieldMap == nullptr)
9397         {
9398             // Create a CompAllocator that labels sub-structure with CMK_ZeroOffsetFieldMap, and use that for
9399             // allocation.
9400             CompAllocator ialloc(getAllocator(CMK_ZeroOffsetFieldMap));
9401             m_zeroOffsetFieldMap = new (ialloc) NodeToFieldSeqMap(ialloc);
9402         }
9403         return m_zeroOffsetFieldMap;
9404     }
9405
9406     // Requires that "op1" is a node of type "TYP_BYREF" or "TYP_I_IMPL".  We are dereferencing this with the fields in
9407     // "fieldSeq", whose offsets are required all to be zero.  Ensures that any field sequence annotation currently on
9408     // "op1" or its components is augmented by appending "fieldSeq".  In practice, if "op1" is a GT_LCL_FLD, it has
9409     // a field sequence as a member; otherwise, it may be the addition of an a byref and a constant, where the const
9410     // has a field sequence -- in this case "fieldSeq" is appended to that of the constant; otherwise, we
9411     // record the the field sequence using the ZeroOffsetFieldMap described above.
9412     //
9413     // One exception above is that "op1" is a node of type "TYP_REF" where "op1" is a GT_LCL_VAR.
9414     // This happens when System.Object vtable pointer is a regular field at offset 0 in System.Private.CoreLib in
9415     // CoreRT. Such case is handled same as the default case.
9416     void fgAddFieldSeqForZeroOffset(GenTree* op1, FieldSeqNode* fieldSeq);
9417
9418     typedef JitHashTable<const GenTree*, JitPtrKeyFuncs<GenTree>, ArrayInfo> NodeToArrayInfoMap;
9419     NodeToArrayInfoMap* m_arrayInfoMap;
9420
9421     NodeToArrayInfoMap* GetArrayInfoMap()
9422     {
9423         Compiler* compRoot = impInlineRoot();
9424         if (compRoot->m_arrayInfoMap == nullptr)
9425         {
9426             // Create a CompAllocator that labels sub-structure with CMK_ArrayInfoMap, and use that for allocation.
9427             CompAllocator ialloc(getAllocator(CMK_ArrayInfoMap));
9428             compRoot->m_arrayInfoMap = new (ialloc) NodeToArrayInfoMap(ialloc);
9429         }
9430         return compRoot->m_arrayInfoMap;
9431     }
9432
9433     //-----------------------------------------------------------------------------------------------------------------
9434     // Compiler::TryGetArrayInfo:
9435     //    Given an indirection node, checks to see whether or not that indirection represents an array access, and
9436     //    if so returns information about the array.
9437     //
9438     // Arguments:
9439     //    indir           - The `GT_IND` node.
9440     //    arrayInfo (out) - Information about the accessed array if this function returns true. Undefined otherwise.
9441     //
9442     // Returns:
9443     //    True if the `GT_IND` node represents an array access; false otherwise.
9444     bool TryGetArrayInfo(GenTreeIndir* indir, ArrayInfo* arrayInfo)
9445     {
9446         if ((indir->gtFlags & GTF_IND_ARR_INDEX) == 0)
9447         {
9448             return false;
9449         }
9450
9451         if (indir->gtOp1->OperIs(GT_INDEX_ADDR))
9452         {
9453             GenTreeIndexAddr* const indexAddr = indir->gtOp1->AsIndexAddr();
9454             *arrayInfo = ArrayInfo(indexAddr->gtElemType, indexAddr->gtElemSize, indexAddr->gtElemOffset,
9455                                    indexAddr->gtStructElemClass);
9456             return true;
9457         }
9458
9459         bool found = GetArrayInfoMap()->Lookup(indir, arrayInfo);
9460         assert(found);
9461         return true;
9462     }
9463
9464     NodeToUnsignedMap* m_memorySsaMap[MemoryKindCount];
9465
9466     // In some cases, we want to assign intermediate SSA #'s to memory states, and know what nodes create those memory
9467     // states. (We do this for try blocks, where, if the try block doesn't do a call that loses track of the memory
9468     // state, all the possible memory states are possible initial states of the corresponding catch block(s).)
9469     NodeToUnsignedMap* GetMemorySsaMap(MemoryKind memoryKind)
9470     {
9471         if (memoryKind == GcHeap && byrefStatesMatchGcHeapStates)
9472         {
9473             // Use the same map for GCHeap and ByrefExposed when their states match.
9474             memoryKind = ByrefExposed;
9475         }
9476
9477         assert(memoryKind < MemoryKindCount);
9478         Compiler* compRoot = impInlineRoot();
9479         if (compRoot->m_memorySsaMap[memoryKind] == nullptr)
9480         {
9481             // Create a CompAllocator that labels sub-structure with CMK_ArrayInfoMap, and use that for allocation.
9482             CompAllocator ialloc(getAllocator(CMK_ArrayInfoMap));
9483             compRoot->m_memorySsaMap[memoryKind] = new (ialloc) NodeToUnsignedMap(ialloc);
9484         }
9485         return compRoot->m_memorySsaMap[memoryKind];
9486     }
9487
9488     // The Refany type is the only struct type whose structure is implicitly assumed by IL.  We need its fields.
9489     CORINFO_CLASS_HANDLE m_refAnyClass;
9490     CORINFO_FIELD_HANDLE GetRefanyDataField()
9491     {
9492         if (m_refAnyClass == nullptr)
9493         {
9494             m_refAnyClass = info.compCompHnd->getBuiltinClass(CLASSID_TYPED_BYREF);
9495         }
9496         return info.compCompHnd->getFieldInClass(m_refAnyClass, 0);
9497     }
9498     CORINFO_FIELD_HANDLE GetRefanyTypeField()
9499     {
9500         if (m_refAnyClass == nullptr)
9501         {
9502             m_refAnyClass = info.compCompHnd->getBuiltinClass(CLASSID_TYPED_BYREF);
9503         }
9504         return info.compCompHnd->getFieldInClass(m_refAnyClass, 1);
9505     }
9506
9507 #if VARSET_COUNTOPS
9508     static BitSetSupport::BitSetOpCounter m_varsetOpCounter;
9509 #endif
9510 #if ALLVARSET_COUNTOPS
9511     static BitSetSupport::BitSetOpCounter m_allvarsetOpCounter;
9512 #endif
9513
9514     static HelperCallProperties s_helperCallProperties;
9515
9516 #ifdef UNIX_AMD64_ABI
9517     static var_types GetTypeFromClassificationAndSizes(SystemVClassificationType classType, int size);
9518     static var_types GetEightByteType(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc,
9519                                       unsigned                                                   slotNum);
9520
9521     static void GetStructTypeOffset(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc,
9522                                     var_types*                                                 type0,
9523                                     var_types*                                                 type1,
9524                                     unsigned __int8*                                           offset0,
9525                                     unsigned __int8*                                           offset1);
9526
9527     void GetStructTypeOffset(CORINFO_CLASS_HANDLE typeHnd,
9528                              var_types*           type0,
9529                              var_types*           type1,
9530                              unsigned __int8*     offset0,
9531                              unsigned __int8*     offset1);
9532
9533 #endif // defined(UNIX_AMD64_ABI)
9534
9535     void fgMorphMultiregStructArgs(GenTreeCall* call);
9536     GenTree* fgMorphMultiregStructArg(GenTree* arg, fgArgTabEntry* fgEntryPtr);
9537
9538     bool killGCRefs(GenTree* tree);
9539
9540 }; // end of class Compiler
9541
9542 //---------------------------------------------------------------------------------------------------------------------
9543 // GenTreeVisitor: a flexible tree walker implemented using the curiosly-recurring-template pattern.
9544 //
9545 // This class implements a configurable walker for IR trees. There are five configuration options (defaults values are
9546 // shown in parentheses):
9547 //
9548 // - ComputeStack (false): when true, the walker will push each node onto the `m_ancestors` stack. "Ancestors" is a bit
9549 //                         of a misnomer, as the first entry will always be the current node.
9550 //
9551 // - DoPreOrder (false): when true, the walker will invoke `TVisitor::PreOrderVisit` with the current node as an
9552 //                       argument before visiting the node's operands.
9553 //
9554 // - DoPostOrder (false): when true, the walker will invoke `TVisitor::PostOrderVisit` with the current node as an
9555 //                        argument after visiting the node's operands.
9556 //
9557 // - DoLclVarsOnly (false): when true, the walker will only invoke `TVisitor::PreOrderVisit` for lclVar nodes.
9558 //                          `DoPreOrder` must be true if this option is true.
9559 //
9560 // - UseExecutionOrder (false): when true, then walker will visit a node's operands in execution order (e.g. if a
9561 //                              binary operator has the `GTF_REVERSE_OPS` flag set, the second operand will be
9562 //                              visited before the first).
9563 //
9564 // At least one of `DoPreOrder` and `DoPostOrder` must be specified.
9565 //
9566 // A simple pre-order visitor might look something like the following:
9567 //
9568 //     class CountingVisitor final : public GenTreeVisitor<CountingVisitor>
9569 //     {
9570 //     public:
9571 //         enum
9572 //         {
9573 //             DoPreOrder = true
9574 //         };
9575 //
9576 //         unsigned m_count;
9577 //
9578 //         CountingVisitor(Compiler* compiler)
9579 //             : GenTreeVisitor<CountingVisitor>(compiler), m_count(0)
9580 //         {
9581 //         }
9582 //
9583 //         Compiler::fgWalkResult PreOrderVisit(GenTree* node)
9584 //         {
9585 //             m_count++;
9586 //         }
9587 //     };
9588 //
9589 // This visitor would then be used like so:
9590 //
9591 //     CountingVisitor countingVisitor(compiler);
9592 //     countingVisitor.WalkTree(root);
9593 //
9594 template <typename TVisitor>
9595 class GenTreeVisitor
9596 {
9597 protected:
9598     typedef Compiler::fgWalkResult fgWalkResult;
9599
9600     enum
9601     {
9602         ComputeStack      = false,
9603         DoPreOrder        = false,
9604         DoPostOrder       = false,
9605         DoLclVarsOnly     = false,
9606         UseExecutionOrder = false,
9607     };
9608
9609     Compiler*            m_compiler;
9610     ArrayStack<GenTree*> m_ancestors;
9611
9612     GenTreeVisitor(Compiler* compiler) : m_compiler(compiler), m_ancestors(compiler->getAllocator(CMK_ArrayStack))
9613     {
9614         assert(compiler != nullptr);
9615
9616         static_assert_no_msg(TVisitor::DoPreOrder || TVisitor::DoPostOrder);
9617         static_assert_no_msg(!TVisitor::DoLclVarsOnly || TVisitor::DoPreOrder);
9618     }
9619
9620     fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
9621     {
9622         return fgWalkResult::WALK_CONTINUE;
9623     }
9624
9625     fgWalkResult PostOrderVisit(GenTree** use, GenTree* user)
9626     {
9627         return fgWalkResult::WALK_CONTINUE;
9628     }
9629
9630 public:
9631     fgWalkResult WalkTree(GenTree** use, GenTree* user)
9632     {
9633         assert(use != nullptr);
9634
9635         GenTree* node = *use;
9636
9637         if (TVisitor::ComputeStack)
9638         {
9639             m_ancestors.Push(node);
9640         }
9641
9642         fgWalkResult result = fgWalkResult::WALK_CONTINUE;
9643         if (TVisitor::DoPreOrder && !TVisitor::DoLclVarsOnly)
9644         {
9645             result = reinterpret_cast<TVisitor*>(this)->PreOrderVisit(use, user);
9646             if (result == fgWalkResult::WALK_ABORT)
9647             {
9648                 return result;
9649             }
9650
9651             node = *use;
9652             if ((node == nullptr) || (result == fgWalkResult::WALK_SKIP_SUBTREES))
9653             {
9654                 goto DONE;
9655             }
9656         }
9657
9658         switch (node->OperGet())
9659         {
9660             // Leaf lclVars
9661             case GT_LCL_VAR:
9662             case GT_LCL_FLD:
9663             case GT_LCL_VAR_ADDR:
9664             case GT_LCL_FLD_ADDR:
9665                 if (TVisitor::DoLclVarsOnly)
9666                 {
9667                     result = reinterpret_cast<TVisitor*>(this)->PreOrderVisit(use, user);
9668                     if (result == fgWalkResult::WALK_ABORT)
9669                     {
9670                         return result;
9671                     }
9672                 }
9673                 __fallthrough;
9674
9675             // Leaf nodes
9676             case GT_CATCH_ARG:
9677             case GT_LABEL:
9678             case GT_FTN_ADDR:
9679             case GT_RET_EXPR:
9680             case GT_CNS_INT:
9681             case GT_CNS_LNG:
9682             case GT_CNS_DBL:
9683             case GT_CNS_STR:
9684             case GT_MEMORYBARRIER:
9685             case GT_JMP:
9686             case GT_JCC:
9687             case GT_SETCC:
9688             case GT_NO_OP:
9689             case GT_START_NONGC:
9690             case GT_START_PREEMPTGC:
9691             case GT_PROF_HOOK:
9692 #if !FEATURE_EH_FUNCLETS
9693             case GT_END_LFIN:
9694 #endif // !FEATURE_EH_FUNCLETS
9695             case GT_PHI_ARG:
9696             case GT_JMPTABLE:
9697             case GT_CLS_VAR:
9698             case GT_CLS_VAR_ADDR:
9699             case GT_ARGPLACE:
9700             case GT_PHYSREG:
9701             case GT_EMITNOP:
9702             case GT_PINVOKE_PROLOG:
9703             case GT_PINVOKE_EPILOG:
9704             case GT_IL_OFFSET:
9705                 break;
9706
9707             // Lclvar unary operators
9708             case GT_STORE_LCL_VAR:
9709             case GT_STORE_LCL_FLD:
9710                 if (TVisitor::DoLclVarsOnly)
9711                 {
9712                     result = reinterpret_cast<TVisitor*>(this)->PreOrderVisit(use, user);
9713                     if (result == fgWalkResult::WALK_ABORT)
9714                     {
9715                         return result;
9716                     }
9717                 }
9718                 __fallthrough;
9719
9720             // Standard unary operators
9721             case GT_NOT:
9722             case GT_NEG:
9723             case GT_BSWAP:
9724             case GT_BSWAP16:
9725             case GT_COPY:
9726             case GT_RELOAD:
9727             case GT_ARR_LENGTH:
9728             case GT_CAST:
9729             case GT_BITCAST:
9730             case GT_CKFINITE:
9731             case GT_LCLHEAP:
9732             case GT_ADDR:
9733             case GT_IND:
9734             case GT_OBJ:
9735             case GT_BLK:
9736             case GT_BOX:
9737             case GT_ALLOCOBJ:
9738             case GT_INIT_VAL:
9739             case GT_JTRUE:
9740             case GT_SWITCH:
9741             case GT_NULLCHECK:
9742             case GT_PUTARG_REG:
9743             case GT_PUTARG_STK:
9744             case GT_RETURNTRAP:
9745             case GT_NOP:
9746             case GT_RETURN:
9747             case GT_RETFILT:
9748             case GT_PHI:
9749             case GT_RUNTIMELOOKUP:
9750             {
9751                 GenTreeUnOp* const unOp = node->AsUnOp();
9752                 if (unOp->gtOp1 != nullptr)
9753                 {
9754                     result = WalkTree(&unOp->gtOp1, unOp);
9755                     if (result == fgWalkResult::WALK_ABORT)
9756                     {
9757                         return result;
9758                     }
9759                 }
9760                 break;
9761             }
9762
9763             // Special nodes
9764             case GT_CMPXCHG:
9765             {
9766                 GenTreeCmpXchg* const cmpXchg = node->AsCmpXchg();
9767
9768                 result = WalkTree(&cmpXchg->gtOpLocation, cmpXchg);
9769                 if (result == fgWalkResult::WALK_ABORT)
9770                 {
9771                     return result;
9772                 }
9773                 result = WalkTree(&cmpXchg->gtOpValue, cmpXchg);
9774                 if (result == fgWalkResult::WALK_ABORT)
9775                 {
9776                     return result;
9777                 }
9778                 result = WalkTree(&cmpXchg->gtOpComparand, cmpXchg);
9779                 if (result == fgWalkResult::WALK_ABORT)
9780                 {
9781                     return result;
9782                 }
9783                 break;
9784             }
9785
9786             case GT_ARR_BOUNDS_CHECK:
9787 #ifdef FEATURE_SIMD
9788             case GT_SIMD_CHK:
9789 #endif // FEATURE_SIMD
9790 #ifdef FEATURE_HW_INTRINSICS
9791             case GT_HW_INTRINSIC_CHK:
9792 #endif // FEATURE_HW_INTRINSICS
9793             {
9794                 GenTreeBoundsChk* const boundsChk = node->AsBoundsChk();
9795
9796                 result = WalkTree(&boundsChk->gtIndex, boundsChk);
9797                 if (result == fgWalkResult::WALK_ABORT)
9798                 {
9799                     return result;
9800                 }
9801                 result = WalkTree(&boundsChk->gtArrLen, boundsChk);
9802                 if (result == fgWalkResult::WALK_ABORT)
9803                 {
9804                     return result;
9805                 }
9806                 break;
9807             }
9808
9809             case GT_FIELD:
9810             {
9811                 GenTreeField* const field = node->AsField();
9812
9813                 if (field->gtFldObj != nullptr)
9814                 {
9815                     result = WalkTree(&field->gtFldObj, field);
9816                     if (result == fgWalkResult::WALK_ABORT)
9817                     {
9818                         return result;
9819                     }
9820                 }
9821                 break;
9822             }
9823
9824             case GT_ARR_ELEM:
9825             {
9826                 GenTreeArrElem* const arrElem = node->AsArrElem();
9827
9828                 result = WalkTree(&arrElem->gtArrObj, arrElem);
9829                 if (result == fgWalkResult::WALK_ABORT)
9830                 {
9831                     return result;
9832                 }
9833
9834                 const unsigned rank = arrElem->gtArrRank;
9835                 for (unsigned dim = 0; dim < rank; dim++)
9836                 {
9837                     result = WalkTree(&arrElem->gtArrInds[dim], arrElem);
9838                     if (result == fgWalkResult::WALK_ABORT)
9839                     {
9840                         return result;
9841                     }
9842                 }
9843                 break;
9844             }
9845
9846             case GT_ARR_OFFSET:
9847             {
9848                 GenTreeArrOffs* const arrOffs = node->AsArrOffs();
9849
9850                 result = WalkTree(&arrOffs->gtOffset, arrOffs);
9851                 if (result == fgWalkResult::WALK_ABORT)
9852                 {
9853                     return result;
9854                 }
9855                 result = WalkTree(&arrOffs->gtIndex, arrOffs);
9856                 if (result == fgWalkResult::WALK_ABORT)
9857                 {
9858                     return result;
9859                 }
9860                 result = WalkTree(&arrOffs->gtArrObj, arrOffs);
9861                 if (result == fgWalkResult::WALK_ABORT)
9862                 {
9863                     return result;
9864                 }
9865                 break;
9866             }
9867
9868             case GT_DYN_BLK:
9869             {
9870                 GenTreeDynBlk* const dynBlock = node->AsDynBlk();
9871
9872                 GenTree** op1Use = &dynBlock->gtOp1;
9873                 GenTree** op2Use = &dynBlock->gtDynamicSize;
9874
9875                 if (TVisitor::UseExecutionOrder && dynBlock->gtEvalSizeFirst)
9876                 {
9877                     std::swap(op1Use, op2Use);
9878                 }
9879
9880                 result = WalkTree(op1Use, dynBlock);
9881                 if (result == fgWalkResult::WALK_ABORT)
9882                 {
9883                     return result;
9884                 }
9885                 result = WalkTree(op2Use, dynBlock);
9886                 if (result == fgWalkResult::WALK_ABORT)
9887                 {
9888                     return result;
9889                 }
9890                 break;
9891             }
9892
9893             case GT_STORE_DYN_BLK:
9894             {
9895                 GenTreeDynBlk* const dynBlock = node->AsDynBlk();
9896
9897                 GenTree** op1Use = &dynBlock->gtOp1;
9898                 GenTree** op2Use = &dynBlock->gtOp2;
9899                 GenTree** op3Use = &dynBlock->gtDynamicSize;
9900
9901                 if (TVisitor::UseExecutionOrder)
9902                 {
9903                     if (dynBlock->IsReverseOp())
9904                     {
9905                         std::swap(op1Use, op2Use);
9906                     }
9907                     if (dynBlock->gtEvalSizeFirst)
9908                     {
9909                         std::swap(op3Use, op2Use);
9910                         std::swap(op2Use, op1Use);
9911                     }
9912                 }
9913
9914                 result = WalkTree(op1Use, dynBlock);
9915                 if (result == fgWalkResult::WALK_ABORT)
9916                 {
9917                     return result;
9918                 }
9919                 result = WalkTree(op2Use, dynBlock);
9920                 if (result == fgWalkResult::WALK_ABORT)
9921                 {
9922                     return result;
9923                 }
9924                 result = WalkTree(op3Use, dynBlock);
9925                 if (result == fgWalkResult::WALK_ABORT)
9926                 {
9927                     return result;
9928                 }
9929                 break;
9930             }
9931
9932             case GT_CALL:
9933             {
9934                 GenTreeCall* const call = node->AsCall();
9935
9936                 if (call->gtCallObjp != nullptr)
9937                 {
9938                     result = WalkTree(&call->gtCallObjp, call);
9939                     if (result == fgWalkResult::WALK_ABORT)
9940                     {
9941                         return result;
9942                     }
9943                 }
9944
9945                 for (GenTreeArgList* args = call->gtCallArgs; args != nullptr; args = args->Rest())
9946                 {
9947                     result = WalkTree(args->pCurrent(), call);
9948                     if (result == fgWalkResult::WALK_ABORT)
9949                     {
9950                         return result;
9951                     }
9952                 }
9953
9954                 for (GenTreeArgList* args = call->gtCallLateArgs; args != nullptr; args = args->Rest())
9955                 {
9956                     result = WalkTree(args->pCurrent(), call);
9957                     if (result == fgWalkResult::WALK_ABORT)
9958                     {
9959                         return result;
9960                     }
9961                 }
9962
9963                 if (call->gtCallType == CT_INDIRECT)
9964                 {
9965                     if (call->gtCallCookie != nullptr)
9966                     {
9967                         result = WalkTree(&call->gtCallCookie, call);
9968                         if (result == fgWalkResult::WALK_ABORT)
9969                         {
9970                             return result;
9971                         }
9972                     }
9973
9974                     result = WalkTree(&call->gtCallAddr, call);
9975                     if (result == fgWalkResult::WALK_ABORT)
9976                     {
9977                         return result;
9978                     }
9979                 }
9980
9981                 if (call->gtControlExpr != nullptr)
9982                 {
9983                     result = WalkTree(&call->gtControlExpr, call);
9984                     if (result == fgWalkResult::WALK_ABORT)
9985                     {
9986                         return result;
9987                     }
9988                 }
9989
9990                 break;
9991             }
9992
9993             // Binary nodes
9994             default:
9995             {
9996                 assert(node->OperIsBinary());
9997
9998                 GenTreeOp* const op = node->AsOp();
9999
10000                 GenTree** op1Use = &op->gtOp1;
10001                 GenTree** op2Use = &op->gtOp2;
10002
10003                 if (TVisitor::UseExecutionOrder && node->IsReverseOp())
10004                 {
10005                     std::swap(op1Use, op2Use);
10006                 }
10007
10008                 if (*op1Use != nullptr)
10009                 {
10010                     result = WalkTree(op1Use, op);
10011                     if (result == fgWalkResult::WALK_ABORT)
10012                     {
10013                         return result;
10014                     }
10015                 }
10016
10017                 if (*op2Use != nullptr)
10018                 {
10019                     result = WalkTree(op2Use, op);
10020                     if (result == fgWalkResult::WALK_ABORT)
10021                     {
10022                         return result;
10023                     }
10024                 }
10025                 break;
10026             }
10027         }
10028
10029     DONE:
10030         // Finally, visit the current node
10031         if (TVisitor::DoPostOrder)
10032         {
10033             result = reinterpret_cast<TVisitor*>(this)->PostOrderVisit(use, user);
10034         }
10035
10036         if (TVisitor::ComputeStack)
10037         {
10038             m_ancestors.Pop();
10039         }
10040
10041         return result;
10042     }
10043 };
10044
10045 template <bool computeStack, bool doPreOrder, bool doPostOrder, bool doLclVarsOnly, bool useExecutionOrder>
10046 class GenericTreeWalker final
10047     : public GenTreeVisitor<GenericTreeWalker<computeStack, doPreOrder, doPostOrder, doLclVarsOnly, useExecutionOrder>>
10048 {
10049 public:
10050     enum
10051     {
10052         ComputeStack      = computeStack,
10053         DoPreOrder        = doPreOrder,
10054         DoPostOrder       = doPostOrder,
10055         DoLclVarsOnly     = doLclVarsOnly,
10056         UseExecutionOrder = useExecutionOrder,
10057     };
10058
10059 private:
10060     Compiler::fgWalkData* m_walkData;
10061
10062 public:
10063     GenericTreeWalker(Compiler::fgWalkData* walkData)
10064         : GenTreeVisitor<GenericTreeWalker<computeStack, doPreOrder, doPostOrder, doLclVarsOnly, useExecutionOrder>>(
10065               walkData->compiler)
10066         , m_walkData(walkData)
10067     {
10068         assert(walkData != nullptr);
10069
10070         if (computeStack)
10071         {
10072             walkData->parentStack = &this->m_ancestors;
10073         }
10074     }
10075
10076     Compiler::fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
10077     {
10078         m_walkData->parent = user;
10079         return m_walkData->wtprVisitorFn(use, m_walkData);
10080     }
10081
10082     Compiler::fgWalkResult PostOrderVisit(GenTree** use, GenTree* user)
10083     {
10084         m_walkData->parent = user;
10085         return m_walkData->wtpoVisitorFn(use, m_walkData);
10086     }
10087 };
10088
10089 /*
10090 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10091 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10092 XX                                                                           XX
10093 XX                   Miscellaneous Compiler stuff                            XX
10094 XX                                                                           XX
10095 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10096 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10097 */
10098
10099 // Values used to mark the types a stack slot is used for
10100
10101 const unsigned TYPE_REF_INT      = 0x01; // slot used as a 32-bit int
10102 const unsigned TYPE_REF_LNG      = 0x02; // slot used as a 64-bit long
10103 const unsigned TYPE_REF_FLT      = 0x04; // slot used as a 32-bit float
10104 const unsigned TYPE_REF_DBL      = 0x08; // slot used as a 64-bit float
10105 const unsigned TYPE_REF_PTR      = 0x10; // slot used as a 32-bit pointer
10106 const unsigned TYPE_REF_BYR      = 0x20; // slot used as a byref pointer
10107 const unsigned TYPE_REF_STC      = 0x40; // slot used as a struct
10108 const unsigned TYPE_REF_TYPEMASK = 0x7F; // bits that represent the type
10109
10110 // const unsigned TYPE_REF_ADDR_TAKEN  = 0x80; // slots address was taken
10111
10112 /*****************************************************************************
10113  *
10114  *  Variables to keep track of total code amounts.
10115  */
10116
10117 #if DISPLAY_SIZES
10118
10119 extern size_t grossVMsize;
10120 extern size_t grossNCsize;
10121 extern size_t totalNCsize;
10122
10123 extern unsigned genMethodICnt;
10124 extern unsigned genMethodNCnt;
10125 extern size_t   gcHeaderISize;
10126 extern size_t   gcPtrMapISize;
10127 extern size_t   gcHeaderNSize;
10128 extern size_t   gcPtrMapNSize;
10129
10130 #endif // DISPLAY_SIZES
10131
10132 /*****************************************************************************
10133  *
10134  *  Variables to keep track of basic block counts (more data on 1 BB methods)
10135  */
10136
10137 #if COUNT_BASIC_BLOCKS
10138 extern Histogram bbCntTable;
10139 extern Histogram bbOneBBSizeTable;
10140 #endif
10141
10142 /*****************************************************************************
10143  *
10144  *  Used by optFindNaturalLoops to gather statistical information such as
10145  *   - total number of natural loops
10146  *   - number of loops with 1, 2, ... exit conditions
10147  *   - number of loops that have an iterator (for like)
10148  *   - number of loops that have a constant iterator
10149  */
10150
10151 #if COUNT_LOOPS
10152
10153 extern unsigned totalLoopMethods;        // counts the total number of methods that have natural loops
10154 extern unsigned maxLoopsPerMethod;       // counts the maximum number of loops a method has
10155 extern unsigned totalLoopOverflows;      // # of methods that identified more loops than we can represent
10156 extern unsigned totalLoopCount;          // counts the total number of natural loops
10157 extern unsigned totalUnnatLoopCount;     // counts the total number of (not-necessarily natural) loops
10158 extern unsigned totalUnnatLoopOverflows; // # of methods that identified more unnatural loops than we can represent
10159 extern unsigned iterLoopCount;           // counts the # of loops with an iterator (for like)
10160 extern unsigned simpleTestLoopCount;     // counts the # of loops with an iterator and a simple loop condition (iter <
10161                                          // const)
10162 extern unsigned  constIterLoopCount;     // counts the # of loops with a constant iterator (for like)
10163 extern bool      hasMethodLoops;         // flag to keep track if we already counted a method as having loops
10164 extern unsigned  loopsThisMethod;        // counts the number of loops in the current method
10165 extern bool      loopOverflowThisMethod; // True if we exceeded the max # of loops in the method.
10166 extern Histogram loopCountTable;         // Histogram of loop counts
10167 extern Histogram loopExitCountTable;     // Histogram of loop exit counts
10168
10169 #endif // COUNT_LOOPS
10170
10171 /*****************************************************************************
10172  * variables to keep track of how many iterations we go in a dataflow pass
10173  */
10174
10175 #if DATAFLOW_ITER
10176
10177 extern unsigned CSEiterCount; // counts the # of iteration for the CSE dataflow
10178 extern unsigned CFiterCount;  // counts the # of iteration for the Const Folding dataflow
10179
10180 #endif // DATAFLOW_ITER
10181
10182 #if MEASURE_BLOCK_SIZE
10183 extern size_t genFlowNodeSize;
10184 extern size_t genFlowNodeCnt;
10185 #endif // MEASURE_BLOCK_SIZE
10186
10187 #if MEASURE_NODE_SIZE
10188 struct NodeSizeStats
10189 {
10190     void Init()
10191     {
10192         genTreeNodeCnt        = 0;
10193         genTreeNodeSize       = 0;
10194         genTreeNodeActualSize = 0;
10195     }
10196
10197     // Count of tree nodes allocated.
10198     unsigned __int64 genTreeNodeCnt;
10199
10200     // The size we allocate.
10201     unsigned __int64 genTreeNodeSize;
10202
10203     // The actual size of the node. Note that the actual size will likely be smaller
10204     // than the allocated size, but we sometimes use SetOper()/ChangeOper() to change
10205     // a smaller node to a larger one. TODO-Cleanup: add stats on
10206     // SetOper()/ChangeOper() usage to quantify this.
10207     unsigned __int64 genTreeNodeActualSize;
10208 };
10209 extern NodeSizeStats genNodeSizeStats;        // Total node size stats
10210 extern NodeSizeStats genNodeSizeStatsPerFunc; // Per-function node size stats
10211 extern Histogram     genTreeNcntHist;
10212 extern Histogram     genTreeNsizHist;
10213 #endif // MEASURE_NODE_SIZE
10214
10215 /*****************************************************************************
10216  *  Count fatal errors (including noway_asserts).
10217  */
10218
10219 #if MEASURE_FATAL
10220 extern unsigned fatal_badCode;
10221 extern unsigned fatal_noWay;
10222 extern unsigned fatal_NOMEM;
10223 extern unsigned fatal_noWayAssertBody;
10224 #ifdef DEBUG
10225 extern unsigned fatal_noWayAssertBodyArgs;
10226 #endif // DEBUG
10227 extern unsigned fatal_NYI;
10228 #endif // MEASURE_FATAL
10229
10230 /*****************************************************************************
10231  * Codegen
10232  */
10233
10234 #ifdef _TARGET_XARCH_
10235
10236 const instruction INS_SHIFT_LEFT_LOGICAL  = INS_shl;
10237 const instruction INS_SHIFT_RIGHT_LOGICAL = INS_shr;
10238 const instruction INS_SHIFT_RIGHT_ARITHM  = INS_sar;
10239
10240 const instruction INS_AND             = INS_and;
10241 const instruction INS_OR              = INS_or;
10242 const instruction INS_XOR             = INS_xor;
10243 const instruction INS_NEG             = INS_neg;
10244 const instruction INS_TEST            = INS_test;
10245 const instruction INS_MUL             = INS_imul;
10246 const instruction INS_SIGNED_DIVIDE   = INS_idiv;
10247 const instruction INS_UNSIGNED_DIVIDE = INS_div;
10248 const instruction INS_BREAKPOINT      = INS_int3;
10249 const instruction INS_ADDC            = INS_adc;
10250 const instruction INS_SUBC            = INS_sbb;
10251 const instruction INS_NOT             = INS_not;
10252
10253 #endif // _TARGET_XARCH_
10254
10255 #ifdef _TARGET_ARM_
10256
10257 const instruction INS_SHIFT_LEFT_LOGICAL  = INS_lsl;
10258 const instruction INS_SHIFT_RIGHT_LOGICAL = INS_lsr;
10259 const instruction INS_SHIFT_RIGHT_ARITHM  = INS_asr;
10260
10261 const instruction INS_AND             = INS_and;
10262 const instruction INS_OR              = INS_orr;
10263 const instruction INS_XOR             = INS_eor;
10264 const instruction INS_NEG             = INS_rsb;
10265 const instruction INS_TEST            = INS_tst;
10266 const instruction INS_MUL             = INS_mul;
10267 const instruction INS_MULADD          = INS_mla;
10268 const instruction INS_SIGNED_DIVIDE   = INS_sdiv;
10269 const instruction INS_UNSIGNED_DIVIDE = INS_udiv;
10270 const instruction INS_BREAKPOINT      = INS_bkpt;
10271 const instruction INS_ADDC            = INS_adc;
10272 const instruction INS_SUBC            = INS_sbc;
10273 const instruction INS_NOT             = INS_mvn;
10274
10275 const instruction INS_ABS  = INS_vabs;
10276 const instruction INS_SQRT = INS_vsqrt;
10277
10278 #endif // _TARGET_ARM_
10279
10280 #ifdef _TARGET_ARM64_
10281
10282 const instruction INS_MULADD     = INS_madd;
10283 const instruction INS_BREAKPOINT = INS_bkpt;
10284
10285 const instruction INS_ABS  = INS_fabs;
10286 const instruction INS_SQRT = INS_fsqrt;
10287
10288 #endif // _TARGET_ARM64_
10289
10290 /*****************************************************************************/
10291
10292 extern const BYTE genTypeSizes[];
10293 extern const BYTE genTypeAlignments[];
10294 extern const BYTE genTypeStSzs[];
10295 extern const BYTE genActualTypes[];
10296
10297 /*****************************************************************************/
10298
10299 // VERY_LARGE_FRAME_SIZE_REG_MASK is the set of registers we need to use for
10300 // the probing loop generated for very large stack frames (see `getVeryLargeFrameSize`).
10301
10302 #ifdef _TARGET_ARM_
10303 #define VERY_LARGE_FRAME_SIZE_REG_MASK (RBM_R4 | RBM_R5 | RBM_R6)
10304 #elif defined(_TARGET_ARM64_)
10305 #define VERY_LARGE_FRAME_SIZE_REG_MASK (RBM_R9 | RBM_R10 | RBM_R11)
10306 #endif
10307
10308 /*****************************************************************************/
10309
10310 extern BasicBlock dummyBB;
10311
10312 /*****************************************************************************/
10313 /*****************************************************************************/
10314
10315 // foreach_treenode_execution_order: An iterator that iterates through all the tree
10316 // nodes of a statement in execution order.
10317 //      __stmt: a GT_STMT type GenTree*
10318 //      __node: a GenTree*, already declared, that gets updated with each node in the statement, in execution order
10319
10320 #define foreach_treenode_execution_order(__node, __stmt)                                                               \
10321     for ((__node) = (__stmt)->gtStmt.gtStmtList; (__node); (__node) = (__node)->gtNext)
10322
10323 // foreach_block: An iterator over all blocks in the function.
10324 //    __compiler: the Compiler* object
10325 //    __block   : a BasicBlock*, already declared, that gets updated each iteration.
10326
10327 #define foreach_block(__compiler, __block)                                                                             \
10328     for ((__block) = (__compiler)->fgFirstBB; (__block); (__block) = (__block)->bbNext)
10329
10330 /*****************************************************************************/
10331 /*****************************************************************************/
10332
10333 #ifdef DEBUG
10334
10335 void dumpConvertedVarSet(Compiler* comp, VARSET_VALARG_TP vars);
10336
10337 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10338 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10339 XX                                                                           XX
10340 XX                          Debugging helpers                                XX
10341 XX                                                                           XX
10342 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10343 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10344 */
10345
10346 /*****************************************************************************/
10347 /* The following functions are intended to be called from the debugger, to dump
10348  * various data structures. The can be used in the debugger Watch or Quick Watch
10349  * windows. They are designed to be short to type and take as few arguments as
10350  * possible. The 'c' versions take a Compiler*, whereas the 'd' versions use the TlsCompiler.
10351  * See the function definition comment for more details.
10352  */
10353
10354 void cBlock(Compiler* comp, BasicBlock* block);
10355 void cBlocks(Compiler* comp);
10356 void cBlocksV(Compiler* comp);
10357 void cTree(Compiler* comp, GenTree* tree);
10358 void cTrees(Compiler* comp);
10359 void cEH(Compiler* comp);
10360 void cVar(Compiler* comp, unsigned lclNum);
10361 void cVarDsc(Compiler* comp, LclVarDsc* varDsc);
10362 void cVars(Compiler* comp);
10363 void cVarsFinal(Compiler* comp);
10364 void cBlockPreds(Compiler* comp, BasicBlock* block);
10365 void cReach(Compiler* comp);
10366 void cDoms(Compiler* comp);
10367 void cLiveness(Compiler* comp);
10368 void cCVarSet(Compiler* comp, VARSET_VALARG_TP vars);
10369
10370 void cFuncIR(Compiler* comp);
10371 void cBlockIR(Compiler* comp, BasicBlock* block);
10372 void cLoopIR(Compiler* comp, Compiler::LoopDsc* loop);
10373 void cTreeIR(Compiler* comp, GenTree* tree);
10374 int cTreeTypeIR(Compiler* comp, GenTree* tree);
10375 int cTreeKindsIR(Compiler* comp, GenTree* tree);
10376 int cTreeFlagsIR(Compiler* comp, GenTree* tree);
10377 int cOperandIR(Compiler* comp, GenTree* operand);
10378 int cLeafIR(Compiler* comp, GenTree* tree);
10379 int cIndirIR(Compiler* comp, GenTree* tree);
10380 int cListIR(Compiler* comp, GenTree* list);
10381 int cSsaNumIR(Compiler* comp, GenTree* tree);
10382 int cValNumIR(Compiler* comp, GenTree* tree);
10383 int cDependsIR(Compiler* comp, GenTree* comma, bool* first);
10384
10385 void dBlock(BasicBlock* block);
10386 void dBlocks();
10387 void dBlocksV();
10388 void dTree(GenTree* tree);
10389 void dTrees();
10390 void dEH();
10391 void dVar(unsigned lclNum);
10392 void dVarDsc(LclVarDsc* varDsc);
10393 void dVars();
10394 void dVarsFinal();
10395 void dBlockPreds(BasicBlock* block);
10396 void dReach();
10397 void dDoms();
10398 void dLiveness();
10399 void dCVarSet(VARSET_VALARG_TP vars);
10400
10401 void dRegMask(regMaskTP mask);
10402
10403 void dFuncIR();
10404 void dBlockIR(BasicBlock* block);
10405 void dTreeIR(GenTree* tree);
10406 void dLoopIR(Compiler::LoopDsc* loop);
10407 void dLoopNumIR(unsigned loopNum);
10408 int dTabStopIR(int curr, int tabstop);
10409 int dTreeTypeIR(GenTree* tree);
10410 int dTreeKindsIR(GenTree* tree);
10411 int dTreeFlagsIR(GenTree* tree);
10412 int dOperandIR(GenTree* operand);
10413 int dLeafIR(GenTree* tree);
10414 int dIndirIR(GenTree* tree);
10415 int dListIR(GenTree* list);
10416 int dSsaNumIR(GenTree* tree);
10417 int dValNumIR(GenTree* tree);
10418 int dDependsIR(GenTree* comma);
10419 void dFormatIR();
10420
10421 GenTree* dFindTree(GenTree* tree, unsigned id);
10422 GenTree* dFindTree(unsigned id);
10423 GenTreeStmt* dFindStmt(unsigned id);
10424 BasicBlock* dFindBlock(unsigned bbNum);
10425
10426 #endif // DEBUG
10427
10428 #include "compiler.hpp" // All the shared inline functions
10429
10430 /*****************************************************************************/
10431 #endif //_COMPILER_H_
10432 /*****************************************************************************/