Merge pull request #6050 from prajwal-aithal/devel/arm-ci-runtests
[platform/upstream/coreclr.git] / src / jit / gentree.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                          GenTree                                          XX
9 XX                                                                           XX
10 XX  This is the node in the semantic tree graph. It represents the operation XX
11 XX  corresponding to the node, and other information during code-gen.        XX
12 XX                                                                           XX
13 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
14 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
15 */
16
17 /*****************************************************************************/
18 #ifndef _GENTREE_H_
19 #define _GENTREE_H_
20 /*****************************************************************************/
21
22 #include "vartype.h"    // For "var_types"
23 #include "target.h"     // For "regNumber"
24 #include "ssaconfig.h"  // For "SsaConfig::RESERVED_SSA_NUM"
25 #include "reglist.h"
26 #include "valuenumtype.h"
27 #include "simplerhash.h"
28 #include "nodeinfo.h"
29 #include "simd.h"
30
31 // Debugging GenTree is much easier if we add a magic virtual function to make the debugger able to figure out what type it's got.
32 // This is enabled by default in DEBUG. To enable it in RET builds (temporarily!), you need to change the build to define DEBUGGABLE_GENTREE=1,
33 // as well as pass /OPT:NOICF to the linker (or else all the vtables get merged, making the debugging value supplied by them useless).
34 // See protojit.nativeproj for a commented example of setting the build flags correctly.
35 #ifndef DEBUGGABLE_GENTREE
36 #ifdef DEBUG
37 #define DEBUGGABLE_GENTREE  1
38 #else // !DEBUG
39 #define DEBUGGABLE_GENTREE  0
40 #endif // !DEBUG
41 #endif // !DEBUGGABLE_GENTREE
42
43 // The SpecialCodeKind enum is used to indicate the type of special (unique)
44 // target block that will be targeted by an instruction.
45 // These are used by:
46 //   GenTreeBoundsChk nodes (SCK_RNGCHK_FAIL, SCK_ARG_EXCPN, SCK_ARG_RNG_EXCPN)
47 //     - these nodes have a field (gtThrowKind) to indicate which kind
48 //   GenTreeOps nodes, for which codegen will generate the branch
49 //     - it will use the appropriate kind based on the opcode, though it's not
50 //       clear why SCK_OVERFLOW == SCK_ARITH_EXCPN
51 // SCK_PAUSE_EXEC is not currently used.
52 //   
53 enum        SpecialCodeKind
54 {
55     SCK_NONE,
56     SCK_RNGCHK_FAIL,                // target when range check fails
57     SCK_PAUSE_EXEC,                 // target to stop (e.g. to allow GC)
58     SCK_DIV_BY_ZERO,                // target for divide by zero (Not used on X86/X64)
59     SCK_ARITH_EXCPN,                // target on arithmetic exception
60     SCK_OVERFLOW = SCK_ARITH_EXCPN, // target on overflow
61     SCK_ARG_EXCPN,                  // target on ArgumentException (currently used only for SIMD intrinsics)
62     SCK_ARG_RNG_EXCPN,              // target on ArgumentOutOfRangeException (currently used only for SIMD intrinsics)
63     SCK_COUNT
64 };
65
66 /*****************************************************************************/
67
68 DECLARE_TYPED_ENUM(genTreeOps,BYTE)
69 {
70     #define GTNODE(en,sn,cm,ok) GT_ ## en,
71     #include "gtlist.h"
72
73     GT_COUNT,
74
75     // GT_CNS_NATIVELONG is the gtOper symbol for GT_CNS_LNG or GT_CNS_INT, depending on the target.
76     // For the 64-bit targets we will only use GT_CNS_INT as it used to represent all the possible sizes
77     // For the 32-bit targets we use a GT_CNS_LNG to hold a 64-bit integer constant and GT_CNS_INT for all others.
78     // In the future when we retarget the JIT for x86 we should consider eliminating GT_CNS_LNG
79     //
80 #ifdef _TARGET_64BIT_
81     GT_CNS_NATIVELONG = GT_CNS_INT,
82 #else
83     GT_CNS_NATIVELONG = GT_CNS_LNG,
84 #endif
85 }
86 END_DECLARE_TYPED_ENUM(genTreeOps,BYTE)
87
88 /*****************************************************************************
89  *
90  *  The following enum defines a set of bit flags that can be used
91  *  to classify expression tree nodes. Note that some operators will
92  *  have more than one bit set, as follows:
93  *
94  *          GTK_CONST    implies    GTK_LEAF
95  *          GTK_RELOP    implies    GTK_BINOP
96  *          GTK_LOGOP    implies    GTK_BINOP
97  */
98
99 enum genTreeKinds
100 {
101     GTK_SPECIAL = 0x0000,       // unclassified operator (special handling reqd)
102
103     GTK_CONST   = 0x0001,       // constant     operator
104     GTK_LEAF    = 0x0002,       // leaf         operator
105     GTK_UNOP    = 0x0004,       // unary        operator
106     GTK_BINOP   = 0x0008,       // binary       operator
107     GTK_RELOP   = 0x0010,       // comparison   operator
108     GTK_LOGOP   = 0x0020,       // logical      operator
109     GTK_ASGOP   = 0x0040,       // assignment   operator
110
111     GTK_KINDMASK= 0x007F,       // operator kind mask
112
113     GTK_COMMUTE = 0x0080,       // commutative  operator
114
115     GTK_EXOP    = 0x0100,       // Indicates that an oper for a node type that extends GenTreeOp (or GenTreeUnOp)
116                                 // by adding non-node fields to unary or binary operator.
117
118     GTK_LOCAL   = 0x0200,       // is a local access (load, store, phi)
119
120     /* Define composite value(s) */
121
122     GTK_SMPOP   = (GTK_UNOP|GTK_BINOP|GTK_RELOP|GTK_LOGOP)
123 };
124
125 /*****************************************************************************/
126
127 #define SMALL_TREE_NODES    1
128
129 /*****************************************************************************/
130
131 DECLARE_TYPED_ENUM(gtCallTypes,BYTE)
132 {
133     CT_USER_FUNC,       // User function
134     CT_HELPER,          // Jit-helper
135     CT_INDIRECT,        // Indirect call
136
137     CT_COUNT            // fake entry (must be last)
138 }
139 END_DECLARE_TYPED_ENUM(gtCallTypes,BYTE)
140
141
142 /*****************************************************************************/
143
144 struct                  BasicBlock;
145  
146 struct                  InlineCandidateInfo;
147
148 /*****************************************************************************/
149
150 // GT_FIELD nodes will be lowered into more "code-gen-able" representations, like
151 // GT_IND's of addresses, or GT_LCL_FLD nodes.  We'd like to preserve the more abstract
152 // information, and will therefore annotate such lowered nodes with FieldSeq's.  A FieldSeq
153 // represents a (possibly) empty sequence of fields.  The fields are in the order
154 // in which they are dereferenced.  The first field may be an object field or a struct field;
155 // all subsequent fields must be struct fields.
156 struct FieldSeqNode
157 {
158     CORINFO_FIELD_HANDLE m_fieldHnd;
159     FieldSeqNode*        m_next;
160
161     FieldSeqNode(CORINFO_FIELD_HANDLE fieldHnd, FieldSeqNode* next) : m_fieldHnd(fieldHnd), m_next(next) {}
162
163     // returns true when this is the pseudo #FirstElem field sequence
164     bool IsFirstElemFieldSeq();
165
166     // returns true when this is the pseudo #ConstantIndex field sequence
167     bool IsConstantIndexFieldSeq();
168
169     // returns true when this is the the pseudo #FirstElem field sequence or the pseudo #ConstantIndex field sequence
170     bool IsPseudoField();
171
172     // Make sure this provides methods that allow it to be used as a KeyFuncs type in SimplerHash.
173     static int GetHashCode(FieldSeqNode fsn)
174     {
175         return static_cast<int>(reinterpret_cast<intptr_t>(fsn.m_fieldHnd)) ^ static_cast<int>(reinterpret_cast<intptr_t>(fsn.m_next));
176     }
177
178     static bool Equals(FieldSeqNode fsn1, FieldSeqNode fsn2)
179     {
180         return fsn1.m_fieldHnd == fsn2.m_fieldHnd && fsn1.m_next == fsn2.m_next;
181     }
182 };
183
184 // This class canonicalizes field sequences.
185 class FieldSeqStore
186 {
187     typedef SimplerHashTable<FieldSeqNode, /*KeyFuncs*/FieldSeqNode, FieldSeqNode*, JitSimplerHashBehavior> FieldSeqNodeCanonMap;
188
189     IAllocator*           m_alloc;
190     FieldSeqNodeCanonMap* m_canonMap;
191
192     static FieldSeqNode   s_notAField;  // No value, just exists to provide an address.
193
194     // Dummy variables to provide the addresses for the "pseudo field handle" statics below.
195     static int FirstElemPseudoFieldStruct;
196     static int ConstantIndexPseudoFieldStruct;
197
198 public:
199     FieldSeqStore(IAllocator* alloc);
200
201     // Returns the (canonical in the store) singleton field sequence for the given handle.
202     FieldSeqNode* CreateSingleton(CORINFO_FIELD_HANDLE fieldHnd);
203
204     // This is a special distinguished FieldSeqNode indicating that a constant does *not*
205     // represent a valid field sequence.  This is "infectious", in the sense that appending it
206     // (on either side) to any field sequence yields the "NotAField()" sequence.
207     static FieldSeqNode* NotAField() { return &s_notAField; }
208
209     // Returns the (canonical in the store) field sequence representing the concatenation of
210     // the sequences represented by "a" and "b".  Assumes that "a" and "b" are canonical; that is,
211     // they are the results of CreateSingleton, NotAField, or Append calls.  If either of the arguments
212     // are the "NotAField" value, so is the result.
213     FieldSeqNode* Append(FieldSeqNode* a, FieldSeqNode* b);
214
215     // We have a few "pseudo" field handles:
216
217     // This treats the constant offset of the first element of something as if it were a field.
218     // Works for method table offsets of boxed structs, or first elem offset of arrays/strings.
219     static CORINFO_FIELD_HANDLE FirstElemPseudoField;
220
221     // If there is a constant index, we make a psuedo field to correspond to the constant added to
222     // offset of the indexed field.  This keeps the field sequence structure "normalized", especially in the
223     // case where the element type is a struct, so we might add a further struct field offset.
224     static CORINFO_FIELD_HANDLE ConstantIndexPseudoField;
225
226     static bool IsPseudoField(CORINFO_FIELD_HANDLE hnd)
227     {
228         return hnd == FirstElemPseudoField || hnd == ConstantIndexPseudoField;
229     }
230 };
231
232
233
234 /*****************************************************************************/
235
236 typedef struct GenTree *  GenTreePtr;
237 struct GenTreeArgList;
238
239 // Forward declarations of the subtypes
240 #define GTSTRUCT_0(fn, en)                struct GenTree##fn;
241 #define GTSTRUCT_1(fn, en)                struct GenTree##fn;
242 #define GTSTRUCT_2(fn, en, en2)           struct GenTree##fn;
243 #define GTSTRUCT_3(fn, en, en2, en3)      struct GenTree##fn;
244 #define GTSTRUCT_4(fn, en, en2, en3, en4) struct GenTree##fn;
245 #define GTSTRUCT_N(fn, ...) struct GenTree##fn;
246 #include "gtstructs.h"
247
248 /*****************************************************************************/
249
250 #ifndef _HOST_64BIT_
251 #include <pshpack4.h>
252 #endif
253
254 struct GenTree
255 {
256     // We use GT_STRUCT_0 only for the category of simple ops.
257 #define GTSTRUCT_0(fn, en)           GenTree##fn* As##fn() \
258                                      { \
259                                          assert(this->OperIsSimple()); \
260                                          return reinterpret_cast<GenTree##fn*>(this); \
261                                      } \
262                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
263                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
264 #define GTSTRUCT_1(fn, en)           GenTree##fn* As##fn() \
265                                      { \
266                                          assert(this->gtOper == en); \
267                                          return reinterpret_cast<GenTree##fn*>(this); \
268                                      } \
269                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
270                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
271 #define GTSTRUCT_2(fn, en, en2)      GenTree##fn* As##fn() \
272                                      { \
273                                          assert(this->gtOper == en || this->gtOper == en2); \
274                                          return reinterpret_cast<GenTree##fn*>(this); \
275                                      } \
276                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
277                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
278 #define GTSTRUCT_3(fn, en, en2, en3) GenTree##fn* As##fn() \
279                                      { \
280                                          assert(this->gtOper == en || this->gtOper == en2 || this->gtOper == en3); \
281                                          return reinterpret_cast<GenTree##fn*>(this); \
282                                      } \
283                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
284                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
285
286 #define GTSTRUCT_4(fn, en, en2, en3, en4) GenTree##fn* As##fn() \
287                                      { \
288                                          assert(this->gtOper == en || this->gtOper == en2 || this->gtOper == en3 || this->gtOper == en4); \
289                                          return reinterpret_cast<GenTree##fn*>(this); \
290                                      } \
291                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
292                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
293
294 #ifdef DEBUG
295 // VC does not optimize out this loop in retail even though the value it computes is unused
296 // so we need a separate version for non-debug
297 #define GTSTRUCT_N(fn, ...)          GenTree##fn* As##fn() \
298                                      { \
299                                          genTreeOps validOps[] = {__VA_ARGS__}; \
300                                          bool found = false;            \
301                                          for (unsigned i=0; i<ArrLen(validOps); i++) { \
302                                              if (this->gtOper == validOps[i]) \
303                                              {                          \
304                                                  found = true;          \
305                                                  break;                 \
306                                              }                          \
307                                          }                              \
308                                          assert(found);                 \
309                                          return reinterpret_cast<GenTree##fn*>(this); \
310                                      }                                  \
311                                      GenTree##fn& As##fn##Ref() { return *As##fn(); }                    \
312                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
313 #else
314 #define GTSTRUCT_N(fn, ...)          GenTree##fn* As##fn()    \
315                                      { \
316                                          return reinterpret_cast<GenTree##fn*>(this); \
317                                      }                                  \
318                                      GenTree##fn& As##fn##Ref() { return *As##fn(); }                    \
319                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
320 #endif
321
322 #include "gtstructs.h"
323
324     genTreeOps          gtOper;       // enum subtype BYTE
325     var_types           gtType;       // enum subtype BYTE 
326
327     genTreeOps          OperGet() const { return gtOper; }
328     var_types           TypeGet() const { return gtType; }
329
330 #ifdef DEBUG
331     genTreeOps          gtOperSave;   // Only used to save gtOper when we destroy a node, to aid debugging.
332 #endif
333
334 #if FEATURE_ANYCSE
335
336 #define NO_CSE           (0)
337
338 #define IS_CSE_INDEX(x)  (x != 0)
339 #define IS_CSE_USE(x)    (x > 0)
340 #define IS_CSE_DEF(x)    (x < 0)
341 #define GET_CSE_INDEX(x) ((x > 0) ? x : -x)
342 #define TO_CSE_DEF(x)    (-x)
343
344     signed char       gtCSEnum;        // 0 or the CSE index (negated if def)
345                                        // valid only for CSE expressions
346
347 #endif // FEATURE_ANYCSE
348
349 #if ASSERTION_PROP
350     unsigned short     gtAssertionNum;  // 0 or Assertion table index
351                                         // valid only for non-GT_STMT nodes
352
353     bool         HasAssertion() const             { return gtAssertionNum != 0; }
354     void         ClearAssertion()                 { gtAssertionNum = 0;         }
355
356     unsigned short GetAssertion() const             { return gtAssertionNum;  }
357     void           SetAssertion(unsigned short value) { assert((unsigned short)value == value); gtAssertionNum = (unsigned short)value; }
358
359 #endif
360
361 #if FEATURE_STACK_FP_X87
362     unsigned char       gtFPlvl;        // x87 stack depth at this node
363     void                gtCopyFPlvl(GenTree * other) { gtFPlvl = other->gtFPlvl; }
364     void                gtSetFPlvl(unsigned level) { noway_assert(FitsIn<unsigned char>(level)); gtFPlvl = (unsigned char)level; }
365 #else // FEATURE_STACK_FP_X87
366     void                gtCopyFPlvl(GenTree * other) { }
367     void                gtSetFPlvl(unsigned level) { }
368 #endif // FEATURE_STACK_FP_X87
369
370     //
371     // Cost metrics on the node. Don't allow direct access to the variable for setting.
372     //
373
374 public:
375
376 #ifdef DEBUG
377     // You are not allowed to read the cost values before they have been set in gtSetEvalOrder().
378     // Keep track of whether the costs have been initialized, and assert if they are read before being initialized.
379     // Obviously, this information does need to be initialized when a node is created.
380     // This is public so the dumpers can see it.
381
382     bool gtCostsInitialized;
383 #endif // DEBUG
384
385 #define MAX_COST        UCHAR_MAX
386 #define IND_COST_EX     3             // execution cost for an indirection
387
388     __declspec(property(get=GetCostEx))
389     unsigned char    gtCostEx;     // estimate of expression execution cost
390
391     __declspec(property(get=GetCostSz))
392     unsigned char    gtCostSz;     // estimate of expression code size cost
393
394     unsigned char GetCostEx() const { assert(gtCostsInitialized); return _gtCostEx; }
395     unsigned char GetCostSz() const { assert(gtCostsInitialized); return _gtCostSz; }
396
397     // Set the costs. They are always both set at the same time.
398     // Don't use the "put" property: force calling this function, to make it more obvious in the few places
399     // that set the values.
400     // Note that costs are only set in gtSetEvalOrder() and its callees.
401     void            SetCosts(unsigned costEx, unsigned costSz)
402     {
403         assert(costEx != (unsigned)-1); // looks bogus
404         assert(costSz != (unsigned)-1); // looks bogus
405         INDEBUG(gtCostsInitialized = true;)
406
407         _gtCostEx = (costEx > MAX_COST) ? MAX_COST : (unsigned char)costEx;
408         _gtCostSz = (costSz > MAX_COST) ? MAX_COST : (unsigned char)costSz;
409     }
410
411     // Opimized copy function, to avoid the SetCosts() function comparisons, and make it more clear that a node copy is happening.
412     void            CopyCosts(const GenTree* const tree)
413     {
414         INDEBUG(gtCostsInitialized = tree->gtCostsInitialized;) // If the 'tree' costs aren't initialized, we'll hit an assert below.
415         _gtCostEx = tree->gtCostEx;
416         _gtCostSz = tree->gtCostSz;
417     }
418
419     // Same as CopyCosts, but avoids asserts if the costs we are copying have not been initialized.
420     // This is because the importer, for example, clones nodes, before these costs have been initialized.
421     // Note that we directly access the 'tree' costs, not going through the accessor functions (either
422     // directly or through the properties).
423     void            CopyRawCosts(const GenTree* const tree)
424     {
425         INDEBUG(gtCostsInitialized = tree->gtCostsInitialized;)
426         _gtCostEx = tree->_gtCostEx;
427         _gtCostSz = tree->_gtCostSz;
428     }
429
430 private:
431
432     unsigned char    _gtCostEx;     // estimate of expression execution cost
433     unsigned char    _gtCostSz;     // estimate of expression code size cost
434
435     //
436     // Register or register pair number of the node.
437     //
438
439 #ifdef DEBUG
440 public:
441     enum genRegTag
442     {
443         GT_REGTAG_NONE,     // Nothing has been assigned to _gtRegNum/_gtRegPair
444         GT_REGTAG_REG,      // _gtRegNum  has been assigned
445 #if CPU_LONG_USES_REGPAIR
446         GT_REGTAG_REGPAIR   // _gtRegPair has been assigned
447 #endif
448     };
449     genRegTag GetRegTag() const
450     {
451 #if CPU_LONG_USES_REGPAIR
452         assert(gtRegTag == GT_REGTAG_NONE || gtRegTag == GT_REGTAG_REG || gtRegTag == GT_REGTAG_REGPAIR);
453 #else
454         assert(gtRegTag == GT_REGTAG_NONE || gtRegTag == GT_REGTAG_REG);
455 #endif
456         return gtRegTag;
457     }
458 private:
459     genRegTag           gtRegTag; // What is in _gtRegNum/_gtRegPair?
460 #endif // DEBUG
461
462 private:
463
464     union
465     { 
466         // NOTE: After LSRA, one of these values may be valid even if GTF_REG_VAL is not set in gtFlags.
467         // They store the register assigned to the node. If a register is not assigned, _gtRegNum is set to REG_NA
468         // or _gtRegPair is set to REG_PAIR_NONE, depending on the node type.
469         regNumberSmall   _gtRegNum;     // which register      the value is in
470         regPairNoSmall   _gtRegPair;    // which register pair the value is in
471     };
472
473 public:
474
475     // The register number is stored in a small format (8 bits), but the getters return and the setters take
476     // a full-size (unsigned) format, to localize the casts here.
477
478     __declspec(property(get=GetRegNum,put=SetRegNum))
479     regNumber           gtRegNum;
480
481     // for codegen purposes, is this node a subnode of its parent
482     bool isContained() const;
483
484     bool isContainedIndir() const;
485
486     bool isIndirAddrMode();
487
488     bool isIndir() const;
489
490     bool isContainedIntOrIImmed() const     { return isContained() && IsCnsIntOrI(); }
491
492     bool isContainedFltOrDblImmed() const   { return isContained() && (OperGet() == GT_CNS_DBL); }
493
494     bool isLclField() const                 { return OperGet() == GT_LCL_FLD || OperGet() == GT_STORE_LCL_FLD; }
495
496     bool isContainedLclField() const        { return isContained() && isLclField(); }
497
498     bool isContainedLclVar() const          {  return isContained() && (OperGet() == GT_LCL_VAR);  } 
499
500     // Indicates whether it is a memory op.
501     // Right now it includes Indir and LclField ops.
502     bool isMemoryOp() const                 { return isIndir() || isLclField(); }
503
504     bool isContainedMemoryOp() const        
505     { 
506         return (isContained() && isMemoryOp()) || isContainedLclVar(); 
507     }
508
509     regNumber GetRegNum() const
510     {
511         assert((gtRegTag == GT_REGTAG_REG) ||
512                (gtRegTag == GT_REGTAG_NONE)); // TODO-Cleanup: get rid of the NONE case, and fix everyplace that reads undefined values
513         regNumber reg = (regNumber) _gtRegNum;
514         assert((gtRegTag == GT_REGTAG_NONE) || // TODO-Cleanup: get rid of the NONE case, and fix everyplace that reads undefined values
515                (reg >= REG_FIRST &&
516                 reg <= REG_COUNT));
517         return reg;
518     }
519
520     void SetRegNum(regNumber reg)
521     {
522         assert(reg >= REG_FIRST &&
523                reg <= REG_COUNT);
524         // Make sure the upper bits of _gtRegPair are clear
525         _gtRegPair = (regPairNoSmall) 0;
526         _gtRegNum = (regNumberSmall) reg;
527         INDEBUG(gtRegTag = GT_REGTAG_REG;)
528         assert(_gtRegNum == reg);
529     }
530
531 #if CPU_LONG_USES_REGPAIR
532     __declspec(property(get=GetRegPair,put=SetRegPair))
533     regPairNo           gtRegPair;
534
535     regPairNo GetRegPair() const
536     {
537         assert((gtRegTag == GT_REGTAG_REGPAIR) ||
538                (gtRegTag == GT_REGTAG_NONE)); // TODO-Cleanup: get rid of the NONE case, and fix everyplace that reads undefined values
539         regPairNo regPair = (regPairNo) _gtRegPair;
540         assert((gtRegTag == GT_REGTAG_NONE) || // TODO-Cleanup: get rid of the NONE case, and fix everyplace that reads undefined values
541                (regPair >= REG_PAIR_FIRST &&
542                 regPair <= REG_PAIR_LAST) ||
543                (regPair == REG_PAIR_NONE));     // allow initializing to an undefined value
544         return regPair;
545     }
546
547     void SetRegPair(regPairNo regPair)
548     {
549         assert((regPair >= REG_PAIR_FIRST &&
550                 regPair <= REG_PAIR_LAST) ||
551                (regPair == REG_PAIR_NONE));     // allow initializing to an undefined value
552         _gtRegPair = (regPairNoSmall) regPair;
553         INDEBUG(gtRegTag = GT_REGTAG_REGPAIR;)
554         assert(_gtRegPair == regPair);
555     }
556 #endif
557
558     // Copy the _gtRegNum/_gtRegPair/gtRegTag fields
559     void CopyReg(GenTreePtr from);
560
561     void gtClearReg(Compiler* compiler);
562
563     bool gtHasReg() const;
564
565     regMaskTP gtGetRegMask() const;
566
567     unsigned            gtFlags;        // see GTF_xxxx below
568
569 #if defined(DEBUG)
570     unsigned            gtDebugFlags;   // see GTF_DEBUG_xxx below
571 #endif // defined(DEBUG)
572
573     ValueNumPair        gtVNPair;
574
575     regMaskSmall        gtRsvdRegs;     // set of fixed trashed  registers
576 #ifdef LEGACY_BACKEND
577     regMaskSmall        gtUsedRegs;     // set of used (trashed) registers
578 #endif // LEGACY_BACKEND
579
580 #ifndef LEGACY_BACKEND
581     TreeNodeInfo        gtLsraInfo;
582 #endif // !LEGACY_BACKEND
583
584     void                SetVNsFromNode(GenTreePtr tree)
585     {
586         gtVNPair = tree->gtVNPair;
587     }
588
589     ValueNum            GetVN(ValueNumKind vnk) const
590     {
591         if (vnk == VNK_Liberal)
592         {
593             return gtVNPair.GetLiberal();
594         }
595         else
596         {
597             assert(vnk == VNK_Conservative);
598             return gtVNPair.GetConservative();
599         }
600     }
601     void                SetVN(ValueNumKind vnk, ValueNum vn)
602     {
603         if (vnk == VNK_Liberal)
604         {
605             return gtVNPair.SetLiberal(vn);
606         }
607         else
608         {
609             assert(vnk == VNK_Conservative);
610             return gtVNPair.SetConservative(vn);
611         }
612     }
613     void                SetVNs(ValueNumPair vnp)
614     {
615         gtVNPair = vnp;
616     }
617     void                ClearVN()
618     {
619         gtVNPair = ValueNumPair();          // Initializes both elements to "NoVN".
620     }
621
622     //---------------------------------------------------------------------
623     //  The first set of flags can be used with a large set of nodes, and
624     //  thus they must all have distinct values. That is, one can test any
625     //  expression node for one of these flags.
626     //---------------------------------------------------------------------
627
628     #define GTF_ASG             0x00000001  // sub-expression contains an assignment
629     #define GTF_CALL            0x00000002  // sub-expression contains a  func. call
630     #define GTF_EXCEPT          0x00000004  // sub-expression might throw an exception
631     #define GTF_GLOB_REF        0x00000008  // sub-expression uses global variable(s)
632     #define GTF_ORDER_SIDEEFF   0x00000010  // sub-expression has a re-ordering side effect
633
634     // If you set these flags, make sure that code:gtExtractSideEffList knows how to find the tree,
635     // otherwise the C# (run csc /o-)
636     // var v = side_eff_operation
637     // with no use of v will drop your tree on the floor.
638     #define GTF_PERSISTENT_SIDE_EFFECTS (GTF_ASG|GTF_CALL)
639     #define GTF_SIDE_EFFECT     (GTF_PERSISTENT_SIDE_EFFECTS|GTF_EXCEPT)
640     #define GTF_GLOB_EFFECT     (GTF_SIDE_EFFECT|GTF_GLOB_REF)
641     #define GTF_ALL_EFFECT      (GTF_GLOB_EFFECT|GTF_ORDER_SIDEEFF)
642
643     // The extra flag GTF_IS_IN_CSE is used to tell the consumer of these flags
644     // that we are calling in the context of performing a CSE, thus we
645     // should allow the run-once side effects of running a class constructor.
646     //
647     // The only requirement of this flag is that it not overlap any of the
648     // side-effect flags. The actual bit used is otherwise arbitrary.
649     #define GTF_IS_IN_CSE  GTF_MAKE_CSE
650     #define GTF_PERSISTENT_SIDE_EFFECTS_IN_CSE (GTF_ASG|GTF_CALL|GTF_IS_IN_CSE)
651
652     // Can any side-effects be observed externally, say by a caller method?
653     // For assignments, only assignments to global memory can be observed
654     // externally, whereas simple assignments to local variables can not.
655     //
656     // Be careful when using this inside a "try" protected region as the
657     // order of assignments to local variables would need to be preserved
658     // wrt side effects if the variables are alive on entry to the
659     // "catch/finally" region. In such cases, even assignments to locals 
660     // will have to be restricted.
661     #define GTF_GLOBALLY_VISIBLE_SIDE_EFFECTS(flags)                    \
662         (((flags) & (GTF_CALL|GTF_EXCEPT))                   ||         \
663          (((flags) & (GTF_ASG|GTF_GLOB_REF)) == (GTF_ASG|GTF_GLOB_REF)))
664     
665     #define GTF_REVERSE_OPS     0x00000020  // operand op2 should be evaluated before op1 (normally, op1 is evaluated first and op2 is evaluated second)
666     #define GTF_REG_VAL         0x00000040  // operand is sitting in a register (or part of a TYP_LONG operand is sitting in a register)
667
668     #define GTF_SPILLED         0x00000080  // the value   has been spilled
669     #define GTF_SPILLED_OPER    0x00000100  //   op1 has been spilled
670
671 #ifdef LEGACY_BACKEND
672     #define GTF_SPILLED_OP2     0x00000200  //   op2 has been spilled
673 #endif // LEGACY_BACKEND
674
675     #define GTF_REDINDEX_CHECK  0x00000100  // Used for redundant range checks. Disjoint from GTF_SPILLED_OPER
676
677     #define GTF_ZSF_SET         0x00000400  // the zero(ZF) and sign(SF) flags set to the operand
678 #if FEATURE_SET_FLAGS
679     #define GTF_SET_FLAGS       0x00000800  // Requires that codegen for this node set the flags
680                                             // Use gtSetFlags() to check this flags
681 #endif
682     #define GTF_IND_NONFAULTING 0x00000800  // An indir that cannot fault.  GTF_SET_FLAGS is not used on indirs
683
684     #define GTF_MAKE_CSE        0x00002000  // Hoisted Expression: try hard to make this into CSE  (see optPerformHoistExpr)
685     #define GTF_DONT_CSE        0x00004000  // don't bother CSE'ing this expr
686     #define GTF_COLON_COND      0x00008000  // this node is conditionally executed (part of ? :)
687
688     #define GTF_NODE_MASK       (GTF_COLON_COND)
689
690     #define GTF_BOOLEAN         0x00040000  // value is known to be 0/1
691
692     #define GTF_SMALL_OK        0x00080000  // actual small int sufficient
693
694     #define GTF_UNSIGNED        0x00100000  // with GT_CAST:   the source operand is an unsigned type
695                                             // with operators: the specified node is an unsigned operator
696
697     #define GTF_LATE_ARG        0x00200000  // the specified node is evaluated to a temp in the arg list, and this temp is added to gtCallLateArgs.
698
699     #define GTF_SPILL           0x00400000  // needs to be spilled here
700     #define GTF_SPILL_HIGH      0x00040000  // shared with GTF_BOOLEAN
701
702     #define GTF_COMMON_MASK     0x007FFFFF  // mask of all the flags above
703
704     #define GTF_REUSE_REG_VAL   0x00800000  // This is set by the register allocator on nodes whose value already exists in the
705                                             // register assigned to this node, so the code generator does not have to generate
706                                             // code to produce the value.
707                                             // It is currently used only on constant nodes.
708                                             // It CANNOT be set on var (GT_LCL*) nodes, or on indir (GT_IND or GT_STOREIND) nodes, since
709                                             // it is not needed for lclVars and is highly unlikely to be useful for indir nodes
710
711     //---------------------------------------------------------------------
712     //  The following flags can be used only with a small set of nodes, and
713     //  thus their values need not be distinct (other than within the set
714     //  that goes with a particular node/nodes, of course). That is, one can
715     //  only test for one of these flags if the 'gtOper' value is tested as
716     //  well to make sure it's the right operator for the particular flag.
717     //---------------------------------------------------------------------
718
719     // NB: GTF_VAR_* and GTF_REG_* share the same namespace of flags, because
720     // GT_LCL_VAR nodes may be changed to GT_REG_VAR nodes without resetting
721     // the flags. These are also used by GT_LCL_FLD.
722     #define GTF_VAR_DEF         0x80000000  // GT_LCL_VAR -- this is a definition
723     #define GTF_VAR_USEASG      0x40000000  // GT_LCL_VAR -- this is a use/def for a x<op>=y
724     #define GTF_VAR_USEDEF      0x20000000  // GT_LCL_VAR -- this is a use/def as in x=x+y (only the lhs x is tagged)
725     #define GTF_VAR_CAST        0x10000000  // GT_LCL_VAR -- has been explictly cast (variable node may not be type of local)
726     #define GTF_VAR_ITERATOR    0x08000000  // GT_LCL_VAR -- this is a iterator reference in the loop condition
727     #define GTF_VAR_CLONED      0x01000000  // GT_LCL_VAR -- this node has been cloned or is a clone
728                                             // Relevant for inlining optimizations (see fgInlinePrependStatements)
729
730     // TODO-Cleanup: Currently, GTF_REG_BIRTH is used only by stackfp
731     //         We should consider using it more generally for VAR_BIRTH, instead of
732     //         GTF_VAR_DEF && !GTF_VAR_USEASG
733     #define GTF_REG_BIRTH       0x04000000  // GT_REG_VAR -- enregistered variable born here
734     #define GTF_VAR_DEATH       0x02000000  // GT_LCL_VAR, GT_REG_VAR -- variable dies here (last use)
735
736     #define GTF_VAR_ARR_INDEX   0x00000020  // The variable is part of (the index portion of) an array index expression.
737                                             // Shares a value with GTF_REVERSE_OPS, which is meaningless for local var.
738
739     #define GTF_LIVENESS_MASK   (GTF_VAR_DEF|GTF_VAR_USEASG|GTF_VAR_USEDEF|GTF_REG_BIRTH|GTF_VAR_DEATH)
740
741     #define GTF_CALL_UNMANAGED  0x80000000  // GT_CALL    -- direct call to unmanaged code
742     #define GTF_CALL_INLINE_CANDIDATE 0x40000000 // GT_CALL -- this call has been marked as an inline candidate
743 //  
744     #define GTF_CALL_VIRT_KIND_MASK  0x30000000 
745     #define GTF_CALL_NONVIRT         0x00000000  // GT_CALL    -- a non virtual call
746     #define GTF_CALL_VIRT_STUB       0x10000000  // GT_CALL    -- a stub-dispatch virtual call
747     #define GTF_CALL_VIRT_VTABLE     0x20000000  // GT_CALL    -- a  vtable-based virtual call
748
749     #define GTF_CALL_NULLCHECK  0x08000000  // GT_CALL    -- must check instance pointer for null
750     #define GTF_CALL_POP_ARGS   0x04000000  // GT_CALL    -- caller pop arguments?
751     #define GTF_CALL_HOISTABLE  0x02000000  // GT_CALL    -- call is hoistable
752     #define GTF_CALL_REG_SAVE   0x01000000  // GT_CALL    -- This call preserves all integer regs
753                                             // For additional flags for GT_CALL node see GTF_CALL_M_
754
755     #define GTF_NOP_DEATH         0x40000000  // GT_NOP     -- operand dies here
756
757     #define GTF_FLD_NULLCHECK     0x80000000  // GT_FIELD -- need to nullcheck the "this" pointer
758     #define GTF_FLD_VOLATILE      0x40000000  // GT_FIELD/GT_CLS_VAR -- same as GTF_IND_VOLATILE
759
760     #define GTF_INX_RNGCHK        0x80000000  // GT_INDEX -- the array reference should be range-checked.
761     #define GTF_INX_REFARR_LAYOUT 0x20000000  // GT_INDEX -- same as GTF_IND_REFARR_LAYOUT
762     #define GTF_INX_STRING_LAYOUT 0x40000000  // GT_INDEX -- this uses the special string array layout
763
764     #define GTF_IND_VOLATILE      0x40000000  // GT_IND   -- the load or store must use volatile sematics (this is a nop on X86)
765     #define GTF_IND_REFARR_LAYOUT 0x20000000  // GT_IND   -- the array holds object refs (only effects layout of Arrays)
766     #define GTF_IND_TGTANYWHERE   0x10000000  // GT_IND   -- the target could be anywhere
767     #define GTF_IND_TLS_REF       0x08000000  // GT_IND   -- the target is accessed via TLS
768     #define GTF_IND_ASG_LHS       0x04000000  // GT_IND   -- this GT_IND node is (the effective val) of the LHS of an assignment; don't evaluate it independently.
769     #define GTF_IND_UNALIGNED     0x02000000  // GT_IND   -- the load or store is unaligned (we assume worst case alignment of 1 byte) 
770     #define GTF_IND_INVARIANT     0x01000000  // GT_IND   -- the target is invariant (a prejit indirection)
771     #define GTF_IND_ARR_LEN       0x80000000  // GT_IND   -- the indirection represents an array length (of the REF contribution to its argument).
772     #define GTF_IND_ARR_INDEX     0x00800000  // GT_IND   -- the indirection represents an (SZ) array index
773
774     #define GTF_IND_FLAGS         (GTF_IND_VOLATILE|GTF_IND_REFARR_LAYOUT|GTF_IND_TGTANYWHERE|GTF_IND_NONFAULTING|\
775                                    GTF_IND_TLS_REF|GTF_IND_UNALIGNED|GTF_IND_INVARIANT|GTF_IND_ARR_INDEX)
776
777     #define GTF_CLS_VAR_ASG_LHS   0x04000000  // GT_CLS_VAR   -- this GT_CLS_VAR node is (the effective val) of the LHS of an assignment; don't evaluate it independently.
778
779     #define GTF_ADDR_ONSTACK      0x80000000  // GT_ADDR    -- this expression is guaranteed to be on the stack
780
781
782     #define GTF_ADDRMODE_NO_CSE 0x80000000  // GT_ADD/GT_MUL/GT_LSH -- Do not CSE this node only, forms complex addressing mode
783
784     #define GTF_MUL_64RSLT      0x40000000  // GT_MUL     -- produce 64-bit result
785
786     #define GTF_MOD_INT_RESULT  0x80000000  // GT_MOD,    -- the real tree represented by this
787                                             // GT_UMOD       node evaluates to an int even though
788                                             //               its type is long.  The result is
789                                             //               placed in the low member of the
790                                             //               reg pair
791
792     #define GTF_RELOP_NAN_UN    0x80000000  // GT_<relop> -- Is branch taken if ops are NaN?
793     #define GTF_RELOP_JMP_USED  0x40000000  // GT_<relop> -- result of compare used for jump or ?:
794     #define GTF_RELOP_QMARK     0x20000000  // GT_<relop> -- the node is the condition for ?:
795     #define GTF_RELOP_SMALL     0x10000000  // GT_<relop> -- We should use a byte or short sized compare (op1->gtType is the small type)
796     #define GTF_RELOP_ZTT       0x08000000  // GT_<relop> -- Loop test cloned for converting while-loops into do-while with explicit "loop test" in the header block.
797
798     #define GTF_QMARK_CAST_INSTOF 0x80000000  // GT_QMARK   -- Is this a top (not nested) level qmark created for castclass or instanceof?
799
800     #define GTF_BOX_VALUE 0x80000000  // GT_BOX   -- "box" is on a value type
801
802     #define GTF_ICON_HDL_MASK   0xF0000000  // Bits used by handle types below
803
804     #define GTF_ICON_SCOPE_HDL  0x10000000  // GT_CNS_INT -- constant is a scope handle
805     #define GTF_ICON_CLASS_HDL  0x20000000  // GT_CNS_INT -- constant is a class handle
806     #define GTF_ICON_METHOD_HDL 0x30000000  // GT_CNS_INT -- constant is a method handle
807     #define GTF_ICON_FIELD_HDL  0x40000000  // GT_CNS_INT -- constant is a field handle
808     #define GTF_ICON_STATIC_HDL 0x50000000  // GT_CNS_INT -- constant is a handle to static data
809     #define GTF_ICON_STR_HDL    0x60000000  // GT_CNS_INT -- constant is a string handle
810     #define GTF_ICON_PSTR_HDL   0x70000000  // GT_CNS_INT -- constant is a ptr to a string handle
811     #define GTF_ICON_PTR_HDL    0x80000000  // GT_CNS_INT -- constant is a ldptr handle
812     #define GTF_ICON_VARG_HDL   0x90000000  // GT_CNS_INT -- constant is a var arg cookie handle
813     #define GTF_ICON_PINVKI_HDL 0xA0000000  // GT_CNS_INT -- constant is a pinvoke calli handle
814     #define GTF_ICON_TOKEN_HDL  0xB0000000  // GT_CNS_INT -- constant is a token handle
815     #define GTF_ICON_TLS_HDL    0xC0000000  // GT_CNS_INT -- constant is a TLS ref with offset
816     #define GTF_ICON_FTN_ADDR   0xD0000000  // GT_CNS_INT -- constant is a function address
817     #define GTF_ICON_CIDMID_HDL 0xE0000000  // GT_CNS_INT -- constant is a class or module ID handle
818     #define GTF_ICON_BBC_PTR    0xF0000000  // GT_CNS_INT -- constant is a basic block count pointer
819
820     #define GTF_ICON_FIELD_OFF  0x08000000  // GT_CNS_INT -- constant is a field offset
821
822     #define GTF_BLK_HASGCPTR    0x80000000  // GT_COPYBLK -- This struct copy will copy GC Pointers
823     #define GTF_BLK_VOLATILE    0x40000000  // GT_INITBLK/GT_COPYBLK -- is a volatile block operation
824     #define GTF_BLK_UNALIGNED   0x02000000  // GT_INITBLK/GT_COPYBLK -- is an unaligned block operation
825
826     #define GTF_OVERFLOW        0x10000000  // GT_ADD, GT_SUB, GT_MUL, - Need overflow check
827                                             // GT_ASG_ADD, GT_ASG_SUB,
828                                             // GT_CAST
829                                             // Use gtOverflow(Ex)() to check this flag
830
831     #define GTF_NO_OP_NO        0x80000000  // GT_NO_OP   --Have the codegenerator generate a special nop
832
833     //----------------------------------------------------------------
834
835     #define GTF_STMT_CMPADD     0x80000000  // GT_STMT    -- added by compiler
836     #define GTF_STMT_HAS_CSE    0x40000000  // GT_STMT    -- CSE def or use was subsituted
837     #define GTF_STMT_TOP_LEVEL  0x20000000  // GT_STMT    -- Top-level statement - true iff gtStmtList->gtPrev == nullptr
838                                             //               True for all stmts when in FGOrderTree
839     #define GTF_STMT_SKIP_LOWER 0x10000000  // GT_STMT    -- Skip lowering if we already lowered an embedded stmt.
840
841     //----------------------------------------------------------------
842
843 #if defined(DEBUG)
844     #define GTF_DEBUG_NONE            0x00000000  // No debug flags.
845
846     #define GTF_DEBUG_NODE_MORPHED    0x00000001  // the node has been morphed (in the global morphing phase)
847     #define GTF_DEBUG_NODE_SMALL      0x00000002
848     #define GTF_DEBUG_NODE_LARGE      0x00000004
849
850     #define GTF_DEBUG_NODE_MASK       0x00000007  // These flags are all node (rather than operation) properties.
851
852     #define GTF_DEBUG_VAR_CSE_REF     0x00800000  // GT_LCL_VAR -- This is a CSE LCL_VAR node
853 #endif // defined(DEBUG)
854
855     GenTreePtr          gtNext;
856     GenTreePtr          gtPrev;
857
858 #ifdef DEBUG
859     unsigned            gtTreeID;
860     unsigned            gtSeqNum;       // liveness traversal order within the current statement
861 #endif
862
863     static
864     const unsigned short   gtOperKindTable[];
865
866     static
867     unsigned        OperKind(unsigned gtOper)
868     {
869         assert(gtOper < GT_COUNT);
870
871         return  gtOperKindTable[gtOper];
872     }
873
874     unsigned        OperKind() const
875     {
876         assert(gtOper < GT_COUNT);
877
878         return  gtOperKindTable[gtOper];
879     }
880
881     static bool     IsExOp(unsigned opKind)
882     {
883         return (opKind & GTK_EXOP) != 0;
884     }
885     // Returns the operKind with the GTK_EX_OP bit removed (the
886     // kind of operator, unary or binary, that is extended).
887     static unsigned StripExOp(unsigned opKind)
888     {
889         return opKind & ~GTK_EXOP;
890     }
891
892     static
893     bool            OperIsConst(genTreeOps gtOper)
894     {
895         return  (OperKind(gtOper) & GTK_CONST  ) != 0;
896     }
897
898     bool            OperIsConst() const
899     {
900         return  (OperKind(gtOper) & GTK_CONST  ) != 0;
901     }
902
903     static
904     bool            OperIsLeaf(genTreeOps gtOper)
905     {
906         return  (OperKind(gtOper) & GTK_LEAF   ) != 0;
907     }
908
909     bool            OperIsLeaf() const
910     {
911         return  (OperKind(gtOper) & GTK_LEAF   ) != 0;
912     }
913
914     static
915     bool            OperIsCompare(genTreeOps gtOper)
916     {
917         return  (OperKind(gtOper) & GTK_RELOP  ) != 0;
918     }
919
920     static
921     bool            OperIsLocal(genTreeOps gtOper)
922     {
923         bool result = (OperKind(gtOper) & GTK_LOCAL) != 0;
924         assert(result ==
925                (gtOper == GT_LCL_VAR ||
926                 gtOper == GT_PHI_ARG ||
927                 gtOper == GT_REG_VAR ||
928                 gtOper == GT_LCL_FLD ||
929                 gtOper == GT_STORE_LCL_VAR ||
930                 gtOper == GT_STORE_LCL_FLD));
931         return result;
932     }
933
934     static
935     bool            OperIsBlkOp(genTreeOps gtOper)
936     {
937         return (gtOper == GT_INITBLK ||
938                 gtOper == GT_COPYBLK ||
939                 gtOper == GT_COPYOBJ);
940     }
941
942     static
943     bool            OperIsCopyBlkOp(genTreeOps gtOper)
944     {
945         return (gtOper == GT_COPYOBJ || gtOper == GT_COPYBLK);
946     }
947
948
949     static
950     bool            OperIsLocalAddr(genTreeOps gtOper)
951     {
952         return (gtOper == GT_LCL_VAR_ADDR ||
953                 gtOper == GT_LCL_FLD_ADDR);
954     }
955
956     static
957     bool           OperIsScalarLocal(genTreeOps gtOper)
958     {
959         return (gtOper == GT_LCL_VAR ||
960                 gtOper == GT_REG_VAR ||
961                 gtOper == GT_STORE_LCL_VAR);
962     }
963
964     static
965     bool            OperIsNonPhiLocal(genTreeOps gtOper)
966     {
967         return OperIsLocal(gtOper) && (gtOper != GT_PHI_ARG);
968     }
969
970     static
971     bool            OperIsLocalRead(genTreeOps gtOper)
972     {
973         return (OperIsLocal(gtOper) && !OperIsLocalStore(gtOper));
974     }
975
976     static
977     bool            OperIsLocalStore(genTreeOps gtOper)
978     {
979         return (gtOper == GT_STORE_LCL_VAR ||
980                 gtOper == GT_STORE_LCL_FLD);
981
982     }
983
984     static
985     bool            OperIsAddrMode(genTreeOps gtOper)
986     {
987         return (gtOper == GT_LEA);
988     }
989
990     bool            OperIsBlkOp() const;
991     bool            OperIsCopyBlkOp() const;
992     bool            OperIsInitBlkOp() const;
993     bool            OperIsDynBlkOp();
994
995     bool            OperIsPutArgStk() const
996     {
997         return gtOper == GT_PUTARG_STK;
998     }
999
1000     bool            OperIsAddrMode() const
1001     {
1002         return OperIsAddrMode(OperGet());
1003     }
1004
1005     bool            OperIsLocal() const
1006     {
1007         return OperIsLocal(OperGet());
1008     }
1009
1010     bool            OperIsLocalAddr() const
1011     {
1012         return OperIsLocalAddr(OperGet());
1013     }
1014
1015     bool            OperIsScalarLocal() const
1016     {
1017         return OperIsScalarLocal(OperGet());
1018     }
1019
1020     bool            OperIsNonPhiLocal() const
1021     {
1022         return OperIsNonPhiLocal(OperGet());
1023     }
1024
1025     bool            OperIsLocalStore() const
1026     {
1027         return OperIsLocalStore(OperGet());
1028     }
1029
1030     bool            OperIsLocalRead() const
1031     {
1032         return OperIsLocalRead(OperGet());
1033     }
1034
1035     bool            OperIsCompare()
1036     {
1037         return  (OperKind(gtOper) & GTK_RELOP  ) != 0;
1038     }
1039
1040     static
1041     bool            OperIsLogical(genTreeOps gtOper)
1042     {
1043         return  (OperKind(gtOper) & GTK_LOGOP  ) != 0;
1044     }
1045
1046     bool            OperIsLogical() const
1047     {
1048         return  (OperKind(gtOper) & GTK_LOGOP  ) != 0;
1049     }
1050
1051     static
1052     bool            OperIsShift(genTreeOps gtOper)
1053     {
1054         return (gtOper == GT_LSH) ||
1055                (gtOper == GT_RSH) ||
1056                (gtOper == GT_RSZ);
1057     }
1058
1059     bool            OperIsShift() const
1060     {
1061         return OperIsShift(OperGet());
1062     }
1063
1064     static
1065     bool            OperIsRotate(genTreeOps gtOper)
1066     {
1067         return (gtOper == GT_ROL) ||
1068                (gtOper == GT_ROR);
1069     }
1070
1071     bool            OperIsRotate() const
1072     {
1073         return OperIsRotate(OperGet());
1074     }
1075
1076     static
1077     bool            OperIsShiftOrRotate(genTreeOps gtOper)
1078     {
1079         return OperIsShift(gtOper) ||
1080                OperIsRotate(gtOper);
1081     }
1082
1083     bool            OperIsShiftOrRotate() const
1084     {
1085         return OperIsShiftOrRotate(OperGet());
1086     }
1087
1088     bool            OperIsArithmetic() const
1089     {
1090         genTreeOps op = OperGet();
1091         return     op==GT_ADD
1092                 || op==GT_SUB
1093                 || op==GT_MUL
1094                 || op==GT_DIV
1095                 || op==GT_MOD
1096
1097                 || op==GT_UDIV
1098                 || op==GT_UMOD
1099
1100                 || op==GT_OR
1101                 || op==GT_XOR
1102                 || op==GT_AND
1103
1104                 || OperIsShiftOrRotate(op);
1105     }
1106
1107 #if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
1108     static
1109     bool            OperIsHigh(genTreeOps gtOper)
1110     {
1111         switch (gtOper)
1112         {
1113         case GT_ADD_HI:
1114         case GT_SUB_HI:
1115         case GT_MUL_HI:
1116         case GT_DIV_HI:
1117         case GT_MOD_HI:
1118             return true;
1119         default:
1120             return false;
1121         }
1122     }
1123
1124     bool            OperIsHigh() const
1125     {
1126         return OperIsHigh(OperGet());
1127     }
1128 #endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
1129
1130     static
1131     bool            OperIsUnary(genTreeOps gtOper)
1132     {
1133         return  (OperKind(gtOper) & GTK_UNOP   ) != 0;
1134     }
1135
1136     bool            OperIsUnary() const
1137     {
1138         return   OperIsUnary(gtOper);
1139     }
1140
1141     static
1142     bool            OperIsBinary(genTreeOps gtOper)
1143     {
1144         return  (OperKind(gtOper) & GTK_BINOP  ) != 0;
1145     }
1146
1147     bool            OperIsBinary() const
1148     {
1149         return   OperIsBinary(gtOper);
1150     }
1151
1152     static
1153     bool            OperIsSimple(genTreeOps gtOper)
1154     {
1155         return (OperKind(gtOper) & GTK_SMPOP  ) != 0;
1156     }
1157
1158     static
1159     bool            OperIsSpecial(genTreeOps gtOper)
1160     {        
1161         return  ((OperKind(gtOper) & GTK_KINDMASK) == GTK_SPECIAL);
1162     }
1163
1164     bool            OperIsSimple() const
1165     {
1166         return  OperIsSimple(gtOper);
1167     }
1168
1169 #ifdef FEATURE_SIMD
1170     bool             isCommutativeSIMDIntrinsic();
1171 #else // !
1172     bool             isCommutativeSIMDIntrinsic()
1173     {
1174         return false;
1175     }
1176 #endif // FEATURE_SIMD
1177
1178     static
1179     bool            OperIsCommutative(genTreeOps gtOper)
1180     {
1181         return  (OperKind(gtOper) & GTK_COMMUTE) != 0;
1182     }
1183
1184     bool            OperIsCommutative()
1185     {
1186         return OperIsCommutative(gtOper) || (OperIsSIMD(gtOper) && isCommutativeSIMDIntrinsic());
1187     }
1188
1189     static
1190     bool            OperIsAssignment(genTreeOps gtOper)
1191     {
1192         return  (OperKind(gtOper) & GTK_ASGOP) != 0;
1193     }
1194
1195     bool            OperIsAssignment() const
1196     {
1197         return  OperIsAssignment(gtOper);
1198     }
1199
1200     static
1201     bool            OperIsIndir(genTreeOps gtOper)
1202     {
1203         return  gtOper == GT_IND || gtOper == GT_STOREIND || gtOper == GT_NULLCHECK;
1204     }
1205
1206     bool            OperIsIndir() const
1207     {
1208         return  OperIsIndir(gtOper);
1209     }
1210
1211     static 
1212     bool            OperIsImplicitIndir(genTreeOps gtOper)
1213     {
1214         switch (gtOper)
1215         {
1216         case GT_LOCKADD:
1217         case GT_XADD:
1218         case GT_CMPXCHG:
1219         case GT_COPYBLK:
1220         case GT_COPYOBJ:
1221         case GT_INITBLK:
1222         case GT_OBJ:
1223         case GT_BOX:
1224         case GT_ARR_INDEX:
1225         case GT_ARR_ELEM:
1226         case GT_ARR_OFFSET:
1227             return true;
1228         default:
1229             return false;
1230         }
1231     }
1232
1233     bool            OperIsImplicitIndir() const
1234     {
1235         return  OperIsImplicitIndir(gtOper);
1236     }
1237
1238     bool            OperIsStore() const
1239     {
1240         return OperIsStore(gtOper);
1241     }
1242
1243     static
1244     bool            OperIsStore(genTreeOps gtOper)
1245     {
1246         return (gtOper == GT_STOREIND
1247                 || gtOper == GT_STORE_LCL_VAR
1248                 || gtOper == GT_STORE_LCL_FLD
1249                 || gtOper == GT_STORE_CLS_VAR);
1250     }
1251
1252     static
1253     bool            OperIsAtomicOp(genTreeOps gtOper)
1254     {
1255         return  (gtOper == GT_XADD 
1256                  || gtOper == GT_XCHG  
1257                  || gtOper == GT_LOCKADD 
1258                  || gtOper == GT_CMPXCHG);
1259     }
1260
1261     bool            OperIsAtomicOp()
1262     {
1263         return  OperIsAtomicOp(gtOper);
1264     }
1265
1266     // This is basically here for cleaner FEATURE_SIMD #ifdefs.
1267     static
1268     bool            OperIsSIMD(genTreeOps gtOper)
1269     {
1270 #ifdef FEATURE_SIMD
1271         return gtOper == GT_SIMD;
1272 #else // !FEATURE_SIMD
1273         return false;
1274 #endif // !FEATURE_SIMD
1275     }
1276
1277     bool            OperIsSIMD()
1278     {
1279         return OperIsSIMD(gtOper);
1280     }
1281
1282     // Requires that "op" is an op= operator.  Returns
1283     // the corresponding "op".
1284     static
1285     genTreeOps      OpAsgToOper(genTreeOps op);
1286
1287 #ifdef DEBUG
1288     bool            NullOp1Legal() const
1289     {
1290         assert(OperIsSimple(gtOper));
1291         switch (gtOper)
1292         {
1293         case GT_PHI: case GT_LEA: case GT_RETFILT: case GT_NOP:
1294             return true;
1295         case GT_RETURN:
1296             return gtType == TYP_VOID;
1297         default:
1298             return false;
1299         }
1300     }
1301
1302     bool            NullOp2Legal() const
1303     {
1304         assert(OperIsSimple(gtOper));
1305         if (!OperIsBinary(gtOper))
1306         {
1307             return true;
1308         }
1309         switch (gtOper)
1310         {
1311         case GT_LIST:
1312         case GT_INTRINSIC:
1313         case GT_LEA:
1314         case GT_STOREIND:
1315         case GT_INITBLK:
1316         case GT_COPYBLK:
1317         case GT_COPYOBJ:
1318 #ifdef FEATURE_SIMD
1319         case GT_SIMD:
1320 #endif // !FEATURE_SIMD
1321             return true;
1322         default:
1323             return false;
1324         }
1325     }
1326
1327     static
1328     inline bool RequiresNonNullOp2(genTreeOps oper);
1329     bool IsListForMultiRegArg();
1330 #endif // DEBUG
1331
1332     inline bool IsFPZero();
1333     inline bool IsIntegralConst(ssize_t constVal);
1334
1335     inline bool IsBoxedValue();
1336
1337     bool IsList() const
1338     {
1339         return gtOper == GT_LIST;
1340     }
1341
1342     inline GenTreePtr MoveNext();
1343
1344     inline GenTreePtr Current();
1345
1346     inline GenTreePtr *pCurrent();
1347
1348     inline GenTreePtr gtGetOp1();
1349
1350     inline GenTreePtr gtGetOp2();
1351
1352     // Given a tree node, if this is a child of that node, return the pointer to the child node so that it
1353     // can be modified; otherwise, return null.
1354     GenTreePtr*       gtGetChildPointer(GenTreePtr parent);
1355
1356     // Get the parent of this node, and optionally capture the pointer to the child so that it can be modified.
1357     GenTreePtr        gtGetParent(GenTreePtr** parentChildPtrPtr);
1358
1359     inline GenTreePtr gtEffectiveVal(bool commaOnly = false);
1360
1361     // Return the child of this node if it is a GT_RELOAD or GT_COPY; otherwise simply return the node itself
1362     inline GenTree*   gtSkipReloadOrCopy();
1363
1364     // Returns true if it is a call node returning its value in more than one register
1365     inline bool     IsMultiRegCall() const;
1366
1367     // Returns true if it is a GT_COPY or GT_RELOAD node
1368     inline bool     IsCopyOrReload() const;
1369
1370     // Returns true if it is a GT_COPY or GT_RELOAD of a multi-reg call node
1371     inline bool     IsCopyOrReloadOfMultiRegCall() const;
1372
1373     bool            OperMayThrow();
1374
1375     unsigned        GetScaleIndexMul();
1376     unsigned        GetScaleIndexShf();
1377     unsigned        GetScaledIndex();
1378
1379     // Returns true if "addr" is a GT_ADD node, at least one of whose arguments is an integer
1380     // (<= 32 bit) constant.  If it returns true, it sets "*offset" to (one of the) constant value(s), and
1381     // "*addr" to the other argument.
1382     bool            IsAddWithI32Const(GenTreePtr* addr, int* offset);
1383
1384     // Insert 'node' after this node in execution order.
1385     void            InsertAfterSelf(GenTree* node, GenTreeStmt* stmt = nullptr);
1386
1387 public:
1388
1389 #if SMALL_TREE_NODES
1390     static
1391     unsigned char   s_gtNodeSizes[];
1392 #endif
1393
1394     static
1395     void            InitNodeSize();
1396
1397     size_t          GetNodeSize() const;
1398
1399     bool            IsNodeProperlySized() const;
1400
1401     void            CopyFrom(const GenTree* src, Compiler* comp);
1402
1403     static
1404     genTreeOps      ReverseRelop(genTreeOps relop);
1405
1406     static
1407     genTreeOps      SwapRelop(genTreeOps relop);
1408
1409     //---------------------------------------------------------------------
1410
1411     static
1412     bool            Compare(GenTreePtr op1, GenTreePtr op2, bool swapOK = false);
1413
1414     //---------------------------------------------------------------------
1415     #ifdef DEBUG
1416     //---------------------------------------------------------------------
1417
1418     static
1419     const   char *  NodeName(genTreeOps op);
1420
1421     static
1422     const   char *  OpName(genTreeOps op);
1423
1424     //---------------------------------------------------------------------
1425     #endif
1426     //---------------------------------------------------------------------
1427
1428     bool                        IsNothingNode       () const;
1429     void                        gtBashToNOP         ();
1430
1431     // Value number update action enumeration
1432     enum ValueNumberUpdate
1433     {
1434         CLEAR_VN,       // Clear value number
1435         PRESERVE_VN     // Preserve value number
1436     };
1437
1438     void                        SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate = CLEAR_VN);  // set gtOper
1439     void                        SetOperResetFlags   (genTreeOps oper);  // set gtOper and reset flags
1440
1441     void                        ChangeOperConst     (genTreeOps oper);  // ChangeOper(constOper)
1442     // set gtOper and only keep GTF_COMMON_MASK flags
1443     void                        ChangeOper(genTreeOps oper, ValueNumberUpdate vnUpdate = CLEAR_VN);
1444     void                        ChangeOperUnchecked (genTreeOps oper);
1445
1446     bool IsLocal() const
1447     {
1448         return OperIsLocal(OperGet());
1449     }
1450
1451     // Returns "true" iff 'this' is a GT_LCL_FLD or GT_STORE_LCL_FLD on which the type
1452     // is not the same size as the type of the GT_LCL_VAR.
1453     bool IsPartialLclFld(Compiler* comp);
1454
1455     // Returns "true" iff "this" defines a local variable.  Requires "comp" to be the 
1456     // current compilation.  If returns "true", sets "*pLclVarTree" to the
1457     // tree for the local that is defined, and, if "pIsEntire" is non-null, sets "*pIsEntire" to
1458     // true or false, depending on whether the assignment writes to the entirety of the local
1459     // variable, or just a portion of it.
1460     bool DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire = nullptr);
1461
1462     // Returns true if "this" represents the address of a local, or a field of a local.  If returns true, sets
1463     // "*pLclVarTree" to the node indicating the local variable.  If the address is that of a field of this node,
1464     // sets "*pFldSeq" to the field sequence representing that field, else null.
1465     bool IsLocalAddrExpr(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, FieldSeqNode** pFldSeq);
1466
1467     // Simpler variant of the above which just returns the local node if this is an expression that 
1468     // yields an address into a local
1469     GenTreeLclVarCommon* IsLocalAddrExpr();
1470
1471     // Determine if this is a LclVarCommon node and return some additional info about it in the
1472     // two out parameters.
1473     bool IsLocalExpr(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, FieldSeqNode** pFldSeq);
1474
1475     // Determine whether this is an assignment tree of the form X = X (op) Y,
1476     // where Y is an arbitrary tree, and X is a lclVar.
1477     unsigned             IsLclVarUpdateTree(GenTree** otherTree, genTreeOps *updateOper);
1478
1479     // If returns "true", "this" may represent the address of a static or instance field
1480     // (or a field of such a field, in the case of an object field of type struct).  
1481     // If returns "true", then either "*pObj" is set to the object reference, 
1482     // or "*pStatic" is set to the baseAddr or offset to be added to the "*pFldSeq" 
1483     // Only one of "*pObj" or "*pStatic" will be set, the other one will be null.
1484     // The boolean return value only indicates that "this" *may* be a field address 
1485     // -- the field sequence must also be checked.  
1486     // If it is a field address, the field sequence will be a sequence of length >= 1, 
1487     // starting with an instance or static field, and optionally continuing with struct fields.
1488     bool IsFieldAddr(Compiler* comp, GenTreePtr* pObj, GenTreePtr* pStatic, FieldSeqNode** pFldSeq);
1489
1490     // Requires "this" to be the address of an array (the child of a GT_IND labeled with GTF_IND_ARR_INDEX).
1491     // Sets "pArr" to the node representing the array (either an array object pointer, or perhaps a byref to the some element).
1492     // Sets "*pArrayType" to the class handle for the array type.
1493     // Sets "*inxVN" to the value number inferred for the array index.
1494     // Sets "*pFldSeq" to the sequence, if any, of struct fields used to index into the array element.
1495     void ParseArrayAddress(Compiler* comp, 
1496                            struct ArrayInfo* arrayInfo, 
1497                            GenTreePtr* pArr, 
1498                            ValueNum* pInxVN,
1499                            FieldSeqNode** pFldSeq);
1500
1501     // Helper method for the above.
1502     void ParseArrayAddressWork(Compiler* comp, ssize_t inputMul, GenTreePtr* pArr, ValueNum* pInxVN, ssize_t* pOffset, FieldSeqNode** pFldSeq);
1503
1504     // Requires "this" to be a GT_IND.  Requires the outermost caller to set "*pFldSeq" to nullptr.
1505     // Returns true if it is an array index expression, or access to a (sequence of) struct field(s)
1506     // within a struct array element.  If it returns true, sets *arrayInfo to the array information, and sets *pFldSeq to the sequence
1507     // of struct field accesses.
1508     bool ParseArrayElemForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq);
1509
1510     // Requires "this" to be the address of a (possible) array element (or struct field within that).
1511     // If it is, sets "*arrayInfo" to the array access info, "*pFldSeq" to the sequence of struct fields
1512     // accessed within the array element, and returns true.  If not, returns "false".
1513     bool ParseArrayElemAddrForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq);
1514
1515     // Requires "this" to be an int expression.  If it is a sequence of one or more integer constants added together,
1516     // returns true and sets "*pFldSeq" to the sequence of fields with which those constants are annotated.
1517     bool ParseOffsetForm(Compiler* comp, FieldSeqNode** pFldSeq);
1518
1519     // Labels "*this" as an array index expression: label all constants and variables that could contribute, as part of an affine expression, to the value of the
1520     // of the index.
1521     void LabelIndex(Compiler* comp, bool isConst = true);
1522
1523     // Assumes that "this" occurs in a context where it is being dereferenced as the LHS of an assignment-like
1524     // statement (assignment, initblk, or copyblk).  The "width" should be the number of bytes copied by the
1525     // operation.  Returns "true" if "this" is an address of (or within)
1526     // a local variable; sets "*pLclVarTree" to that local variable instance; and, if "pIsEntire" is non-null,
1527     // sets "*pIsEntire" to true if this assignment writes the full width of the local.
1528     bool DefinesLocalAddr(Compiler* comp, unsigned width, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire);
1529
1530     bool                        IsRegVar            () const
1531     {
1532         return OperGet() == GT_REG_VAR?true:false;
1533     }
1534     bool                        InReg() const
1535     {
1536         return (gtFlags & GTF_REG_VAL)?true:false;       
1537     }
1538     void                        SetInReg()
1539     {
1540         gtFlags |= GTF_REG_VAL;
1541     }
1542
1543     regNumber                   GetReg() const
1544     {
1545         return InReg() ? gtRegNum : REG_NA;
1546     }
1547     bool                        IsRegVarDeath       () const
1548     {
1549         assert(OperGet() == GT_REG_VAR);
1550         return (gtFlags & GTF_VAR_DEATH)?true:false;       
1551     }
1552     bool                        IsRegVarBirth       () const
1553     {
1554         assert(OperGet() == GT_REG_VAR);
1555         return (gtFlags & GTF_REG_BIRTH)?true:false;       
1556     }
1557     bool                        IsReverseOp() const
1558     {
1559         return (gtFlags & GTF_REVERSE_OPS)?true:false;
1560     }
1561
1562     inline bool                 IsCnsIntOrI         () const;
1563
1564     inline bool                 IsIntegralConst     () const;
1565
1566     inline bool                 IsIntCnsFitsInI32   ();
1567
1568     inline bool                 IsCnsFltOrDbl() const;
1569
1570     inline bool                 IsCnsNonZeroFltOrDbl();    
1571
1572     bool                        IsIconHandle        () const
1573     {
1574         assert(gtOper == GT_CNS_INT);
1575         return (gtFlags & GTF_ICON_HDL_MASK) ? true : false;
1576     }
1577
1578     bool                        IsIconHandle        (unsigned handleType) const
1579     {
1580         assert(gtOper == GT_CNS_INT);
1581         assert((handleType & GTF_ICON_HDL_MASK) != 0);      // check that handleType is one of the valid GTF_ICON_* values
1582         assert((handleType & ~GTF_ICON_HDL_MASK) == 0);
1583         return (gtFlags & GTF_ICON_HDL_MASK) == handleType;
1584     }
1585
1586     // Return just the part of the flags corresponding to the GTF_ICON_*_HDL flag. For example,
1587     // GTF_ICON_SCOPE_HDL. The tree node must be a const int, but it might not be a handle, in which
1588     // case we'll return zero.
1589     unsigned                    GetIconHandleFlag   () const
1590     {
1591         assert(gtOper == GT_CNS_INT);
1592         return (gtFlags & GTF_ICON_HDL_MASK);
1593     }
1594
1595     // Mark this node as no longer being a handle; clear its GTF_ICON_*_HDL bits.
1596     void                        ClearIconHandleMask()
1597     {
1598         assert(gtOper == GT_CNS_INT);
1599         gtFlags &= ~GTF_ICON_HDL_MASK;
1600     }
1601
1602     // Return true if the two GT_CNS_INT trees have the same handle flag (GTF_ICON_*_HDL).
1603     static bool                 SameIconHandleFlag(GenTree* t1, GenTree* t2)
1604     {
1605         return t1->GetIconHandleFlag() == t2->GetIconHandleFlag();
1606     }
1607
1608     bool                        IsArgPlaceHolderNode() const { return OperGet() == GT_ARGPLACE; }
1609     bool                        IsCall              () const { return OperGet() == GT_CALL; }
1610     bool                        IsStatement         () const { return OperGet() == GT_STMT; }
1611     inline bool                 IsHelperCall        ();
1612
1613     bool                        IsVarAddr           () const;
1614     bool                        gtOverflow          () const;
1615     bool                        gtOverflowEx        () const;
1616     bool                        gtSetFlags          () const;
1617     bool                        gtRequestSetFlags   ();
1618 #ifdef DEBUG
1619     bool                        gtIsValid64RsltMul  ();
1620     static int                  gtDispFlags         (unsigned flags, unsigned debugFlags);
1621 #endif
1622
1623     // cast operations 
1624     inline var_types            CastFromType();
1625     inline var_types&           CastToType();
1626
1627     // Returns true if this gentree node is marked by lowering to indicate
1628     // that codegen can still generate code even if it wasn't allocated a 
1629     // register.
1630     bool IsRegOptional() const;   
1631
1632     // Returns "true" iff "*this" is an assignment (GT_ASG) tree that defines an SSA name (lcl = phi(...));
1633     bool IsPhiDefn();
1634
1635     // Returns "true" iff "*this" is a statement containing an assignment that defines an SSA name (lcl = phi(...));
1636     bool IsPhiDefnStmt();
1637
1638     // Can't use an assignment operator, because we need the extra "comp" argument
1639     // (to provide the allocator necessary for the VarSet assignment).
1640     // TODO-Cleanup: Not really needed now, w/o liveset on tree nodes
1641     void CopyTo(class Compiler* comp, const GenTree& gt);
1642
1643     // Like the above, excepts assumes copying from small node to small node.
1644     // (Following the code it replaces, it does *not* copy the GenTree fields,
1645     // which CopyTo does.)
1646     void CopyToSmall(const GenTree& gt);
1647
1648     // Because of the fact that we hid the assignment operator of "BitSet" (in DEBUG),
1649     // we can't synthesize an assignment operator.
1650     // TODO-Cleanup: Could change this w/o liveset on tree nodes
1651     // (This is also necessary for the VTable trick.)
1652     GenTree() {}
1653
1654     // Returns the number of children of the current node.
1655     unsigned NumChildren();
1656
1657     // Requires "childNum < NumChildren()".  Returns the "n"th child of "this."
1658     GenTreePtr GetChild(unsigned childNum);
1659
1660     // The maximum possible # of children of any node.
1661     static const int MAX_CHILDREN = 6;
1662
1663     bool IsReuseRegVal() const
1664     {
1665         // This can be extended to non-constant nodes, but not to local or indir nodes.
1666         if(OperIsConst() && ((gtFlags & GTF_REUSE_REG_VAL) != 0))
1667         {
1668             return true;
1669         }
1670         return false;
1671     }
1672     void SetReuseRegVal()
1673     {
1674         assert(OperIsConst());
1675         gtFlags |= GTF_REUSE_REG_VAL;
1676     }
1677     void ResetReuseRegVal()
1678     {
1679         assert(OperIsConst());
1680         gtFlags &= ~GTF_REUSE_REG_VAL;
1681     }
1682
1683 #ifdef DEBUG
1684   private:
1685     GenTree& operator=(const GenTree& gt) {
1686         assert(!"Don't copy");
1687         return *this;
1688     }
1689 #endif // DEBUG
1690
1691 #if DEBUGGABLE_GENTREE
1692     // In DEBUG builds, add a dummy virtual method, to give the debugger run-time type information.
1693     virtual void DummyVirt() {}
1694
1695     typedef void* VtablePtr;
1696
1697     VtablePtr GetVtableForOper(genTreeOps oper);
1698     void SetVtableForOper(genTreeOps oper);
1699
1700     static VtablePtr s_vtablesForOpers[GT_COUNT];
1701     static VtablePtr s_vtableForOp;
1702 #endif // DEBUGGABLE_GENTREE
1703
1704   public:
1705     inline void* operator new(size_t sz, class Compiler*, genTreeOps oper);
1706
1707     inline GenTree(genTreeOps oper, var_types type
1708                    DEBUGARG(bool largeNode = false));
1709 };
1710
1711
1712 /*****************************************************************************/
1713 // In the current design, we never instantiate GenTreeUnOp: it exists only to be
1714 // used as a base class.  For unary operators, we instantiate GenTreeOp, with a NULL second
1715 // argument.  We check that this is true dynamically.  We could tighten this and get static
1716 // checking, but that would entail accessing the first child of a unary operator via something
1717 // like gtUnOp.gtOp1 instead of gtOp.gtOp1.
1718 struct GenTreeUnOp: public GenTree
1719 {
1720     GenTreePtr      gtOp1;
1721
1722 protected:
1723     GenTreeUnOp(genTreeOps oper, var_types type 
1724                 DEBUGARG(bool largeNode = false)) : 
1725         GenTree(oper, type 
1726                 DEBUGARG(largeNode)),
1727         gtOp1(nullptr)
1728         {}
1729
1730     GenTreeUnOp(genTreeOps oper, var_types type, GenTreePtr op1 
1731                 DEBUGARG(bool largeNode = false)) : 
1732         GenTree(oper, type 
1733                 DEBUGARG(largeNode)), 
1734         gtOp1(op1)
1735         {
1736             assert(op1 != nullptr || NullOp1Legal());
1737             if (op1 != nullptr)  // Propagate effects flags from child.
1738                 gtFlags |= op1->gtFlags & GTF_ALL_EFFECT;
1739         }
1740
1741 #if DEBUGGABLE_GENTREE
1742     GenTreeUnOp() : GenTree(), gtOp1(nullptr) {}
1743 #endif
1744 };
1745
1746 struct GenTreeOp: public GenTreeUnOp
1747 {
1748     GenTreePtr      gtOp2;
1749
1750     GenTreeOp(genTreeOps oper, var_types type, GenTreePtr op1, GenTreePtr op2 
1751               DEBUGARG(bool largeNode = false)) : 
1752         GenTreeUnOp(oper, type, op1 
1753                     DEBUGARG(largeNode)), 
1754         gtOp2(op2) 
1755         {
1756             // comparisons are always integral types
1757             assert(!GenTree::OperIsCompare(oper) || varTypeIsIntegral(type));
1758             // Binary operators, with a few exceptions, require a non-nullptr
1759             // second argument.
1760             assert(op2 != nullptr || NullOp2Legal());
1761             // Unary operators, on the other hand, require a null second argument.
1762             assert(!OperIsUnary(oper) || op2 == nullptr);
1763             // Propagate effects flags from child.  (UnOp handled this for first child.)
1764             if (op2 != nullptr)
1765             {
1766                 gtFlags |= op2->gtFlags & GTF_ALL_EFFECT;
1767             }
1768         }
1769
1770     // A small set of types are unary operators with optional arguments.  We use
1771     // this constructor to build those.
1772     GenTreeOp(genTreeOps oper, var_types type 
1773               DEBUGARG(bool largeNode = false)) : 
1774         GenTreeUnOp(oper, type 
1775                     DEBUGARG(largeNode)),
1776         gtOp2(nullptr)
1777         {
1778             // Unary operators with optional arguments:
1779             assert(oper == GT_NOP     ||
1780                    oper == GT_RETURN  ||
1781                    oper == GT_RETFILT ||
1782                    OperIsBlkOp(oper));
1783         }
1784
1785 #if DEBUGGABLE_GENTREE
1786     GenTreeOp() : GenTreeUnOp(), gtOp2(nullptr) {}
1787 #endif
1788 };
1789
1790
1791 struct GenTreeVal: public GenTree
1792 {
1793     size_t          gtVal1;
1794
1795     GenTreeVal(genTreeOps oper, var_types type, ssize_t val) : 
1796         GenTree(oper, type),
1797         gtVal1(val)
1798         {}
1799 #if DEBUGGABLE_GENTREE
1800     GenTreeVal() : GenTree() {}
1801 #endif
1802 };
1803
1804 struct GenTreeIntConCommon: public GenTree
1805 {
1806     inline INT64   LngValue();
1807     inline void    SetLngValue(INT64 val);
1808     inline ssize_t IconValue();
1809     inline void SetIconValue(ssize_t val);
1810     
1811     GenTreeIntConCommon(genTreeOps oper, var_types type
1812                         DEBUGARG(bool largeNode = false)) : 
1813         GenTree(oper, type 
1814                 DEBUGARG(largeNode))
1815         {}
1816
1817         bool FitsInI32() 
1818         {  
1819             return FitsInI32(IconValue());
1820         }
1821
1822         static bool FitsInI32(ssize_t val)
1823         {
1824 #ifdef _TARGET_64BIT_
1825             return (int)val == val;
1826 #else
1827             return true;
1828 #endif
1829         }
1830
1831         bool ImmedValNeedsReloc(Compiler* comp);
1832         bool GenTreeIntConCommon::ImmedValCanBeFolded(Compiler* comp, genTreeOps op);
1833
1834 #ifdef _TARGET_XARCH_
1835         bool FitsInAddrBase(Compiler* comp);
1836         bool AddrNeedsReloc(Compiler* comp);
1837 #endif
1838
1839 #if DEBUGGABLE_GENTREE
1840     GenTreeIntConCommon() : GenTree() {}
1841 #endif
1842 };
1843
1844 // node representing a read from a physical register
1845 struct GenTreePhysReg: public GenTree
1846 {
1847     // physregs need a field beyond gtRegNum because 
1848     // gtRegNum indicates the destination (and can be changed)
1849     // whereas reg indicates the source
1850     regNumber gtSrcReg;
1851     GenTreePhysReg(regNumber r, var_types type=TYP_I_IMPL) : 
1852         GenTree(GT_PHYSREG, type), gtSrcReg(r)
1853     {
1854     }
1855 #if DEBUGGABLE_GENTREE
1856     GenTreePhysReg() : GenTree() {}
1857 #endif
1858 };
1859
1860 #ifndef LEGACY_BACKEND
1861 // gtJumpTable - Switch Jump Table
1862 //
1863 // This node stores a DWORD constant that represents the
1864 // absolute address of a jump table for switches.  The code 
1865 // generator uses this table to code the destination for every case
1866 // in an array of addresses which starting position is stored in
1867 // this constant.
1868 struct GenTreeJumpTable : public GenTreeIntConCommon
1869 {
1870     ssize_t        gtJumpTableAddr;
1871
1872     GenTreeJumpTable(var_types type
1873                   DEBUGARG(bool largeNode = false)) : 
1874         GenTreeIntConCommon(GT_JMPTABLE, type 
1875                             DEBUGARG(largeNode)) 
1876         {}
1877 #if DEBUGGABLE_GENTREE
1878     GenTreeJumpTable() : GenTreeIntConCommon() {}
1879 #endif // DEBUG
1880 };
1881 #endif // !LEGACY_BACKEND
1882
1883 /* gtIntCon -- integer constant (GT_CNS_INT) */
1884 struct GenTreeIntCon: public GenTreeIntConCommon
1885 {
1886     /* 
1887      * This is the GT_CNS_INT struct definition.
1888      * It's used to hold for both int constants and pointer handle constants.
1889      * For the 64-bit targets we will only use GT_CNS_INT as it used to represent all the possible sizes
1890      * For the 32-bit targets we use a GT_CNS_LNG to hold a 64-bit integer constant and GT_CNS_INT for all others.
1891      * In the future when we retarget the JIT for x86 we should consider eliminating GT_CNS_LNG
1892      */
1893     ssize_t         gtIconVal;   // Must overlap and have the same offset with the gtIconVal field in GenTreeLngCon below.
1894     
1895     /* The InitializeArray intrinsic needs to go back to the newarray statement
1896        to find the class handle of the array so that we can get its size.  However,
1897        in ngen mode, the handle in that statement does not correspond to the compile
1898        time handle (rather it lets you get a handle at run-time).  In that case, we also
1899        need to store a compile time handle, which goes in this gtCompileTimeHandle field.
1900     */
1901     ssize_t         gtCompileTimeHandle;
1902
1903     // TODO-Cleanup: It's not clear what characterizes the cases where the field
1904     // above is used.  It may be that its uses and those of the "gtFieldSeq" field below
1905     // are mutually exclusive, and they could be put in a union.  Or else we should separate
1906     // this type into three subtypes.
1907
1908     // If this constant represents the offset of one or more fields, "gtFieldSeq" represents that
1909     // sequence of fields.
1910     FieldSeqNode*   gtFieldSeq;
1911
1912 #if defined (LATE_DISASM)
1913
1914     /*  If the constant was morphed from some other node,
1915         these fields enable us to get back to what the node
1916         originally represented. See use of gtNewIconHandleNode()
1917      */
1918
1919     union
1920     {
1921         /* Template struct - The significant field of the other
1922          * structs should overlap exactly with this struct
1923          */
1924
1925         struct
1926         {
1927             unsigned        gtIconHdl1;
1928             void *          gtIconHdl2;
1929         }
1930                             gtIconHdl;
1931
1932         /* GT_FIELD, etc */
1933
1934         struct
1935         {
1936             unsigned                gtIconCPX;
1937             CORINFO_CLASS_HANDLE    gtIconCls;
1938         }
1939                                     gtIconFld;
1940     };
1941 #endif
1942
1943     GenTreeIntCon(var_types type, ssize_t value
1944                   DEBUGARG(bool largeNode = false)) : 
1945         GenTreeIntConCommon(GT_CNS_INT, type 
1946                             DEBUGARG(largeNode)),
1947         gtIconVal(value),
1948         gtCompileTimeHandle(0),
1949         gtFieldSeq(FieldSeqStore::NotAField())
1950         {}
1951
1952     GenTreeIntCon(var_types type, ssize_t value, FieldSeqNode* fields
1953                   DEBUGARG(bool largeNode = false)) : 
1954         GenTreeIntConCommon(GT_CNS_INT, type 
1955                             DEBUGARG(largeNode)),
1956         gtIconVal(value),
1957         gtCompileTimeHandle(0),
1958         gtFieldSeq(fields)
1959         {
1960             assert(fields != NULL);
1961         }
1962
1963     void FixupInitBlkValue(var_types asgType);
1964
1965 #ifdef _TARGET_64BIT_
1966     void TruncateOrSignExtend32()
1967     {        
1968         if (gtFlags & GTF_UNSIGNED)
1969         {
1970             gtIconVal = UINT32(gtIconVal);
1971         }
1972         else
1973         {
1974             gtIconVal = INT32(gtIconVal);
1975         }
1976     }
1977 #endif // _TARGET_64BIT_
1978
1979 #if DEBUGGABLE_GENTREE
1980     GenTreeIntCon() : GenTreeIntConCommon() {}
1981 #endif
1982 };
1983
1984
1985 /* gtLngCon -- long    constant (GT_CNS_LNG) */
1986
1987 struct GenTreeLngCon: public GenTreeIntConCommon
1988 {
1989     INT64 gtLconVal;   // Must overlap and have the same offset with the gtIconVal field in GenTreeIntCon above.
1990     INT32 LoVal()
1991     {
1992         return (INT32)(gtLconVal & 0xffffffff);
1993     }
1994
1995     INT32 HiVal()
1996     {
1997         return (INT32)(gtLconVal >> 32);;
1998     }
1999
2000     GenTreeLngCon(INT64 val) : 
2001         GenTreeIntConCommon(GT_CNS_NATIVELONG, TYP_LONG)
2002         { SetLngValue(val); }
2003 #if DEBUGGABLE_GENTREE
2004     GenTreeLngCon() : GenTreeIntConCommon() {}
2005 #endif
2006 };
2007
2008
2009 inline INT64 GenTreeIntConCommon::LngValue()
2010 {
2011 #ifndef _TARGET_64BIT_
2012     assert(gtOper == GT_CNS_LNG);
2013     return AsLngCon()->gtLconVal;
2014 #else
2015     return IconValue();
2016 #endif
2017 }
2018
2019 inline void GenTreeIntConCommon::SetLngValue(INT64 val)
2020 {
2021 #ifndef _TARGET_64BIT_
2022     assert(gtOper == GT_CNS_LNG);
2023     AsLngCon()->gtLconVal = val;
2024 #else
2025     // Compile time asserts that these two fields overlap and have the same offsets:  gtIconVal and gtLconVal
2026     C_ASSERT(offsetof(GenTreeLngCon, gtLconVal) == offsetof(GenTreeIntCon, gtIconVal));
2027     C_ASSERT(sizeof(AsLngCon()->gtLconVal) == sizeof(AsIntCon()->gtIconVal));
2028
2029     SetIconValue(ssize_t(val));
2030 #endif
2031 }
2032
2033 inline ssize_t GenTreeIntConCommon::IconValue()
2034 {
2035     assert(gtOper == GT_CNS_INT);   //  We should never see a GT_CNS_LNG for a 64-bit target!
2036     return AsIntCon()->gtIconVal;
2037 }
2038
2039 inline void GenTreeIntConCommon::SetIconValue(ssize_t val)
2040 {
2041     assert(gtOper == GT_CNS_INT);   //  We should never see a GT_CNS_LNG for a 64-bit target!
2042     AsIntCon()->gtIconVal = val;
2043 }
2044
2045 /* gtDblCon -- double  constant (GT_CNS_DBL) */
2046
2047 struct GenTreeDblCon: public GenTree
2048 {
2049     double          gtDconVal;
2050
2051     bool            isBitwiseEqual(GenTreeDblCon* other)
2052     {
2053         unsigned __int64 bits = *(unsigned __int64 *)(&gtDconVal);
2054         unsigned __int64 otherBits = *(unsigned __int64 *)(&(other->gtDconVal));
2055         return (bits == otherBits);
2056     }
2057
2058     GenTreeDblCon(double val) : 
2059         GenTree(GT_CNS_DBL, TYP_DOUBLE),
2060         gtDconVal(val)
2061         {}
2062 #if DEBUGGABLE_GENTREE
2063     GenTreeDblCon() : GenTree() {}
2064 #endif
2065 };
2066
2067
2068 /* gtStrCon -- string  constant (GT_CNS_STR) */
2069
2070 struct GenTreeStrCon: public GenTree
2071 {
2072     unsigned              gtSconCPX;
2073     CORINFO_MODULE_HANDLE gtScpHnd;
2074
2075     // Because this node can come from an inlined method we need to
2076     // have the scope handle, since it will become a helper call.
2077     GenTreeStrCon(unsigned sconCPX, CORINFO_MODULE_HANDLE mod
2078                   DEBUGARG(bool largeNode = false)) : 
2079         GenTree(GT_CNS_STR, TYP_REF 
2080                 DEBUGARG(largeNode)),
2081         gtSconCPX(sconCPX), gtScpHnd(mod)
2082         {}
2083 #if DEBUGGABLE_GENTREE
2084     GenTreeStrCon() : GenTree() {}
2085 #endif
2086 };
2087
2088 // Common supertype of LCL_VAR, LCL_FLD, REG_VAR, PHI_ARG
2089 // This inherits from UnOp because lclvar stores are Unops
2090 struct GenTreeLclVarCommon: public GenTreeUnOp
2091 {
2092 private:
2093     unsigned        _gtLclNum;      // The local number. An index into the Compiler::lvaTable array.
2094     unsigned        _gtSsaNum;      // The SSA number.
2095
2096 public:
2097     GenTreeLclVarCommon(genTreeOps oper, var_types type, unsigned lclNum
2098                         DEBUGARG(bool largeNode = false)) : 
2099         GenTreeUnOp(oper, type 
2100                 DEBUGARG(largeNode))
2101     {
2102         SetLclNum(lclNum);
2103     }
2104
2105     unsigned GetLclNum() const
2106     {
2107         return _gtLclNum;
2108     }
2109     __declspec(property(get=GetLclNum))  unsigned  gtLclNum;
2110
2111     void SetLclNum(unsigned lclNum)
2112     {
2113         _gtLclNum = lclNum;
2114         _gtSsaNum = SsaConfig::RESERVED_SSA_NUM;
2115     }
2116
2117     unsigned GetSsaNum() const
2118     {
2119         return _gtSsaNum;
2120     }
2121     __declspec(property(get=GetSsaNum))  unsigned  gtSsaNum;
2122
2123     void SetSsaNum(unsigned ssaNum)
2124     {
2125         _gtSsaNum = ssaNum;
2126     }
2127
2128     bool HasSsaName()
2129     {
2130         return (gtSsaNum != SsaConfig::RESERVED_SSA_NUM);
2131     }
2132
2133 #if DEBUGGABLE_GENTREE
2134     GenTreeLclVarCommon() : GenTreeUnOp() {}
2135 #endif
2136 };
2137
2138 // gtLclVar -- load/store/addr of local variable 
2139
2140 struct GenTreeLclVar: public GenTreeLclVarCommon
2141 {
2142     IL_OFFSET       gtLclILoffs;    // instr offset of ref (only for debug info)
2143
2144     GenTreeLclVar(var_types type, unsigned lclNum, IL_OFFSET ilOffs
2145                   DEBUGARG(bool largeNode = false)) : 
2146         GenTreeLclVarCommon(GT_LCL_VAR, type, lclNum
2147                             DEBUGARG(largeNode)),
2148             gtLclILoffs(ilOffs)
2149             {}
2150     
2151     GenTreeLclVar(genTreeOps oper, var_types type, unsigned lclNum, IL_OFFSET ilOffs
2152               DEBUGARG(bool largeNode = false)) : 
2153         GenTreeLclVarCommon(oper, type, lclNum
2154                             DEBUGARG(largeNode)),
2155             gtLclILoffs(ilOffs)
2156             {
2157                 assert(OperIsLocal(oper) || OperIsLocalAddr(oper));
2158             }
2159     
2160 #if DEBUGGABLE_GENTREE
2161     GenTreeLclVar() : GenTreeLclVarCommon() {}
2162 #endif
2163 };
2164
2165 // gtLclFld -- load/store/addr of local variable field 
2166
2167 struct GenTreeLclFld: public GenTreeLclVarCommon
2168 {
2169     unsigned        gtLclOffs;      // offset into the variable to access
2170
2171     FieldSeqNode*   gtFieldSeq;     // This LclFld node represents some sequences of accesses.
2172
2173     // old/FE style constructor where load/store/addr share same opcode
2174     GenTreeLclFld(var_types type, unsigned lclNum, unsigned lclOffs) : 
2175         GenTreeLclVarCommon(GT_LCL_FLD, type, lclNum),
2176         gtLclOffs(lclOffs), gtFieldSeq(NULL)
2177         {
2178             assert(sizeof(*this) <= s_gtNodeSizes[GT_LCL_FLD]);
2179         }
2180
2181
2182     GenTreeLclFld(genTreeOps oper, var_types type, unsigned lclNum, unsigned lclOffs) : 
2183         GenTreeLclVarCommon(oper, type, lclNum),
2184         gtLclOffs(lclOffs), gtFieldSeq(NULL)
2185         {
2186             assert(sizeof(*this) <= s_gtNodeSizes[GT_LCL_FLD]);
2187         }
2188 #if DEBUGGABLE_GENTREE
2189     GenTreeLclFld() : GenTreeLclVarCommon() {}
2190 #endif
2191 };
2192
2193 struct GenTreeRegVar: public GenTreeLclVarCommon
2194 {
2195     // TODO-Cleanup: Note that the base class GenTree already has a gtRegNum field.
2196     // It's not clear exactly why a GT_REG_VAR has a separate field. When
2197     // GT_REG_VAR is created, the two are identical. It appears that they may
2198     // or may not remain so. In particular, there is a comment in stackfp.cpp
2199     // that states:
2200     //
2201     //      There used to be an assertion: assert(src->gtRegNum == src->gtRegVar.gtRegNum, ...)
2202     //      here, but there's actually no reason to assume that.  AFAICT, for FP vars under stack FP,
2203     //      src->gtRegVar.gtRegNum is the allocated stack pseudo-register, but src->gtRegNum is the
2204     //      FP stack position into which that is loaded to represent a particular use of the variable.
2205     //
2206     // It might be the case that only for stackfp do they ever differ.
2207     //
2208     // The following might be possible: the GT_REG_VAR node has a last use prior to a complex
2209     // subtree being evaluated. It could then be spilled from the register. Later,
2210     // it could be unspilled into a different register, which would be recorded at
2211     // the unspill time in the GenTree::gtRegNum, whereas GenTreeRegVar::gtRegNum
2212     // is left alone. It's not clear why that is useful.
2213     //
2214     // Assuming there is a particular use, like stack fp, that requires it, maybe we
2215     // can get rid of GT_REG_VAR and just leave it as GT_LCL_VAR, using the base class gtRegNum field.
2216     // If we need it for stackfp, we could add a GenTreeStackFPRegVar type, which carries both the
2217     // pieces of information, in a clearer and more specific way (in particular, with
2218     // a different member name).
2219     //
2220
2221 private:
2222
2223     regNumberSmall  _gtRegNum;
2224
2225 public:
2226
2227     GenTreeRegVar(var_types type, unsigned lclNum, regNumber regNum) : 
2228         GenTreeLclVarCommon(GT_REG_VAR, type, lclNum
2229                             )
2230         {
2231             gtRegNum = regNum;
2232         }
2233
2234     // The register number is stored in a small format (8 bits), but the getters return and the setters take
2235     // a full-size (unsigned) format, to localize the casts here.
2236
2237     __declspec(property(get=GetRegNum,put=SetRegNum))
2238     regNumber           gtRegNum;
2239
2240     regNumber GetRegNum() const
2241     {
2242         return (regNumber) _gtRegNum;
2243     }
2244
2245     void SetRegNum(regNumber reg)
2246     {
2247         _gtRegNum = (regNumberSmall) reg;
2248         assert(_gtRegNum == reg);
2249     }
2250
2251 #if DEBUGGABLE_GENTREE
2252     GenTreeRegVar() : GenTreeLclVarCommon() {}
2253 #endif
2254 };
2255                               
2256 /* gtCast -- conversion to a different type  (GT_CAST) */
2257
2258 struct GenTreeCast: public GenTreeOp
2259 {
2260     GenTreePtr&     CastOp() { return gtOp1; }
2261     var_types       gtCastType;
2262
2263     GenTreeCast(var_types type, GenTreePtr op, var_types castType 
2264                 DEBUGARG(bool largeNode = false)) : 
2265         GenTreeOp(GT_CAST, type, op, nullptr
2266                     DEBUGARG(largeNode)), 
2267         gtCastType(castType) 
2268         {}
2269 #if DEBUGGABLE_GENTREE
2270     GenTreeCast() : GenTreeOp() {}
2271 #endif
2272 };
2273
2274
2275 // GT_BOX nodes are place markers for boxed values.  The "real" tree
2276 // for most purposes is in gtBoxOp.
2277 struct GenTreeBox: public GenTreeUnOp
2278 {
2279     // An expanded helper call to implement the "box" if we don't get
2280     // rid of it any other way.  Must be in same position as op1.
2281
2282     GenTreePtr&      BoxOp() { return gtOp1; }
2283     // This is the statement that contains the assignment tree when the node is an inlined GT_BOX on a value
2284     // type            
2285     GenTreePtr       gtAsgStmtWhenInlinedBoxValue;
2286
2287     GenTreeBox(var_types type, GenTreePtr boxOp, GenTreePtr asgStmtWhenInlinedBoxValue) : 
2288         GenTreeUnOp(GT_BOX, type, boxOp),
2289         gtAsgStmtWhenInlinedBoxValue(asgStmtWhenInlinedBoxValue)
2290         {}
2291 #if DEBUGGABLE_GENTREE
2292     GenTreeBox() : GenTreeUnOp() {}
2293 #endif
2294 };
2295
2296
2297
2298 /* gtField  -- data member ref  (GT_FIELD) */
2299
2300 struct GenTreeField: public GenTree
2301 {
2302     GenTreePtr      gtFldObj;
2303     CORINFO_FIELD_HANDLE    gtFldHnd;
2304     DWORD           gtFldOffset;
2305     bool            gtFldMayOverlap;
2306 #ifdef FEATURE_READYTORUN_COMPILER
2307     CORINFO_CONST_LOOKUP gtFieldLookup;
2308 #endif
2309
2310     GenTreeField(var_types type) : 
2311         GenTree(GT_FIELD, type 
2312                 ) 
2313     {
2314         gtFldMayOverlap = false;
2315     }
2316 #if DEBUGGABLE_GENTREE
2317     GenTreeField() : GenTree() {}
2318 #endif
2319 };
2320
2321 // Represents the Argument list of a call node, as a Lisp-style linked list.
2322 // (Originally I had hoped that this could have *only* the m_arg/m_rest fields, but it turns out
2323 // that enough of the GenTree mechanism is used that it makes sense just to make it a subtype.  But
2324 // note that in many ways, this is *not* a "real" node of the tree, but rather a mechanism for
2325 // giving call nodes a flexible number of children.  GenTreeArgListNodes never evaluate to registers,
2326 // for example.)
2327
2328 // Note that while this extends GenTreeOp, it is *not* an EXOP.  We don't add any new fields, and one
2329 // is free to allocate a GenTreeOp of type GT_LIST.  If you use this type, you get the convenient Current/Rest
2330 // method names for the arguments.
2331 struct GenTreeArgList: public GenTreeOp  
2332 {
2333     GenTreePtr&      Current() { return gtOp1; }
2334     GenTreeArgList*& Rest()    { assert(gtOp2 == NULL || gtOp2->OperGet() == GT_LIST); return *reinterpret_cast<GenTreeArgList**>(&gtOp2); }
2335
2336 #if DEBUGGABLE_GENTREE
2337     GenTreeArgList() : GenTreeOp() {}
2338 #endif
2339
2340     GenTreeArgList(GenTreePtr arg) :
2341         GenTreeArgList(arg, nullptr) {}
2342       
2343     GenTreeArgList(GenTreePtr arg, GenTreeArgList* rest) : 
2344         GenTreeOp(GT_LIST, TYP_VOID, arg, rest) 
2345     {
2346         // With structs passed in multiple args we could have an arg
2347         // GT_LIST containing a list of LCL_FLDs, see IsListForMultiRegArg()
2348         //
2349         assert((arg != nullptr) && ((!arg->IsList()) || (arg->IsListForMultiRegArg())));
2350         gtFlags |=  arg->gtFlags & GTF_ALL_EFFECT;
2351         if (rest != NULL)
2352         {
2353             gtFlags |= rest->gtFlags & GTF_ALL_EFFECT;
2354         }
2355     }
2356 };
2357
2358 // There was quite a bit of confusion in the code base about which of gtOp1 and gtOp2 was the
2359 // 'then' and 'else' clause of a colon node.  Adding these accessors, while not enforcing anything,
2360 // at least *allows* the programmer to be obviously correct.
2361 // However, these conventions seem backward.
2362 // TODO-Cleanup: If we could get these accessors used everywhere, then we could switch them.
2363 struct GenTreeColon: public GenTreeOp
2364 {
2365     GenTreePtr&      ThenNode() { return gtOp2; }
2366     GenTreePtr&      ElseNode() { return gtOp1; }
2367
2368 #if DEBUGGABLE_GENTREE
2369     GenTreeColon() : GenTreeOp() {}
2370 #endif
2371
2372     GenTreeColon(var_types typ, GenTreePtr thenNode, GenTreePtr elseNode) : 
2373         GenTreeOp(GT_COLON, typ, elseNode, thenNode)
2374         {}
2375 };
2376
2377 // gtCall   -- method call      (GT_CALL)
2378 typedef class fgArgInfo *  fgArgInfoPtr;
2379 enum class InlineObservation;
2380
2381 // Return type descriptor of a GT_CALL node.
2382 // x64 Unix, Arm64, Arm32 and x86 allow a value to be returned in multiple
2383 // registers. For such calls this struct provides the following info 
2384 // on their return type
2385 //    - type of value returned in each return register
2386 //    - ABI return register numbers in which the value is returned
2387 //    - count of return registers in which the value is returned
2388 //
2389 // TODO-ARM: Update this to meet the needs of Arm64 and Arm32
2390 //
2391 // TODO-AllArch: Right now it is used for describing multi-reg returned types.
2392 // Eventually we would want to use it for describing even single-reg
2393 // returned types (e.g. structs returned in single register x64/arm).
2394 // This would allow us not to lie or normalize single struct return
2395 // values in importer/morph.
2396 struct ReturnTypeDesc
2397 {
2398 private:
2399     var_types m_regType[MAX_RET_REG_COUNT];
2400
2401 #ifdef DEBUG
2402     bool m_inited;
2403 #endif
2404
2405 public:
2406     ReturnTypeDesc()
2407     {
2408         Reset();
2409     }
2410
2411     // Initialize the return type descriptor given its type handle
2412     void InitializeReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd);
2413
2414     // Reset type descriptor to defaults
2415     void Reset()
2416     {
2417         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2418         {
2419             m_regType[i] = TYP_UNKNOWN;
2420         }
2421 #ifdef DEBUG
2422         m_inited = false;
2423 #endif
2424     }
2425
2426     //--------------------------------------------------------------------------------------------
2427     // GetReturnRegCount:  Get the count of return registers in which the return value is returned.
2428     //
2429     // Arguments:
2430     //    None
2431     //
2432     // Return Value:
2433     //   Count of return registers.
2434     //   Returns 0 if the return type is not returned in registers.
2435     unsigned GetReturnRegCount() const
2436     {
2437         assert(m_inited);
2438
2439         int regCount = 0;
2440         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2441         {
2442             if (m_regType[i] == TYP_UNKNOWN)
2443             {
2444                 break;
2445             }
2446             // otherwise
2447             regCount++;
2448         }
2449
2450 #ifdef DEBUG
2451         // Any remaining elements in m_regTypes[] should also be TYP_UNKNOWN
2452         for (unsigned i = regCount+1; i < MAX_RET_REG_COUNT; ++i)
2453         {
2454             assert(m_regType[i] == TYP_UNKNOWN);
2455         }
2456 #endif        
2457
2458         return regCount;
2459     }
2460
2461     //-----------------------------------------------------------------------
2462     // IsMultiRegRetType: check whether the type is returned in multiple 
2463     // return registers.
2464     //
2465     // Arguments: 
2466     //    None
2467     //
2468     // Return Value:
2469     //    Returns true if the type is returned in multiple return registers.
2470     //    False otherwise.
2471     // Note that we only have to examine the first two values to determine this
2472     //
2473     bool IsMultiRegRetType() const
2474     {
2475         if (MAX_RET_REG_COUNT < 2)
2476         {
2477             return false;
2478         }
2479         else
2480         {
2481             return ((m_regType[0] != TYP_UNKNOWN) &&
2482                     (m_regType[1] != TYP_UNKNOWN));
2483         }
2484     }
2485
2486     //--------------------------------------------------------------------------
2487     // GetReturnRegType:  Get var_type of the return register specified by index.
2488     // 
2489     // Arguments:
2490     //    index - Index of the return register.
2491     //            First return register will have an index 0 and so on.
2492     //
2493     // Return Value:
2494     //    var_type of the return register specified by its index.
2495     //    asserts if the index does not have a valid register return type.
2496     
2497     var_types GetReturnRegType(unsigned index)
2498     {
2499         var_types result = m_regType[index];
2500         assert(result != TYP_UNKNOWN);
2501
2502         return result;
2503     }
2504
2505     // Get ith ABI return register 
2506     regNumber GetABIReturnReg(unsigned idx);
2507
2508     // Get reg mask of ABI return registers 
2509     regMaskTP GetABIReturnRegs();
2510 };
2511
2512 struct GenTreeCall final : public GenTree
2513 {
2514     GenTreePtr        gtCallObjp;             // The instance argument ('this' pointer)
2515     GenTreeArgList*   gtCallArgs;             // The list of arguments in original evaluation order
2516     GenTreeArgList*   gtCallLateArgs;         // On x86:     The register arguments in an optimal order
2517                                               // On ARM/x64: - also includes any outgoing arg space arguments
2518                                               //             - that were evaluated into a temp LclVar
2519     fgArgInfoPtr      fgArgInfo;
2520
2521 #if !FEATURE_FIXED_OUT_ARGS
2522     int               regArgListCount;
2523     regList           regArgList;  
2524 #endif
2525     
2526     // TODO-Throughput: Revisit this (this used to be only defined if
2527     // FEATURE_FIXED_OUT_ARGS was enabled, so this makes GenTreeCall 4 bytes bigger on x86). 
2528     CORINFO_SIG_INFO* callSig;                // Used by tail calls and to register callsites with the EE
2529
2530 #ifdef LEGACY_BACKEND
2531     regMaskTP         gtCallRegUsedMask;      // mask of registers used to pass parameters
2532 #endif // LEGACY_BACKEND
2533
2534     // State required to support multi-reg returning call nodes.
2535     // For now it is enabled only for x64 unix.
2536     //
2537     // TODO-AllArch: enable for all call nodes to unify single-reg and multi-reg returns.
2538 #if FEATURE_MULTIREG_RET
2539     ReturnTypeDesc    gtReturnTypeDesc;
2540
2541     // gtRegNum would always be the first return reg.
2542     // The following array holds the other reg numbers of multi-reg return.
2543     regNumber         gtOtherRegs[MAX_RET_REG_COUNT - 1];
2544
2545     // GTF_SPILL or GTF_SPILLED flag on a multi-reg call node indicates that one or
2546     // more of its result regs are in that state.  The spill flag of each of the
2547     // return register is stored in the below array.
2548     unsigned          gtSpillFlags[MAX_RET_REG_COUNT];
2549 #endif 
2550
2551     //-----------------------------------------------------------------------
2552     // GetReturnTypeDesc: get the type descriptor of return value of the call
2553     //
2554     // Arguments:
2555     //    None
2556     //
2557     // Returns
2558     //    Type descriptor of the value returned by call
2559     //
2560     // Note:
2561     //    Right now implemented only for x64 unix and yet to be 
2562     //    implemented for other multi-reg target arch (Arm64/Arm32/x86).
2563     //
2564     // TODO-AllArch: enable for all call nodes to unify single-reg and multi-reg returns.
2565     ReturnTypeDesc*   GetReturnTypeDesc()
2566     {
2567 #if FEATURE_MULTIREG_RET
2568         return &gtReturnTypeDesc;
2569 #else
2570         return nullptr;
2571 #endif
2572     }
2573
2574     //---------------------------------------------------------------------------
2575     // GetRegNumByIdx: get ith return register allocated to this call node.
2576     //
2577     // Arguments:
2578     //     idx   -   index of the return register
2579     //
2580     // Return Value:
2581     //     Return regNumber of ith return register of call node.
2582     //     Returns REG_NA if there is no valid return register for the given index.
2583     //
2584     regNumber  GetRegNumByIdx(unsigned idx) const
2585     {
2586         assert(idx < MAX_RET_REG_COUNT);
2587
2588         if (idx == 0)
2589         {
2590             return gtRegNum;
2591         }
2592
2593 #if FEATURE_MULTIREG_RET
2594         return gtOtherRegs[idx-1];
2595 #else
2596         return REG_NA;
2597 #endif
2598     }
2599
2600     //----------------------------------------------------------------------
2601     // SetRegNumByIdx: set ith return register of this call node
2602     //
2603     // Arguments:
2604     //    reg    -   reg number
2605     //    idx    -   index of the return register
2606     //
2607     // Return Value:
2608     //    None
2609     //
2610     void  SetRegNumByIdx(regNumber reg, unsigned idx)
2611     {
2612         assert(idx < MAX_RET_REG_COUNT);
2613
2614         if (idx == 0)
2615         {
2616             gtRegNum = reg;
2617         }
2618 #if FEATURE_MULTIREG_RET
2619         else
2620         {
2621             gtOtherRegs[idx - 1] = reg;
2622             assert(gtOtherRegs[idx - 1] == reg);
2623         }
2624 #else
2625         unreached();
2626 #endif
2627     }
2628
2629     //----------------------------------------------------------------------------
2630     // ClearOtherRegs: clear multi-reg state to indicate no regs are allocated
2631     //
2632     // Arguments:
2633     //    None
2634     //
2635     // Return Value:
2636     //    None
2637     //
2638     void  ClearOtherRegs()
2639     {
2640 #if FEATURE_MULTIREG_RET
2641         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
2642         {
2643             gtOtherRegs[i] = REG_NA;
2644         }
2645 #endif
2646     }
2647
2648     //----------------------------------------------------------------------------
2649     // CopyOtherRegs: copy multi-reg state from the given call node to this node
2650     //
2651     // Arguments:
2652     //    fromCall  -  GenTreeCall node from which to copy multi-reg state
2653     //
2654     // Return Value:
2655     //    None
2656     //
2657     void CopyOtherRegs(GenTreeCall* fromCall)
2658     {
2659 #if FEATURE_MULTIREG_RET
2660         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
2661         {
2662             this->gtOtherRegs[i] = fromCall->gtOtherRegs[i];
2663         }
2664 #endif
2665     }
2666
2667     // Get reg mask of all the valid registers of gtOtherRegs array
2668     regMaskTP  GetOtherRegMask() const;
2669
2670     //----------------------------------------------------------------------
2671     // GetRegSpillFlagByIdx: get spill flag associated with the return register 
2672     // specified by its index.
2673     //
2674     // Arguments:
2675     //    idx  -  Position or index of the return register
2676     //
2677     // Return Value:
2678     //    Returns GTF_* flags associated with.
2679     unsigned GetRegSpillFlagByIdx(unsigned idx) const
2680     {
2681         assert(idx < MAX_RET_REG_COUNT);
2682
2683 #if FEATURE_MULTIREG_RET
2684         return gtSpillFlags[idx];
2685 #else
2686         assert(!"unreached");
2687         return 0;
2688 #endif
2689     }
2690
2691     //----------------------------------------------------------------------
2692     // SetRegSpillFlagByIdx: set spill flags for the return register 
2693     // specified by its index.
2694     //
2695     // Arguments:
2696     //    flags  -  GTF_* flags
2697     //    idx    -  Position or index of the return register
2698     //
2699     // Return Value:
2700     //    None
2701     void SetRegSpillFlagByIdx(unsigned flags, unsigned idx)
2702     {
2703         assert(idx < MAX_RET_REG_COUNT);
2704
2705 #if FEATURE_MULTIREG_RET
2706         gtSpillFlags[idx] = flags;
2707 #else
2708         unreached();
2709 #endif
2710     }
2711
2712     //-------------------------------------------------------------------
2713     // clearOtherRegFlags: clear GTF_* flags associated with gtOtherRegs
2714     //
2715     // Arguments:
2716     //     None
2717     //
2718     // Return Value:
2719     //     None
2720     void ClearOtherRegFlags()
2721     {
2722 #if FEATURE_MULTIREG_RET
2723         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2724         {
2725             gtSpillFlags[i] = 0;
2726         }
2727 #endif
2728     }
2729
2730     //-------------------------------------------------------------------------
2731     // CopyOtherRegFlags: copy GTF_* flags associated with gtOtherRegs from
2732     // the given call node.
2733     //
2734     // Arguments:
2735     //    fromCall  -  GenTreeCall node from which to copy
2736     //
2737     // Return Value:
2738     //    None
2739     //
2740     void CopyOtherRegFlags(GenTreeCall* fromCall)
2741     {
2742 #if FEATURE_MULTIREG_RET
2743         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2744         {
2745             this->gtSpillFlags[i] = fromCall->gtSpillFlags[i];
2746         }
2747 #endif
2748     }
2749
2750 #define     GTF_CALL_M_EXPLICIT_TAILCALL       0x0001  // GT_CALL -- the call is "tail" prefixed and importer has performed tail call checks
2751 #define     GTF_CALL_M_TAILCALL                0x0002  // GT_CALL -- the call is a tailcall
2752 #define     GTF_CALL_M_VARARGS                 0x0004  // GT_CALL -- the call uses varargs ABI
2753 #define     GTF_CALL_M_RETBUFFARG              0x0008  // GT_CALL -- first parameter is the return buffer argument
2754 #define     GTF_CALL_M_DELEGATE_INV            0x0010  // GT_CALL -- call to Delegate.Invoke
2755 #define     GTF_CALL_M_NOGCCHECK               0x0020  // GT_CALL -- not a call for computing full interruptability
2756 #define     GTF_CALL_M_SPECIAL_INTRINSIC       0x0040  // GT_CALL -- function that could be optimized as an intrinsic 
2757                                                        // in special cases. Used to optimize fast way out in morphing
2758 #define     GTF_CALL_M_UNMGD_THISCALL          0x0080  // "this" pointer (first argument) should be enregistered (only for GTF_CALL_UNMANAGED)
2759 #define     GTF_CALL_M_VIRTSTUB_REL_INDIRECT   0x0080  // the virtstub is indirected through a relative address (only for GTF_CALL_VIRT_STUB)
2760 #define     GTF_CALL_M_NONVIRT_SAME_THIS       0x0080  // callee "this" pointer is equal to caller this pointer (only for GTF_CALL_NONVIRT)
2761 #define     GTF_CALL_M_FRAME_VAR_DEATH         0x0100  // GT_CALL -- the compLvFrameListRoot variable dies here (last use)
2762
2763 #ifndef LEGACY_BACKEND
2764 #define     GTF_CALL_M_TAILCALL_VIA_HELPER     0x0200  // GT_CALL -- call is a tail call dispatched via tail call JIT helper.
2765 #endif // !LEGACY_BACKEND
2766
2767 #if FEATURE_TAILCALL_OPT
2768 #define     GTF_CALL_M_IMPLICIT_TAILCALL       0x0400  // GT_CALL -- call is an opportunistic tail call and importer has performed tail call checks
2769 #define     GTF_CALL_M_TAILCALL_TO_LOOP        0x0800  // GT_CALL -- call is a fast recursive tail call that can be converted into a loop
2770 #endif
2771
2772 #define     GTF_CALL_M_PINVOKE                 0x1000  // GT_CALL -- call is a pinvoke.  This mirrors VM flag CORINFO_FLG_PINVOKE.
2773                                                        // A call marked as Pinvoke is not necessarily a GT_CALL_UNMANAGED. For e.g.
2774                                                        // an IL Stub dynamically generated for a PInvoke declaration is flagged as
2775                                                        // a Pinvoke but not as an unmanaged call. See impCheckForPInvokeCall() to
2776                                                        // know when these flags are set.
2777
2778 #define     GTF_CALL_M_R2R_REL_INDIRECT        0x2000  // GT_CALL -- ready to run call is indirected through a relative address
2779
2780     bool IsUnmanaged()       const { return (gtFlags & GTF_CALL_UNMANAGED) != 0; }
2781     bool NeedsNullCheck()    const { return (gtFlags & GTF_CALL_NULLCHECK) != 0; }
2782     bool CallerPop()         const { return (gtFlags & GTF_CALL_POP_ARGS) != 0;  }
2783     bool IsVirtual()         const { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) != GTF_CALL_NONVIRT; }
2784     bool IsVirtualStub()     const { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) == GTF_CALL_VIRT_STUB; }
2785     bool IsVirtualVtable()   const { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) == GTF_CALL_VIRT_VTABLE; }
2786     bool IsInlineCandidate() const { return (gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0; }
2787
2788 #ifndef LEGACY_BACKEND
2789     bool HasNonStandardAddedArgs(Compiler* compiler) const;
2790     int GetNonStandardAddedArgCount(Compiler* compiler) const;
2791 #endif // !LEGACY_BACKEND
2792
2793     // Returns true if this call uses a retBuf argument and its calling convention
2794     bool HasRetBufArg() const
2795     {
2796          return (gtCallMoreFlags & GTF_CALL_M_RETBUFFARG) != 0;
2797     }
2798
2799     //-------------------------------------------------------------------------
2800     // TreatAsHasRetBufArg:
2801     //
2802     // Arguments:
2803     //     compiler, the compiler instance so that we can call eeGetHelperNum
2804     //
2805     // Return Value:
2806     //     Returns true if we treat the call as if it has a retBuf argument
2807     //     This method may actually have a retBuf argument 
2808     //     or it could be a JIT helper that we are still transforming during 
2809     //     the importer phase.
2810     //
2811     // Notes:
2812     //     On ARM64 marking the method with the GTF_CALL_M_RETBUFFARG flag
2813     //     will make HasRetBufArg() return true, but will also force the 
2814     //     use of register x8 to pass the RetBuf argument.
2815     //
2816     bool TreatAsHasRetBufArg(Compiler* compiler) const;
2817
2818     //-----------------------------------------------------------------------------------------
2819     // HasMultiRegRetVal: whether the call node returns its value in multiple return registers.
2820     //
2821     // Arguments:
2822     //     None
2823     //
2824     // Return Value:
2825     //     True if the call is returning a multi-reg return value. False otherwise.
2826     //
2827     // Note:
2828     //     This is implemented only for x64 Unix and yet to be implemented for
2829     //     other multi-reg return target arch (arm64/arm32/x86).
2830     //
2831     // TODO-ARM: Implement this routine for Arm64 and Arm32
2832     bool HasMultiRegRetVal() const 
2833     { 
2834 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
2835         return varTypeIsStruct(gtType) && !HasRetBufArg(); 
2836 #elif defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)
2837         // LEGACY_BACKEND does not use multi reg returns for calls with long return types
2838         return varTypeIsLong(gtType);
2839 #else
2840         return false;
2841 #endif
2842     }
2843
2844     // Returns true if VM has flagged this method as CORINFO_FLG_PINVOKE.
2845     bool IsPInvoke() const              { return (gtCallMoreFlags & GTF_CALL_M_PINVOKE) != 0; }
2846
2847     // Note that the distinction of whether tail prefixed or an implicit tail call
2848     // is maintained on a call node till fgMorphCall() after which it will be
2849     // either a tail call (i.e. IsTailCall() is true) or a non-tail call.
2850     bool IsTailPrefixedCall() const     { return (gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0; }     
2851
2852     // This method returning "true" implies that tail call flowgraph morhphing has 
2853     // performed final checks and committed to making a tail call.
2854     bool IsTailCall() const             { return (gtCallMoreFlags & GTF_CALL_M_TAILCALL) != 0; }
2855
2856     // This method returning "true" implies that importer has performed tail call checks
2857     // and providing a hint that this can be converted to a tail call.
2858     bool CanTailCall() const            { return IsTailPrefixedCall() || IsImplicitTailCall(); }
2859
2860 #ifndef LEGACY_BACKEND
2861     bool IsTailCallViaHelper() const    { return IsTailCall() && (gtCallMoreFlags & GTF_CALL_M_TAILCALL_VIA_HELPER); } 
2862 #else // LEGACY_BACKEND
2863     bool IsTailCallViaHelper() const    { return true; }
2864 #endif // LEGACY_BACKEND
2865
2866 #if FEATURE_FASTTAILCALL    
2867     bool IsFastTailCall() const         { return IsTailCall() && !(gtCallMoreFlags & GTF_CALL_M_TAILCALL_VIA_HELPER); }
2868 #else // !FEATURE_FASTTAILCALL
2869     bool IsFastTailCall() const         { return false; }    
2870 #endif // !FEATURE_FASTTAILCALL
2871
2872 #if FEATURE_TAILCALL_OPT
2873     // Returns true if this is marked for opportunistic tail calling.
2874     // That is, can be tail called though not explicitly prefixed with "tail" prefix.
2875     bool IsImplicitTailCall() const             { return (gtCallMoreFlags & GTF_CALL_M_IMPLICIT_TAILCALL) != 0; }
2876     bool IsTailCallConvertibleToLoop() const    { return (gtCallMoreFlags & GTF_CALL_M_TAILCALL_TO_LOOP) != 0; }
2877 #else // !FEATURE_TAILCALL_OPT
2878     bool IsImplicitTailCall() const             { return false; }
2879     bool IsTailCallConvertibleToLoop() const    { return false; }
2880 #endif // !FEATURE_TAILCALL_OPT
2881
2882     bool IsSameThis() const                 { return (gtCallMoreFlags & GTF_CALL_M_NONVIRT_SAME_THIS) != 0; } 
2883     bool IsDelegateInvoke() const           { return (gtCallMoreFlags & GTF_CALL_M_DELEGATE_INV) != 0; } 
2884     bool IsVirtualStubRelativeIndir() const { return (gtCallMoreFlags & GTF_CALL_M_VIRTSTUB_REL_INDIRECT) != 0; } 
2885
2886 #ifdef FEATURE_READYTORUN_COMPILER
2887     bool IsR2RRelativeIndir() const         { return (gtCallMoreFlags & GTF_CALL_M_R2R_REL_INDIRECT) != 0; }
2888     void setEntryPoint(CORINFO_CONST_LOOKUP entryPoint)
2889     {
2890         gtEntryPoint = entryPoint;
2891         if (gtEntryPoint.accessType == IAT_PVALUE)
2892         {
2893             gtCallMoreFlags |= GTF_CALL_M_R2R_REL_INDIRECT;
2894         }
2895     }
2896 #endif // FEATURE_READYTORUN_COMPILER
2897
2898     bool IsVarargs() const                  { return (gtCallMoreFlags & GTF_CALL_M_VARARGS) != 0; }
2899
2900     unsigned short  gtCallMoreFlags;        // in addition to gtFlags
2901     
2902     unsigned char   gtCallType   :3;        // value from the gtCallTypes enumeration
2903     unsigned char   gtReturnType :5;        // exact return type
2904
2905     CORINFO_CLASS_HANDLE    gtRetClsHnd;    // The return type handle of the call if it is a struct; always available
2906
2907     union
2908     {
2909         // only used for CALLI unmanaged calls (CT_INDIRECT)
2910         GenTreePtr      gtCallCookie;           
2911         // gtInlineCandidateInfo is only used when inlining methods 
2912         InlineCandidateInfo* gtInlineCandidateInfo;
2913         void* gtStubCallStubAddr;             // GTF_CALL_VIRT_STUB - these are never inlined                
2914         CORINFO_GENERIC_HANDLE compileTimeHelperArgumentHandle; // Used to track type handle argument of dynamic helpers
2915         void* gtDirectCallAddress; // Used to pass direct call address between lower and codegen
2916     };
2917
2918     // expression evaluated after args are placed which determines the control target
2919     GenTree * gtControlExpr; 
2920
2921     union
2922     {
2923         CORINFO_METHOD_HANDLE gtCallMethHnd;  // CT_USER_FUNC
2924         GenTreePtr  gtCallAddr;               // CT_INDIRECT
2925     };
2926
2927 #ifdef FEATURE_READYTORUN_COMPILER
2928     // Call target lookup info for method call from a Ready To Run module
2929     CORINFO_CONST_LOOKUP gtEntryPoint;
2930 #endif
2931
2932 #if defined(DEBUG) || defined(INLINE_DATA)
2933     // For non-inline candidates, track the first observation
2934     // that blocks candidacy.
2935     InlineObservation gtInlineObservation;
2936
2937     // IL offset of the call wrt its parent method.
2938     IL_OFFSET gtRawILOffset;
2939 #endif // defined(DEBUG) || defined(INLINE_DATA)
2940  
2941     bool IsHelperCall() const
2942     {
2943         return gtCallType == CT_HELPER;
2944     }
2945  
2946     bool IsHelperCall(CORINFO_METHOD_HANDLE callMethHnd) const
2947     {
2948         return IsHelperCall() && (callMethHnd == gtCallMethHnd);
2949     }
2950  
2951     bool IsHelperCall(Compiler* compiler, unsigned helper) const;
2952
2953     GenTreeCall(var_types type) : 
2954         GenTree(GT_CALL, type) 
2955     {
2956     }
2957 #if DEBUGGABLE_GENTREE
2958     GenTreeCall() : GenTree()
2959     {
2960     }
2961 #endif
2962 };
2963
2964 struct GenTreeCmpXchg: public GenTree
2965 {
2966     GenTreePtr      gtOpLocation;
2967     GenTreePtr      gtOpValue;
2968     GenTreePtr      gtOpComparand;
2969
2970     GenTreeCmpXchg(var_types type, GenTreePtr loc, GenTreePtr val, GenTreePtr comparand) : 
2971         GenTree(GT_CMPXCHG, type), 
2972         gtOpLocation(loc), gtOpValue(val),  gtOpComparand(comparand)
2973         {
2974             // There's no reason to do a compare-exchange on a local location, so we'll assume that all of these
2975             // have global effects.
2976             gtFlags |= GTF_GLOB_EFFECT;
2977         }
2978 #if DEBUGGABLE_GENTREE
2979     GenTreeCmpXchg() : GenTree() {}
2980 #endif
2981 };
2982
2983
2984
2985 struct GenTreeFptrVal: public GenTree
2986 {
2987     CORINFO_METHOD_HANDLE gtFptrMethod;
2988
2989 #ifdef FEATURE_READYTORUN_COMPILER
2990     CORINFO_CONST_LOOKUP gtEntryPoint;
2991     CORINFO_RESOLVED_TOKEN* gtLdftnResolvedToken;
2992 #endif
2993
2994     GenTreeFptrVal(var_types type, CORINFO_METHOD_HANDLE meth) : 
2995         GenTree(GT_FTN_ADDR, type), 
2996         gtFptrMethod(meth) 
2997         {}
2998 #if DEBUGGABLE_GENTREE
2999     GenTreeFptrVal() : GenTree() {}
3000 #endif
3001 };
3002
3003 /* gtQmark */
3004 struct GenTreeQmark : public GenTreeOp
3005 {
3006     // Livesets on entry to then and else subtrees
3007     VARSET_TP       gtThenLiveSet;
3008     VARSET_TP       gtElseLiveSet;
3009     
3010     // The "Compiler*" argument is not a DEBUGARG here because we use it to keep track of the set of
3011     // (possible) QMark nodes.
3012     GenTreeQmark(var_types type, GenTreePtr cond, GenTreePtr colonOp, class Compiler* comp);
3013
3014 #if DEBUGGABLE_GENTREE
3015     GenTreeQmark() : GenTreeOp(GT_QMARK, TYP_INT, NULL, NULL) {}
3016 #endif
3017 };
3018
3019 /* gtIntrinsic   -- intrinsic   (possibly-binary op [NULL op2 is allowed] with an additional field) */
3020
3021 struct GenTreeIntrinsic: public GenTreeOp
3022 {
3023     CorInfoIntrinsics     gtIntrinsicId;
3024     CORINFO_METHOD_HANDLE gtMethodHandle;    // Method handle of the method which is treated as an intrinsic.
3025
3026 #ifdef FEATURE_READYTORUN_COMPILER
3027     // Call target lookup info for method call from a Ready To Run module
3028     CORINFO_CONST_LOOKUP gtEntryPoint;
3029 #endif
3030
3031     GenTreeIntrinsic(var_types type, GenTreePtr op1, CorInfoIntrinsics intrinsicId, CORINFO_METHOD_HANDLE methodHandle) :
3032         GenTreeOp(GT_INTRINSIC, type, op1, NULL),
3033         gtIntrinsicId(intrinsicId),
3034         gtMethodHandle(methodHandle)
3035         {}
3036
3037     GenTreeIntrinsic(var_types type, GenTreePtr op1, GenTreePtr op2, CorInfoIntrinsics intrinsicId, CORINFO_METHOD_HANDLE methodHandle) :
3038         GenTreeOp(GT_INTRINSIC, type, op1, op2),
3039         gtIntrinsicId(intrinsicId),
3040         gtMethodHandle(methodHandle)
3041         {}
3042
3043 #if DEBUGGABLE_GENTREE
3044     GenTreeIntrinsic() : GenTreeOp() {}
3045 #endif
3046 };
3047
3048 #ifdef FEATURE_SIMD
3049
3050 /* gtSIMD   -- SIMD intrinsic   (possibly-binary op [NULL op2 is allowed] with additional fields) */
3051 struct GenTreeSIMD: public GenTreeOp
3052 {
3053     SIMDIntrinsicID         gtSIMDIntrinsicID;  // operation Id
3054     var_types               gtSIMDBaseType;     // SIMD vector base type
3055     unsigned                gtSIMDSize;         // SIMD vector size in bytes
3056
3057     GenTreeSIMD(var_types type, GenTreePtr op1, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size) : 
3058         GenTreeOp(GT_SIMD, type, op1, nullptr),
3059         gtSIMDIntrinsicID(simdIntrinsicID),
3060         gtSIMDBaseType(baseType),
3061         gtSIMDSize(size)
3062         {}
3063
3064     GenTreeSIMD(var_types type, GenTreePtr op1, GenTreePtr op2, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size) : 
3065         GenTreeOp(GT_SIMD, type, op1, op2),
3066         gtSIMDIntrinsicID(simdIntrinsicID),
3067         gtSIMDBaseType(baseType),
3068         gtSIMDSize(size)
3069         {}
3070
3071 #if DEBUGGABLE_GENTREE
3072     GenTreeSIMD() : GenTreeOp() {}
3073 #endif
3074 };
3075 #endif // FEATURE_SIMD
3076
3077 /* gtIndex -- array access */
3078
3079 struct GenTreeIndex: public GenTreeOp
3080 {
3081     GenTreePtr&     Arr()   { return gtOp1; }
3082     GenTreePtr&     Index() { return gtOp2; }
3083
3084     unsigned        gtIndElemSize;  // size of elements in the array
3085     CORINFO_CLASS_HANDLE gtStructElemClass;   // If the element type is a struct, this is the struct type.
3086
3087     GenTreeIndex(var_types type, GenTreePtr arr, GenTreePtr ind, unsigned indElemSize) :
3088         GenTreeOp(GT_INDEX, type, arr, ind),
3089         gtIndElemSize(indElemSize),
3090         gtStructElemClass(nullptr)  // We always initialize this after construction.
3091         {
3092 #ifdef DEBUG
3093             if (JitConfig.JitSkipArrayBoundCheck() == 1)
3094             {
3095                 // Skip bounds check
3096             }
3097             else
3098 #endif
3099             {
3100                 // Do bounds check
3101                 gtFlags |= GTF_INX_RNGCHK;
3102             }
3103
3104             if (type == TYP_REF)
3105             {
3106                 gtFlags |= GTF_INX_REFARR_LAYOUT;
3107             }
3108
3109             gtFlags |= GTF_EXCEPT|GTF_GLOB_REF;
3110         }
3111 #if DEBUGGABLE_GENTREE
3112     GenTreeIndex() : GenTreeOp() {}
3113 #endif
3114 };
3115
3116 /* gtArrLen -- array length (GT_ARR_LENGTH)
3117    GT_ARR_LENGTH is used for "arr.length" */
3118
3119 struct GenTreeArrLen: public GenTreeUnOp
3120 {
3121     GenTreePtr&     ArrRef() { return gtOp1; }   // the array address node
3122 private:
3123     int             gtArrLenOffset; // constant to add to "gtArrRef" to get the address of the array length.
3124
3125 public:
3126     inline int      ArrLenOffset() {
3127         return gtArrLenOffset;
3128     }
3129
3130     GenTreeArrLen(var_types type, GenTreePtr arrRef, int lenOffset) : 
3131         GenTreeUnOp(GT_ARR_LENGTH, type, arrRef), 
3132         gtArrLenOffset(lenOffset)
3133         {}
3134
3135 #if DEBUGGABLE_GENTREE
3136     GenTreeArrLen() : GenTreeUnOp() {}
3137 #endif
3138 };
3139
3140 // This takes:
3141 // - a comparison value (generally an array length),
3142 // - an index value, and
3143 // - the label to jump to if the index is out of range.
3144 // - the "kind" of the throw block to branch to on failure
3145 // It generates no result.
3146
3147 struct GenTreeBoundsChk: public GenTree
3148 {
3149     GenTreePtr              gtArrLen;       // An expression for the length of the array being indexed.
3150     GenTreePtr              gtIndex;        // The index expression.
3151
3152     GenTreePtr              gtIndRngFailBB; // Label to jump to for array-index-out-of-range
3153     SpecialCodeKind         gtThrowKind;    // Kind of throw block to branch to on failure
3154
3155     /* Only out-of-ranges at same stack depth can jump to the same label (finding return address is easier)
3156        For delayed calling of fgSetRngChkTarget() so that the
3157        optimizer has a chance of eliminating some of the rng checks */
3158     unsigned        gtStkDepth;
3159
3160     GenTreeBoundsChk(genTreeOps oper, var_types type, GenTreePtr arrLen, GenTreePtr index, SpecialCodeKind kind) : 
3161         GenTree(oper, type), 
3162         gtArrLen(arrLen), gtIndex(index), 
3163         gtIndRngFailBB(NULL), 
3164         gtThrowKind(kind),
3165         gtStkDepth(0)
3166         {
3167             // Effects flags propagate upwards.
3168             gtFlags |= (arrLen->gtFlags & GTF_ALL_EFFECT);
3169             gtFlags |= GTF_EXCEPT;
3170         }
3171 #if DEBUGGABLE_GENTREE
3172     GenTreeBoundsChk() : GenTree() {}
3173 #endif
3174
3175     // If the gtArrLen is really an array length, returns array reference, else "NULL".
3176     GenTreePtr GetArray()
3177     {
3178         if (gtArrLen->OperGet() == GT_ARR_LENGTH)
3179         {
3180             return gtArrLen->gtArrLen.ArrRef();
3181         }
3182         else
3183         {
3184             return NULL;
3185         }
3186     }
3187 };
3188
3189 // gtArrElem -- general array element (GT_ARR_ELEM), for non "SZ_ARRAYS"
3190 //              -- multidimensional arrays, or 1-d arrays with non-zero lower bounds.
3191
3192 struct GenTreeArrElem: public GenTree
3193 {
3194     GenTreePtr      gtArrObj;
3195
3196     #define         GT_ARR_MAX_RANK 3
3197     GenTreePtr      gtArrInds[GT_ARR_MAX_RANK]; // Indices
3198     unsigned char   gtArrRank;                  // Rank of the array
3199
3200     unsigned char   gtArrElemSize;              // !!! Caution, this is an "unsigned char", it is used only
3201                                                 // on the optimization path of array intrisics.
3202                                                 // It stores the size of array elements WHEN it can fit
3203                                                 // into an "unsigned char".
3204                                                 // This has caused VSW 571394.
3205     var_types       gtArrElemType;              // The array element type
3206
3207     // Requires that "inds" is a pointer to an array of "rank" GenTreePtrs for the indices.
3208     GenTreeArrElem(var_types type, GenTreePtr arr, unsigned char rank, unsigned char elemSize, var_types elemType, GenTreePtr* inds) : 
3209         GenTree(GT_ARR_ELEM, type), 
3210         gtArrObj(arr), gtArrRank(rank), gtArrElemSize(elemSize), gtArrElemType(elemType)
3211         {
3212             for (unsigned char i = 0; i < rank; i++) gtArrInds[i] = inds[i];
3213             gtFlags |= GTF_EXCEPT;
3214         }
3215 #if DEBUGGABLE_GENTREE
3216     GenTreeArrElem() : GenTree() {}
3217 #endif
3218 };
3219
3220 //--------------------------------------------
3221 // 
3222 // GenTreeArrIndex (gtArrIndex): Expression to bounds-check the index for one dimension of a
3223 //    multi-dimensional or non-zero-based array., and compute the effective index
3224 //    (i.e. subtracting the lower bound).
3225 //
3226 // Notes:
3227 //    This node is similar in some ways to GenTreeBoundsChk, which ONLY performs the check.
3228 //    The reason that this node incorporates the check into the effective index computation is
3229 //    to avoid duplicating the codegen, as the effective index is required to compute the
3230 //    offset anyway.
3231 //    TODO-CQ: Enable optimization of the lower bound and length by replacing this:
3232 //                /--*  <arrObj>
3233 //                +--*  <index0>
3234 //             +--* ArrIndex[i, ]
3235 //    with something like:
3236 //                   /--*  <arrObj>
3237 //                /--*  ArrLowerBound[i, ]
3238 //                |  /--*  <arrObj>
3239 //                +--*  ArrLen[i, ]    (either generalize GT_ARR_LENGTH or add a new node)
3240 //                +--*  <index0>
3241 //             +--* ArrIndex[i, ]
3242 //    Which could, for example, be optimized to the following when known to be within bounds:
3243 //                /--*  TempForLowerBoundDim0
3244 //                +--*  <index0>
3245 //             +--* - (GT_SUB)
3246 //
3247 struct GenTreeArrIndex: public GenTreeOp
3248 {
3249     // The array object - may be any expression producing an Array reference, but is likely to be a lclVar.
3250     GenTreePtr&     ArrObj()    { return gtOp1; }
3251     // The index expression - may be any integral expression.
3252     GenTreePtr&     IndexExpr() { return gtOp2; }
3253     unsigned char   gtCurrDim;      // The current dimension
3254     unsigned char   gtArrRank;      // Rank of the array
3255     var_types       gtArrElemType;  // The array element type
3256
3257     GenTreeArrIndex(var_types type, GenTreePtr arrObj, GenTreePtr indexExpr,
3258                   unsigned char currDim, unsigned char arrRank, var_types elemType) :
3259         GenTreeOp(GT_ARR_INDEX, type, arrObj, indexExpr),
3260                   gtCurrDim(currDim), gtArrRank(arrRank), gtArrElemType(elemType)
3261     {
3262         gtFlags |= GTF_EXCEPT;
3263     }
3264 #if DEBUGGABLE_GENTREE
3265 protected:
3266     friend GenTree;
3267     // Used only for GenTree::GetVtableForOper()
3268     GenTreeArrIndex() : GenTreeOp() {}
3269 #endif
3270 };
3271
3272 // Represents either an InitBlk, InitObj, CpBlk or CpObj 
3273 // MSIL OpCode.
3274 struct GenTreeBlkOp : public GenTreeOp
3275 {
3276 public:
3277     // The destination for the CpBlk/CpObj/InitBlk/InitObj to copy bits to
3278     GenTreePtr Dest()         { 
3279                                 assert(gtOp1->gtOper == GT_LIST);
3280                                 return gtOp1->gtOp.gtOp1;
3281                               }
3282
3283     // Return true iff the object being copied contains one or more GC pointers.
3284     bool        HasGCPtr();
3285
3286     // True if this BlkOpNode is a volatile memory operation.
3287     bool IsVolatile() const { return (gtFlags & GTF_BLK_VOLATILE) != 0; }
3288
3289     // True if this BlkOpNode is a volatile memory operation.
3290     bool IsUnaligned() const { return (gtFlags & GTF_BLK_UNALIGNED) != 0; }
3291
3292     // Instruction selection: during codegen time, what code sequence we will be using
3293     // to encode this operation.
3294     enum
3295     {
3296         BlkOpKindInvalid,
3297         BlkOpKindHelper,
3298         BlkOpKindRepInstr,
3299         BlkOpKindUnroll,
3300     } gtBlkOpKind;
3301
3302     bool gtBlkOpGcUnsafe; 
3303
3304     GenTreeBlkOp(genTreeOps oper) :
3305         GenTreeOp(oper, TYP_VOID DEBUGARG(true)),
3306             gtBlkOpKind(BlkOpKindInvalid),
3307             gtBlkOpGcUnsafe(false)
3308     {
3309         assert(OperIsBlkOp(oper));
3310     }
3311
3312 #if DEBUGGABLE_GENTREE
3313 protected:
3314     friend GenTree;
3315     GenTreeBlkOp() : GenTreeOp(){}
3316 #endif // DEBUGGABLE_GENTREE
3317 };
3318
3319 // gtObj  -- 'object' (GT_OBJ). */
3320
3321 struct GenTreeObj: public GenTreeUnOp
3322 {
3323     // The address of the block.
3324     GenTreePtr&     Addr()          { return gtOp1; }
3325
3326     CORINFO_CLASS_HANDLE gtClass;   // the class of the object
3327
3328     GenTreeObj(var_types type, GenTreePtr addr, CORINFO_CLASS_HANDLE cls) : 
3329         GenTreeUnOp(GT_OBJ, type, addr),
3330         gtClass(cls)
3331         {
3332             // By default, an OBJ is assumed to be a global reference.
3333             gtFlags |= GTF_GLOB_REF;
3334         }
3335
3336 #if DEBUGGABLE_GENTREE
3337     GenTreeObj() : GenTreeUnOp() {}
3338 #endif
3339 };
3340
3341 // Represents a CpObj MSIL Node.
3342 struct GenTreeCpObj : public GenTreeBlkOp
3343 {
3344 public:
3345     // The source for the CpBlk/CpObj to copy bits from
3346     GenTreePtr Source()       {
3347         assert(gtOper == GT_COPYOBJ && gtOp1->gtOper == GT_LIST);
3348         return gtOp1->gtOp.gtOp2;
3349     }
3350
3351     // In the case of CopyObj, this is the class token that represents the type that is being copied.
3352     GenTreePtr ClsTok() { return gtOp2; }
3353
3354     // If non-null, this array represents the gc-layout of the class that is being copied
3355     // with CpObj.
3356     BYTE*       gtGcPtrs;
3357
3358     // If non-zero, this is the number of slots in the class layout that 
3359     // contain gc-pointers.
3360     unsigned    gtGcPtrCount;
3361
3362     // If non-zero, the number of pointer-sized slots that constitutes the class token in CpObj.
3363     unsigned    gtSlots;
3364
3365     GenTreeCpObj(unsigned gcPtrCount, unsigned gtSlots, BYTE* gtGcPtrs) :
3366         GenTreeBlkOp(GT_COPYOBJ),
3367         gtGcPtrs(gtGcPtrs),
3368         gtGcPtrCount(gcPtrCount),
3369         gtSlots(gtSlots){ }
3370
3371 #if DEBUGGABLE_GENTREE
3372 protected:
3373     friend GenTree;
3374     GenTreeCpObj() : GenTreeBlkOp(),
3375         gtGcPtrs(nullptr),
3376         gtGcPtrCount(0),
3377         gtSlots(0) {}
3378 #endif // DEBUGGABLE_GENTREE
3379 };
3380
3381 // Represents either an InitBlk or InitObj MSIL OpCode.
3382 struct GenTreeInitBlk : public GenTreeBlkOp
3383 {
3384 public:
3385
3386     // The value used to fill the destination buffer.
3387     GenTreePtr InitVal() { assert(gtOp1->gtOper == GT_LIST);
3388                            return gtOp1->gtOp.gtOp2; }
3389
3390     // The size of the buffer to be copied.
3391     GenTreePtr Size()    { return gtOp2; }
3392
3393     GenTreeInitBlk() : GenTreeBlkOp(GT_INITBLK){}
3394
3395 #if DEBUGGABLE_GENTREE
3396 protected:
3397     friend GenTree;
3398 #endif // DEBUGGABLE_GENTREE
3399 };
3400
3401 // Represents a CpBlk or CpObj with no GC-pointers MSIL OpCode.
3402 struct GenTreeCpBlk : public GenTreeBlkOp
3403 {
3404 public:
3405
3406     // The value used to fill the destination buffer.
3407     // The source for the CpBlk/CpObj to copy bits from
3408     GenTreePtr Source() { assert(gtOp1->gtOper == GT_LIST);
3409                           return gtOp1->gtOp.gtOp2; }
3410
3411     // The size of the buffer to be copied.
3412     GenTreePtr Size()   { return gtOp2; }
3413
3414     GenTreeCpBlk() : GenTreeBlkOp(GT_COPYBLK){}
3415
3416 #if DEBUGGABLE_GENTREE
3417 protected:
3418     friend GenTree;
3419 #endif // DEBUGGABLE_GENTREE
3420 };
3421
3422 //--------------------------------------------
3423 // 
3424 // GenTreeArrOffset (gtArrOffset): Expression to compute the accumulated offset for the address
3425 //    of an element of a multi-dimensional or non-zero-based array.
3426 //
3427 // Notes:
3428 //    The result of this expression is (gtOffset * dimSize) + gtIndex
3429 //    where dimSize is the length/stride/size of the dimension, and is obtained from gtArrObj.
3430 //    This node is generated in conjunction with the GenTreeArrIndex node, which computes the
3431 //    effective index for a single dimension.  The sub-trees can be separately optimized, e.g.
3432 //    within a loop body where the expression for the 0th dimension may be invariant.
3433 //
3434 //    Here is an example of how the tree might look for a two-dimension array reference:
3435 //                /--*  const 0
3436 //                |  /--* <arrObj>
3437 //                |  +--* <index0>
3438 //                +--* ArrIndex[i, ]
3439 //                +--*  <arrObj>
3440 //             /--| arrOffs[i, ]
3441 //             |  +--*  <arrObj>
3442 //             |  +--*  <index1>
3443 //             +--* ArrIndex[*,j]
3444 //             +--*  <arrObj>
3445 //          /--| arrOffs[*,j]
3446 //    TODO-CQ: see comment on GenTreeArrIndex for how its representation may change.  When that
3447 //    is done, we will also want to replace the <arrObj> argument to arrOffs with the
3448 //    ArrLen as for GenTreeArrIndex.
3449 //
3450 struct GenTreeArrOffs: public GenTree
3451 {
3452     GenTreePtr      gtOffset;       // The accumulated offset for lower dimensions - must be TYP_I_IMPL, and
3453                                     // will either be a CSE temp, the constant 0, or another GenTreeArrOffs node.
3454     GenTreePtr      gtIndex;        // The effective index for the current dimension - must be non-negative
3455                                     // and can be any expression (though it is likely to be either a GenTreeArrIndex,
3456                                     // node, a lclVar, or a constant).
3457     GenTreePtr      gtArrObj;       // The array object - may be any expression producing an Array reference,
3458                                     // but is likely to be a lclVar.
3459     unsigned char   gtCurrDim;      // The current dimension
3460     unsigned char   gtArrRank;      // Rank of the array
3461     var_types       gtArrElemType;  // The array element type
3462
3463     GenTreeArrOffs(var_types type, GenTreePtr offset, GenTreePtr index, GenTreePtr arrObj,
3464                    unsigned char currDim, unsigned char rank, var_types elemType) : 
3465         GenTree(GT_ARR_OFFSET, type), gtOffset(offset), gtIndex(index), gtArrObj(arrObj),
3466                 gtCurrDim(currDim), gtArrRank(rank), gtArrElemType(elemType)
3467     {
3468         assert(index->gtFlags & GTF_EXCEPT);
3469         gtFlags |= GTF_EXCEPT;
3470     }
3471 #if DEBUGGABLE_GENTREE
3472     GenTreeArrOffs() : GenTree() {}
3473 #endif
3474 };
3475
3476 /* gtAddrMode -- Target-specific canonicalized addressing expression (GT_LEA) */
3477
3478 struct GenTreeAddrMode: public GenTreeOp
3479 {
3480     // Address is Base + Index*Scale + Offset.
3481     // These are the legal patterns:
3482     //
3483     //      Base                                // Base != nullptr && Index == nullptr && Scale == 0 && Offset == 0
3484     //      Base + Index*Scale                  // Base != nullptr && Index != nullptr && Scale != 0 && Offset == 0
3485     //      Base + Offset                       // Base != nullptr && Index == nullptr && Scale == 0 && Offset != 0
3486     //      Base + Index*Scale + Offset         // Base != nullptr && Index != nullptr && Scale != 0 && Offset != 0
3487     //             Index*Scale                  // Base == nullptr && Index != nullptr && Scale >  1 && Offset == 0
3488     //             Index*Scale + Offset         // Base == nullptr && Index != nullptr && Scale >  1 && Offset != 0
3489     //                           Offset         // Base == nullptr && Index == nullptr && Scale == 0 && Offset != 0
3490     //
3491     // So, for example:
3492     //      1. Base + Index is legal with Scale==1
3493     //      2. If Index is null, Scale should be zero (or unintialized / unused)
3494     //      3. If Scale==1, then we should have "Base" instead of "Index*Scale", and "Base + Offset" instead of "Index*Scale + Offset".
3495
3496     // First operand is base address/pointer
3497     bool            HasBase() const     { return gtOp1 != nullptr; }
3498     GenTreePtr&     Base()              { return gtOp1; }
3499
3500     // Second operand is scaled index value
3501     bool            HasIndex() const    { return gtOp2 != nullptr; }
3502     GenTreePtr&     Index()             { return gtOp2; }
3503
3504     unsigned        gtScale;        // The scale factor
3505     unsigned        gtOffset;       // The offset to add
3506
3507     GenTreeAddrMode(var_types type, GenTreePtr base, GenTreePtr index,
3508                     unsigned scale, unsigned offset) : 
3509         GenTreeOp(GT_LEA, type, base, index )
3510     {
3511         gtScale = scale;
3512         gtOffset = offset;
3513     }
3514 #if DEBUGGABLE_GENTREE
3515 protected:
3516     friend GenTree;
3517     // Used only for GenTree::GetVtableForOper()
3518     GenTreeAddrMode() : GenTreeOp() {}
3519 #endif
3520 };
3521
3522 // Indir is just an op, no additional data, but some additional abstractions
3523 struct GenTreeIndir: public GenTreeOp
3524 {
3525     // like an assign, op1 is the destination
3526     GenTreePtr&     Addr()      { return gtOp1; }
3527
3528     // these methods provide an interface to the indirection node which 
3529     bool            HasBase();
3530     bool            HasIndex();
3531     GenTree*        Base(); 
3532     GenTree*        Index(); 
3533     unsigned        Scale();
3534     size_t          Offset();
3535
3536     GenTreeIndir(genTreeOps oper, var_types type, GenTree *addr, GenTree *data) : 
3537     GenTreeOp(oper, type, addr, data)
3538     {
3539     }
3540
3541 #if DEBUGGABLE_GENTREE
3542 protected:
3543     friend GenTree;
3544     // Used only for GenTree::GetVtableForOper()
3545     GenTreeIndir() : GenTreeOp() {}
3546 #endif
3547 };
3548
3549 // Read-modify-write status of a RMW memory op rooted at a storeInd 
3550 enum  RMWStatus {    
3551     STOREIND_RMW_STATUS_UNKNOWN,  // RMW status of storeInd unknown
3552                                   // Default status unless modified by IsRMWMemOpRootedAtStoreInd()
3553
3554     // One of these denote storeind is a RMW memory operation.
3555     STOREIND_RMW_DST_IS_OP1,       // StoreInd is known to be a RMW memory op and dst candidate is op1
3556     STOREIND_RMW_DST_IS_OP2,       // StoreInd is known to be a RMW memory op and dst candidate is op2
3557
3558     // One of these denote the reason for storeind is marked as non-RMW operation
3559     STOREIND_RMW_UNSUPPORTED_ADDR, // Addr mode is not yet supported for RMW memory
3560     STOREIND_RMW_UNSUPPORTED_OPER, // Operation is not supported for RMW memory
3561     STOREIND_RMW_UNSUPPORTED_TYPE, // Type is not supported for RMW memory
3562     STOREIND_RMW_INDIR_UNEQUAL     // Indir to read value is not equivalent to indir that writes the value
3563 };
3564
3565 // StoreInd is just a BinOp, with additional RMW status
3566 struct GenTreeStoreInd: public GenTreeIndir
3567 {
3568 #if !CPU_LOAD_STORE_ARCH
3569     // The below flag is set and used during lowering
3570     RMWStatus  gtRMWStatus;
3571
3572     bool  IsRMWStatusUnknown() { return gtRMWStatus == STOREIND_RMW_STATUS_UNKNOWN; }
3573     bool  IsNonRMWMemoryOp() {
3574         return gtRMWStatus == STOREIND_RMW_UNSUPPORTED_ADDR ||
3575                gtRMWStatus == STOREIND_RMW_UNSUPPORTED_OPER ||
3576                gtRMWStatus == STOREIND_RMW_UNSUPPORTED_TYPE ||
3577                gtRMWStatus == STOREIND_RMW_INDIR_UNEQUAL;
3578     }
3579     bool  IsRMWMemoryOp() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP1 || gtRMWStatus == STOREIND_RMW_DST_IS_OP2; }
3580     bool  IsRMWDstOp1() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP1; }
3581     bool  IsRMWDstOp2() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP2; }
3582 #endif //!CPU_LOAD_STORE_ARCH
3583
3584     RMWStatus GetRMWStatus() { 
3585 #if !CPU_LOAD_STORE_ARCH
3586         return gtRMWStatus; 
3587 #else
3588         return STOREIND_RMW_STATUS_UNKNOWN;
3589 #endif
3590     }
3591
3592     void SetRMWStatusDefault() 
3593     {
3594 #if !CPU_LOAD_STORE_ARCH
3595         gtRMWStatus = STOREIND_RMW_STATUS_UNKNOWN;
3596 #endif
3597     }
3598
3599     void SetRMWStatus(RMWStatus status)
3600     {
3601 #if !CPU_LOAD_STORE_ARCH
3602         gtRMWStatus = status;
3603 #endif
3604     }
3605
3606     GenTreePtr&     Data()      { return gtOp2; }
3607
3608     GenTreeStoreInd(var_types type, GenTree *destPtr, GenTree *data) : 
3609     GenTreeIndir(GT_STOREIND, type, destPtr, data)
3610     {
3611         SetRMWStatusDefault();
3612     }
3613
3614 #if DEBUGGABLE_GENTREE
3615 protected:
3616     friend GenTree;
3617     // Used only for GenTree::GetVtableForOper()
3618     GenTreeStoreInd() : GenTreeIndir() { SetRMWStatusDefault(); }
3619 #endif
3620 };
3621
3622
3623 /* gtRetExp -- Place holder for the return expression from an inline candidate (GT_RET_EXPR) */
3624
3625 struct GenTreeRetExpr: public GenTree
3626 {
3627     GenTreePtr      gtInlineCandidate;
3628
3629     CORINFO_CLASS_HANDLE gtRetClsHnd;
3630
3631     GenTreeRetExpr(var_types type) : 
3632         GenTree(GT_RET_EXPR, type) 
3633         {}
3634 #if DEBUGGABLE_GENTREE
3635     GenTreeRetExpr() : GenTree() {}
3636 #endif
3637 };
3638
3639
3640 /* gtStmt   -- 'statement expr' (GT_STMT) */
3641
3642 class InlineContext;
3643
3644 struct GenTreeStmt: public GenTree
3645 {
3646     GenTreePtr      gtStmtExpr;      // root of the expression tree
3647     GenTreePtr      gtStmtList;      // first node (for forward walks)
3648     InlineContext*  gtInlineContext; // The inline context for this statement.
3649   
3650 #if defined(DEBUGGING_SUPPORT) || defined(DEBUG)
3651     IL_OFFSETX      gtStmtILoffsx;   // instr offset (if available)
3652 #endif
3653
3654 #ifdef DEBUG
3655     IL_OFFSET       gtStmtLastILoffs;// instr offset at end of stmt
3656 #endif
3657
3658     bool            gtStmtIsTopLevel()
3659     {
3660         return (gtFlags & GTF_STMT_TOP_LEVEL) != 0;
3661     }
3662
3663     bool            gtStmtIsEmbedded()
3664     {
3665         return !gtStmtIsTopLevel();
3666     }
3667
3668     // Return the next statement, if it is embedded, otherwise nullptr
3669     GenTreeStmt*    gtStmtNextIfEmbedded()
3670     {
3671         GenTree* nextStmt = gtNext;
3672         if (nextStmt != nullptr && nextStmt->gtStmt.gtStmtIsEmbedded())
3673         {
3674             return nextStmt->AsStmt();
3675         }
3676         else
3677         {
3678             return nullptr;
3679         }
3680     }
3681
3682     GenTree*    gtStmtNextTopLevelStmt()
3683     {
3684         GenTree* nextStmt = gtNext;
3685         while (nextStmt != nullptr && nextStmt->gtStmt.gtStmtIsEmbedded())
3686         {
3687             nextStmt = nextStmt->gtNext;
3688         }
3689         return nextStmt;
3690     }
3691
3692     __declspec(property(get=getNextStmt))
3693     GenTreeStmt* gtNextStmt;
3694
3695     __declspec(property(get=getPrevStmt))
3696     GenTreeStmt* gtPrevStmt;
3697
3698     GenTreeStmt* getNextStmt() 
3699     {
3700         if (gtNext == nullptr)
3701             return nullptr;
3702         else
3703             return gtNext->AsStmt();
3704     }
3705
3706     GenTreeStmt* getPrevStmt() 
3707     {
3708         if (gtPrev == nullptr)
3709             return nullptr;
3710         else
3711             return gtPrev->AsStmt();
3712     }
3713
3714     GenTreeStmt(GenTreePtr expr, IL_OFFSETX offset)
3715         : GenTree(GT_STMT, TYP_VOID)
3716         , gtStmtExpr(expr)
3717         , gtStmtList(nullptr)
3718         , gtInlineContext(nullptr)
3719 #if defined(DEBUGGING_SUPPORT) || defined(DEBUG)
3720         , gtStmtILoffsx(offset)
3721 #endif
3722 #ifdef DEBUG
3723         , gtStmtLastILoffs(BAD_IL_OFFSET)
3724 #endif
3725     {
3726         // Statements can't have statements as part of their expression tree.
3727         assert(expr->gtOper != GT_STMT);
3728
3729         gtFlags |= GTF_STMT_TOP_LEVEL;
3730
3731         // Set the statement to have the same costs as the top node of the tree.
3732         // This is used long before costs have been assigned, so we need to copy
3733         // the raw costs.
3734         CopyRawCosts(expr);
3735     }
3736
3737 #if DEBUGGABLE_GENTREE
3738     GenTreeStmt() : GenTree(GT_STMT, TYP_VOID) {}
3739 #endif
3740 };
3741
3742
3743
3744
3745 /*  NOTE: Any tree nodes that are larger than 8 bytes (two ints or
3746     pointers) must be flagged as 'large' in GenTree::InitNodeSize().
3747  */
3748
3749                 
3750 /* gtClsVar -- 'static data member' (GT_CLS_VAR) */
3751
3752 struct GenTreeClsVar: public GenTree
3753 {
3754     CORINFO_FIELD_HANDLE    gtClsVarHnd;
3755     FieldSeqNode*           gtFieldSeq;
3756
3757     GenTreeClsVar(var_types type, CORINFO_FIELD_HANDLE clsVarHnd, FieldSeqNode* fldSeq) : 
3758         GenTree(GT_CLS_VAR, type), 
3759         gtClsVarHnd(clsVarHnd),
3760         gtFieldSeq(fldSeq)
3761         {
3762             gtFlags |= GTF_GLOB_REF;
3763         }
3764 #if DEBUGGABLE_GENTREE
3765     GenTreeClsVar() : GenTree() {}
3766 #endif
3767 };
3768
3769 /* gtArgPlace -- 'register argument placeholder' (GT_ARGPLACE) */
3770
3771 struct GenTreeArgPlace: public GenTree
3772 {
3773     CORINFO_CLASS_HANDLE    gtArgPlaceClsHnd;    // Needed when we have a TYP_STRUCT argument
3774
3775     GenTreeArgPlace(var_types type, CORINFO_CLASS_HANDLE clsHnd) : 
3776         GenTree(GT_ARGPLACE, type), 
3777         gtArgPlaceClsHnd(clsHnd) 
3778         {}
3779 #if DEBUGGABLE_GENTREE
3780     GenTreeArgPlace() : GenTree() {}
3781 #endif
3782 };
3783
3784 /* gtLabel  -- code label target    (GT_LABEL) */
3785
3786 struct GenTreeLabel: public GenTree
3787 {
3788     BasicBlock* gtLabBB;
3789
3790     GenTreeLabel(BasicBlock* bb) : 
3791         GenTree(GT_LABEL, TYP_VOID), 
3792         gtLabBB(bb) 
3793         {}
3794 #if DEBUGGABLE_GENTREE
3795     GenTreeLabel() : GenTree() {}
3796 #endif
3797 };
3798
3799 /* gtPhiArg -- phi node rhs argument, var = phi(phiarg, phiarg, phiarg...); GT_PHI_ARG */
3800 struct GenTreePhiArg: public GenTreeLclVarCommon
3801 {
3802     BasicBlock  *   gtPredBB;
3803
3804     GenTreePhiArg(var_types type, unsigned lclNum, unsigned snum, BasicBlock* block)
3805         : GenTreeLclVarCommon(GT_PHI_ARG, type, lclNum)
3806         , gtPredBB(block)
3807     { 
3808         SetSsaNum(snum);
3809     }
3810
3811 #if DEBUGGABLE_GENTREE
3812     GenTreePhiArg() : GenTreeLclVarCommon() {}
3813 #endif
3814 };
3815
3816 /* gtPutArgStk -- Argument passed on stack */
3817
3818 struct GenTreePutArgStk: public GenTreeUnOp
3819 {
3820     unsigned gtSlotNum;        // Slot number of the argument to be passed on stack
3821
3822 #if FEATURE_FASTTAILCALL
3823     bool putInIncomingArgArea;    // Whether this arg needs to be placed in incoming arg area.
3824                                   // By default this is false and will be placed in out-going arg area.
3825                                   // Fast tail calls set this to true.
3826                                   // In future if we need to add more such bool fields consider bit fields.
3827
3828     GenTreePutArgStk(
3829             genTreeOps oper,
3830             var_types type,
3831             unsigned slotNum
3832             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3833             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct),
3834             bool _putInIncomingArgArea = false
3835             DEBUGARG(GenTreePtr callNode = NULL)
3836             DEBUGARG(bool largeNode = false))
3837         : 
3838         GenTreeUnOp(oper, type DEBUGARG(largeNode)),
3839         gtSlotNum(slotNum),
3840         putInIncomingArgArea(_putInIncomingArgArea)
3841 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3842         , gtPutArgStkKind(PutArgStkKindInvalid),
3843         gtNumSlots(numSlots),
3844         gtIsStruct(isStruct),
3845         gtNumberReferenceSlots(0),
3846         gtGcPtrs(nullptr)
3847 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3848     {
3849 #ifdef DEBUG
3850         gtCall = callNode;
3851 #endif
3852     }
3853
3854
3855     GenTreePutArgStk(
3856             genTreeOps oper,
3857             var_types type,
3858             GenTreePtr op1,
3859             unsigned slotNum
3860             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3861             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct),
3862             bool _putInIncomingArgArea = false
3863             DEBUGARG(GenTreePtr callNode = NULL)
3864             DEBUGARG(bool largeNode = false))
3865         :
3866         GenTreeUnOp(oper, type, op1 DEBUGARG(largeNode)), 
3867         gtSlotNum(slotNum),
3868         putInIncomingArgArea(_putInIncomingArgArea)
3869 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3870         , gtPutArgStkKind(PutArgStkKindInvalid),
3871         gtNumSlots(numSlots),
3872         gtIsStruct(isStruct),
3873         gtNumberReferenceSlots(0),
3874         gtGcPtrs(nullptr)
3875 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3876     {
3877 #ifdef DEBUG
3878         gtCall = callNode;
3879 #endif
3880     }
3881
3882 #else  // !FEATURE_FASTTAILCALL
3883
3884     GenTreePutArgStk(
3885             genTreeOps oper,
3886             var_types type,
3887             unsigned slotNum
3888             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3889             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct)
3890             DEBUGARG(GenTreePtr callNode = NULL)
3891             DEBUGARG(bool largeNode = false))
3892         :
3893         GenTreeUnOp(oper, type DEBUGARG(largeNode)),
3894         gtSlotNum(slotNum)
3895 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3896         , gtPutArgStkKind(PutArgStkKindInvalid),
3897         gtNumSlots(numSlots),
3898         gtIsStruct(isStruct),
3899         gtNumberReferenceSlots(0),
3900         gtGcPtrs(nullptr)
3901 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3902     {
3903 #ifdef DEBUG
3904         gtCall = callNode;
3905 #endif
3906     }
3907
3908
3909     GenTreePutArgStk(
3910             genTreeOps oper,
3911             var_types type,
3912             GenTreePtr op1,
3913             unsigned slotNum
3914             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3915             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct)
3916             DEBUGARG(GenTreePtr callNode = NULL)
3917             DEBUGARG(bool largeNode = false))
3918         :
3919         GenTreeUnOp(oper, type, op1 DEBUGARG(largeNode)), 
3920         gtSlotNum(slotNum)
3921 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3922         , gtPutArgStkKind(PutArgStkKindInvalid),
3923         gtNumSlots(numSlots),
3924         gtIsStruct(isStruct),
3925         gtNumberReferenceSlots(0),
3926         gtGcPtrs(nullptr)
3927 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3928     {
3929 #ifdef DEBUG
3930         gtCall = callNode;
3931 #endif
3932     }
3933 #endif // FEATURE_FASTTAILCALL
3934
3935     unsigned getArgOffset() { return gtSlotNum * TARGET_POINTER_SIZE; }
3936
3937 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3938     unsigned getArgSize() { return gtNumSlots * TARGET_POINTER_SIZE; }
3939 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3940
3941 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3942     //------------------------------------------------------------------------
3943     // setGcPointers: Sets the number of references and the layout of the struct object returned by the VM.
3944     //
3945     // Arguments:
3946     //    numPointers - Number of pointer references.
3947     //    pointers    - layout of the struct (with pointers marked.)
3948     //
3949     // Return Value:
3950     //    None
3951     //
3952     // Notes:
3953     //    This data is used in the codegen for GT_PUTARG_STK to decide how to copy the struct to the stack by value.
3954     //    If no pointer references are used, block copying instructions are used.
3955     //    Otherwise the pointer reference slots are copied atomically in a way that gcinfo is emitted.
3956     //    Any non pointer references between the pointer reference slots are copied in block fashion.
3957     //
3958     void setGcPointers(unsigned numPointers, BYTE* pointers)
3959     {
3960         gtNumberReferenceSlots = numPointers;
3961         gtGcPtrs = pointers;
3962     }
3963 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3964
3965 #ifdef DEBUG
3966     GenTreePtr      gtCall;                // the call node to which this argument belongs
3967 #endif
3968
3969 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3970     // Instruction selection: during codegen time, what code sequence we will be using
3971     // to encode this operation.
3972
3973     enum PutArgStkKind : __int8
3974     {
3975         PutArgStkKindInvalid,
3976         PutArgStkKindRepInstr,
3977         PutArgStkKindUnroll,
3978     };
3979
3980     PutArgStkKind gtPutArgStkKind;
3981
3982     unsigned gtNumSlots;              // Number of slots for the argument to be passed on stack
3983     bool     gtIsStruct;              // This stack arg is a struct.
3984     unsigned gtNumberReferenceSlots;  // Number of reference slots.
3985     BYTE*    gtGcPtrs;                // gcPointers
3986 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3987
3988 #if DEBUGGABLE_GENTREE
3989     GenTreePutArgStk() : GenTreeUnOp() {}
3990 #endif
3991 };
3992
3993 // Represents GT_COPY or GT_RELOAD node
3994 struct GenTreeCopyOrReload : public GenTreeUnOp
3995 {
3996     // State required to support copy/reload of a multi-reg call node.
3997     // First register is is always given by gtRegNum.
3998     //
3999 #if FEATURE_MULTIREG_RET
4000     regNumber gtOtherRegs[MAX_RET_REG_COUNT - 1];
4001 #endif
4002
4003     //----------------------------------------------------------
4004     // ClearOtherRegs: set gtOtherRegs to REG_NA.
4005     //
4006     // Arguments:
4007     //    None
4008     //
4009     // Return Value:
4010     //    None
4011     //
4012     void ClearOtherRegs()
4013     {
4014 #if FEATURE_MULTIREG_RET
4015         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
4016         {
4017             gtOtherRegs[i] = REG_NA;
4018         }
4019 #endif
4020     }
4021
4022     //-----------------------------------------------------------
4023     // GetRegNumByIdx: Get regNumber of ith position.
4024     //
4025     // Arguments:
4026     //    idx   -   register position.
4027     //
4028     // Return Value:
4029     //    Returns regNumber assigned to ith position.
4030     //
4031     regNumber GetRegNumByIdx(unsigned idx) const
4032     {
4033         assert(idx < MAX_RET_REG_COUNT);
4034
4035         if (idx == 0)
4036         {
4037             return gtRegNum;
4038         }
4039
4040 #if FEATURE_MULTIREG_RET
4041         return gtOtherRegs[idx - 1];
4042 #else
4043         return REG_NA;
4044 #endif
4045     }
4046
4047     //-----------------------------------------------------------
4048     // SetRegNumByIdx: Set the regNumber for ith position.
4049     //
4050     // Arguments:
4051     //    reg   -   reg number 
4052     //    idx   -   register position.
4053     //
4054     // Return Value:
4055     //    None.
4056     //
4057     void SetRegNumByIdx(regNumber reg, unsigned idx)
4058     {
4059         assert(idx < MAX_RET_REG_COUNT);
4060
4061         if (idx == 0)
4062         {
4063             gtRegNum = reg;
4064         }
4065 #if FEATURE_MULTIREG_RET
4066         else
4067         {
4068             gtOtherRegs[idx - 1] = reg;
4069             assert(gtOtherRegs[idx - 1] == reg);
4070         }
4071 #else
4072         else
4073         {
4074             unreached();
4075         }
4076 #endif
4077     }
4078
4079     //----------------------------------------------------------------------------
4080     // CopyOtherRegs: copy multi-reg state from the given copy/reload node to this
4081     // node.
4082     //
4083     // Arguments:
4084     //    from  -  GenTree node from which to copy multi-reg state
4085     //
4086     // Return Value:
4087     //    None
4088     //
4089     // TODO-ARM: Implement this routine for Arm64 and Arm32
4090     // TODO-X86: Implement this routine for x86
4091     void CopyOtherRegs(GenTreeCopyOrReload* from)
4092     {
4093         assert(OperGet() == from->OperGet());
4094
4095 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
4096         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
4097         {
4098             gtOtherRegs[i] = from->gtOtherRegs[i];
4099         }
4100 #endif
4101     }
4102
4103     GenTreeCopyOrReload(genTreeOps oper,
4104         var_types type,
4105         GenTree* op1) : GenTreeUnOp(oper, type, op1)
4106     {
4107         gtRegNum = REG_NA;
4108         ClearOtherRegs();
4109     }
4110
4111 #if DEBUGGABLE_GENTREE
4112     GenTreeCopyOrReload() : GenTreeUnOp() {}
4113 #endif
4114 };
4115
4116 //------------------------------------------------------------------------
4117 // Deferred inline functions of GenTree -- these need the subtypes above to
4118 // be defined already.
4119 //------------------------------------------------------------------------
4120
4121 inline bool            GenTree::OperIsBlkOp() const
4122 {
4123     return (gtOper == GT_INITBLK ||
4124             gtOper == GT_COPYBLK ||
4125             gtOper == GT_COPYOBJ);
4126 }
4127
4128 inline bool            GenTree::OperIsDynBlkOp()
4129 {
4130     return (OperIsBlkOp() && !gtGetOp2()->IsCnsIntOrI());
4131 }
4132
4133 inline bool            GenTree::OperIsCopyBlkOp() const
4134 {
4135     return (gtOper == GT_COPYOBJ || gtOper == GT_COPYBLK);
4136 }
4137
4138 inline bool GenTree::OperIsInitBlkOp() const
4139 {
4140     return (gtOper == GT_INITBLK);
4141 }
4142
4143 //------------------------------------------------------------------------
4144 // IsFPZero: Checks whether this is a floating point constant with value 0.0
4145 //
4146 // Return Value:
4147 //    Returns true iff the tree is an GT_CNS_DBL, with value of 0.0.
4148
4149 inline bool GenTree::IsFPZero()
4150 {
4151     if ((gtOper == GT_CNS_DBL) && (gtDblCon.gtDconVal == 0.0))
4152         return true;
4153     return false;
4154 }
4155
4156 //------------------------------------------------------------------------
4157 // IsIntegralConst: Checks whether this is a constant node with the given value
4158 //
4159 // Arguments:
4160 //    constVal - the value of interest
4161 //
4162 // Return Value:
4163 //    Returns true iff the tree is an integral constant opcode, with
4164 //    the given value.
4165 //
4166 // Notes:
4167 //    Like gtIconVal, the argument is of ssize_t, so cannot check for
4168 //    long constants in a target-independent way.
4169
4170 inline bool GenTree::IsIntegralConst(ssize_t constVal)
4171
4172 {
4173     if ((gtOper == GT_CNS_INT) && (gtIntConCommon.IconValue() == constVal))
4174         return true;
4175
4176     if ((gtOper == GT_CNS_LNG) && (gtIntConCommon.LngValue() == constVal))
4177         return true;
4178
4179     return false;
4180 }
4181
4182 inline bool GenTree::IsBoxedValue()
4183 {
4184     assert(gtOper != GT_BOX || gtBox.BoxOp() != NULL);
4185     return (gtOper == GT_BOX) && (gtFlags & GTF_BOX_VALUE);
4186 }
4187
4188 inline GenTreePtr GenTree::MoveNext()
4189 {
4190     assert(IsList());
4191     return gtOp.gtOp2;
4192 }
4193
4194 #ifdef DEBUG
4195 //------------------------------------------------------------------------
4196 // IsListForMultiRegArg: Given an GenTree node that represents an argument
4197 //                       enforce (or don't enforce) the following invariant.
4198 //
4199 // For LEGACY_BACKEND or architectures that don't support MultiReg args
4200 // we don't allow a GT_LIST at all.
4201 //
4202 // Currently for AMD64 UNIX we allow a limited case where a GT_LIST is 
4203 // allowed but every element must be a GT_LCL_FLD.
4204 //
4205 // For the future targets that allow for Multireg args (and this includes
4206 //  the current ARM64 target) we allow a GT_LIST of arbitrary nodes, these
4207 //  would typically start out as GT_LCL_VARs or GT_LCL_FLDS or GT_INDs, 
4208 //  but could be changed into constants or GT_COMMA trees by the later 
4209 //  optimization phases.
4210 // 
4211 // Arguments:
4212 //    instance method for a GenTree node
4213 //
4214 // Return values:
4215 //    true:      the GenTree node is accepted as a valid argument
4216 //    false:     the GenTree node is not accepted as a valid argumeny
4217 //
4218 inline bool GenTree::IsListForMultiRegArg()
4219 {
4220     if (!IsList())
4221     {
4222         // We don't have a GT_LIST, so just return true.
4223         return true;
4224     }
4225     else  // We do have a GT_LIST
4226     {
4227 #if defined(LEGACY_BACKEND) || !FEATURE_MULTIREG_ARGS
4228
4229         // Not allowed to have a GT_LIST for an argument 
4230         // unless we have a RyuJIT backend and FEATURE_MULTIREG_ARGS
4231
4232         return false;
4233
4234 #else  // we have RyuJIT backend and FEATURE_MULTIREG_ARGS
4235
4236 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
4237         // For UNIX ABI we currently only allow a GT_LIST of GT_LCL_FLDs nodes 
4238         GenTree* gtListPtr = this;
4239         while (gtListPtr != nullptr) 
4240         {
4241             // ToDo: fix UNIX_AMD64 so that we do not generate this kind of a List
4242             //  Note the list as currently created is malformed, as the last entry is a nullptr
4243             if (gtListPtr->Current() == nullptr)
4244                 break;
4245
4246             // Only a list of GT_LCL_FLDs is allowed
4247             if (gtListPtr->Current()->OperGet() != GT_LCL_FLD)
4248             {
4249                 return false;
4250             }
4251             gtListPtr = gtListPtr->MoveNext();
4252         }
4253 #endif  // FEATURE_UNIX_AMD64_STRUCT_PASSING
4254
4255         // Note that for non-UNIX ABI the GT_LIST may contain any node
4256         //
4257         // We allow this GT_LIST as an argument 
4258         return true;
4259
4260 #endif  // RyuJIT backend and FEATURE_MULTIREG_ARGS
4261     }
4262 }
4263 #endif // DEBUG
4264
4265 inline GenTreePtr GenTree::Current()
4266 {
4267     assert(IsList());
4268     return gtOp.gtOp1;
4269 }
4270
4271 inline GenTreePtr *GenTree::pCurrent()
4272 {
4273     assert(IsList());
4274     return &(gtOp.gtOp1);
4275 }
4276
4277 inline GenTreePtr      GenTree::gtGetOp1() 
4278 {
4279     return gtOp.gtOp1;
4280 }
4281
4282 #ifdef DEBUG
4283 /* static */
4284 inline bool GenTree::RequiresNonNullOp2(genTreeOps oper)
4285 {
4286     switch (oper)
4287     {
4288     case GT_ADD:
4289     case GT_SUB:
4290     case GT_MUL:
4291     case GT_DIV:
4292     case GT_MOD:
4293     case GT_UDIV:
4294     case GT_UMOD:
4295     case GT_OR:
4296     case GT_XOR:
4297     case GT_AND:
4298     case GT_LSH:
4299     case GT_RSH:
4300     case GT_RSZ:
4301     case GT_ROL:
4302     case GT_ROR:
4303     case GT_INDEX:
4304     case GT_ASG:
4305     case GT_ASG_ADD:
4306     case GT_ASG_SUB:
4307     case GT_ASG_MUL:
4308     case GT_ASG_DIV:
4309     case GT_ASG_MOD:
4310     case GT_ASG_UDIV:
4311     case GT_ASG_UMOD:
4312     case GT_ASG_OR:
4313     case GT_ASG_XOR:
4314     case GT_ASG_AND:
4315     case GT_ASG_LSH:
4316     case GT_ASG_RSH:
4317     case GT_ASG_RSZ:
4318     case GT_EQ:
4319     case GT_NE:
4320     case GT_LT:
4321     case GT_LE:
4322     case GT_GE:
4323     case GT_GT:
4324     case GT_COMMA:
4325     case GT_QMARK:
4326     case GT_COLON:
4327     case GT_MKREFANY:
4328     case GT_INITBLK:
4329     case GT_COPYBLK:
4330         return true;
4331     default:
4332         return false;
4333     }
4334 }
4335 #endif // DEBUG
4336
4337 inline GenTreePtr      GenTree::gtGetOp2() 
4338 {
4339     /* gtOp.gtOp2 is only valid for GTK_BINOP nodes. */
4340
4341     GenTreePtr op2 = OperIsBinary() ? gtOp.gtOp2 : nullptr;
4342
4343     // This documents the genTreeOps for which gtOp.gtOp2 cannot be nullptr.
4344     // This helps prefix in its analyis of code which calls gtGetOp2()
4345
4346     assert((op2 != nullptr) || !RequiresNonNullOp2(gtOper));
4347
4348     return op2;
4349 }
4350
4351 inline GenTreePtr      GenTree::gtEffectiveVal(bool commaOnly)
4352 {
4353     switch (gtOper)
4354     {
4355     case GT_COMMA:
4356         return gtOp.gtOp2->gtEffectiveVal(commaOnly);
4357
4358     case GT_NOP:
4359         if (!commaOnly && gtOp.gtOp1 != NULL) 
4360             return gtOp.gtOp1->gtEffectiveVal();
4361         break;
4362
4363     default:
4364         break;
4365     }       
4366
4367     return this;
4368 }
4369
4370 inline GenTree*         GenTree::gtSkipReloadOrCopy()
4371 {
4372     // There can be only one reload or copy (we can't have a reload/copy of a reload/copy)
4373     if (gtOper == GT_RELOAD || gtOper == GT_COPY)
4374     {
4375         assert(gtGetOp1()->OperGet() != GT_RELOAD && gtGetOp1()->OperGet() != GT_COPY);
4376         return gtGetOp1();
4377     }
4378     return this;
4379 }
4380
4381 //-----------------------------------------------------------------------------------
4382 // IsMultiRegCall: whether a call node returning its value in more than one register
4383 //
4384 // Arguments:
4385 //     None
4386 //
4387 // Return Value:
4388 //     Returns true if this GenTree is a multi register returning call 
4389 inline bool  GenTree::IsMultiRegCall() const
4390 {
4391     if (this->IsCall())
4392     {
4393         // We cannot use AsCall() as it is not declared const
4394         const GenTreeCall* call = reinterpret_cast<const GenTreeCall *>(this);
4395         return call->HasMultiRegRetVal();
4396     }
4397
4398     return false;
4399 }
4400
4401 //-------------------------------------------------------------------------
4402 // IsCopyOrReload: whether this is a GT_COPY or GT_RELOAD node.
4403 //
4404 // Arguments:
4405 //     None
4406 //
4407 // Return Value:
4408 //     Returns true if this GenTree is a copy or reload node.
4409 inline bool GenTree::IsCopyOrReload() const
4410 {
4411     return (gtOper == GT_COPY || gtOper == GT_RELOAD);
4412 }
4413
4414 //-----------------------------------------------------------------------------------
4415 // IsCopyOrReloadOfMultiRegCall: whether this is a GT_COPY or GT_RELOAD of a multi-reg
4416 // call node.
4417 //
4418 // Arguments:
4419 //     None
4420 //
4421 // Return Value:
4422 //     Returns true if this GenTree is a copy or reload of multi-reg call node.
4423 inline bool GenTree::IsCopyOrReloadOfMultiRegCall() const
4424 {
4425     if (IsCopyOrReload())
4426     {
4427         GenTree* t = const_cast<GenTree*>(this);
4428         return t->gtGetOp1()->IsMultiRegCall();
4429     }
4430
4431     return false;
4432 }
4433
4434 inline bool GenTree::IsCnsIntOrI() const
4435 {
4436     return (gtOper == GT_CNS_INT);
4437 }
4438
4439 inline bool GenTree::IsIntegralConst() const
4440 {
4441 #ifdef _TARGET_64BIT_
4442     return IsCnsIntOrI();
4443 #else // !_TARGET_64BIT_
4444     return ((gtOper == GT_CNS_INT) || (gtOper == GT_CNS_LNG));
4445 #endif // !_TARGET_64BIT_
4446 }
4447
4448 inline bool GenTree::IsIntCnsFitsInI32()
4449 {
4450 #ifdef _TARGET_64BIT_
4451     return IsCnsIntOrI() && ((int)gtIntConCommon.IconValue() == gtIntConCommon.IconValue());
4452 #else // !_TARGET_64BIT_
4453     return IsCnsIntOrI();
4454 #endif // !_TARGET_64BIT_
4455 }
4456
4457 inline bool GenTree::IsCnsFltOrDbl() const
4458 {
4459     return OperGet() == GT_CNS_DBL;
4460 }
4461
4462 inline bool GenTree::IsCnsNonZeroFltOrDbl()
4463 {
4464     if (OperGet() == GT_CNS_DBL)
4465     {
4466         double constValue = gtDblCon.gtDconVal;
4467         return *(__int64*)&constValue != 0;
4468     }
4469
4470     return false;
4471 }
4472
4473 inline bool GenTree::IsHelperCall() { return OperGet() == GT_CALL && gtCall.gtCallType == CT_HELPER; }
4474
4475 inline var_types GenTree::CastFromType() { return this->gtCast.CastOp()->TypeGet(); }
4476 inline var_types& GenTree::CastToType()  { return this->gtCast.gtCastType; }
4477
4478 //-----------------------------------------------------------------------------------
4479 // HasGCPtr: determine whether this block op involves GC pointers
4480 //
4481 // Arguments:
4482 //     None
4483 //
4484 // Return Value:
4485 //    Returns true iff the object being copied contains one or more GC pointers.
4486 //
4487 // Notes:
4488 //    Of the block ops only GT_COPYOBJ is allowed to have GC pointers.
4489 // 
4490 inline bool
4491 GenTreeBlkOp::HasGCPtr()
4492 {
4493     if (gtFlags & GTF_BLK_HASGCPTR)
4494     {
4495         assert((gtOper == GT_COPYOBJ) && (AsCpObj()->gtGcPtrCount != 0));
4496         return true;
4497     }
4498     return false;
4499 }
4500
4501
4502 /*****************************************************************************/
4503
4504 #ifndef _HOST_64BIT_
4505 #include <poppack.h>
4506 #endif
4507
4508 /*****************************************************************************/
4509
4510 #if     SMALL_TREE_NODES
4511
4512 // In debug, on some platforms (e.g., when LATE_DISASM is defined), GenTreeIntCon is bigger than GenTreeLclFld.
4513 const
4514 size_t              TREE_NODE_SZ_SMALL = max(sizeof(GenTreeIntCon), sizeof(GenTreeLclFld));
4515
4516 #endif // SMALL_TREE_NODES
4517
4518 const
4519 size_t              TREE_NODE_SZ_LARGE = sizeof(GenTreeCall);
4520
4521 /*****************************************************************************
4522  * Types returned by GenTree::lvaLclVarRefs()
4523  */
4524
4525 enum varRefKinds
4526 {
4527     VR_INVARIANT  = 0x00,      // an invariant value
4528     VR_NONE       = 0x00,
4529     VR_IND_REF    = 0x01,      // an object reference
4530     VR_IND_SCL    = 0x02,      // a non-object reference
4531     VR_GLB_VAR    = 0x04,      // a global (clsVar)
4532 };
4533 // Add a temp define to avoid merge conflict.
4534 #define VR_IND_PTR VR_IND_REF
4535
4536 /*****************************************************************************/
4537 #endif  // !GENTREE_H
4538 /*****************************************************************************/
4539