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