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