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