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