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