Merge pull request #6094 from mikedn/x86-uncontained-long
[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     {
992         return OperIsBlkOp(OperGet());
993     }
994
995     bool            OperIsCopyBlkOp() const
996     {
997         return OperIsCopyBlkOp(OperGet());
998     }
999
1000     bool            OperIsPutArgStk() const
1001     {
1002         return gtOper == GT_PUTARG_STK;
1003     }
1004
1005     bool            OperIsAddrMode() const
1006     {
1007         return OperIsAddrMode(OperGet());
1008     }
1009
1010     bool            OperIsLocal() const
1011     {
1012         return OperIsLocal(OperGet());
1013     }
1014
1015     bool            OperIsLocalAddr() const
1016     {
1017         return OperIsLocalAddr(OperGet());
1018     }
1019
1020     bool            OperIsScalarLocal() const
1021     {
1022         return OperIsScalarLocal(OperGet());
1023     }
1024
1025     bool            OperIsNonPhiLocal() const
1026     {
1027         return OperIsNonPhiLocal(OperGet());
1028     }
1029
1030     bool            OperIsLocalStore() const
1031     {
1032         return OperIsLocalStore(OperGet());
1033     }
1034
1035     bool            OperIsLocalRead() const
1036     {
1037         return OperIsLocalRead(OperGet());
1038     }
1039
1040     bool            OperIsCompare()
1041     {
1042         return  (OperKind(gtOper) & GTK_RELOP  ) != 0;
1043     }
1044
1045     static
1046     bool            OperIsLogical(genTreeOps gtOper)
1047     {
1048         return  (OperKind(gtOper) & GTK_LOGOP  ) != 0;
1049     }
1050
1051     bool            OperIsLogical() const
1052     {
1053         return  (OperKind(gtOper) & GTK_LOGOP  ) != 0;
1054     }
1055
1056     static
1057     bool            OperIsShift(genTreeOps gtOper)
1058     {
1059         return (gtOper == GT_LSH) ||
1060                (gtOper == GT_RSH) ||
1061                (gtOper == GT_RSZ);
1062     }
1063
1064     bool            OperIsShift() const
1065     {
1066         return OperIsShift(OperGet());
1067     }
1068
1069     static
1070     bool            OperIsRotate(genTreeOps gtOper)
1071     {
1072         return (gtOper == GT_ROL) ||
1073                (gtOper == GT_ROR);
1074     }
1075
1076     bool            OperIsRotate() const
1077     {
1078         return OperIsRotate(OperGet());
1079     }
1080
1081     static
1082     bool            OperIsShiftOrRotate(genTreeOps gtOper)
1083     {
1084         return OperIsShift(gtOper) ||
1085                OperIsRotate(gtOper);
1086     }
1087
1088     bool            OperIsShiftOrRotate() const
1089     {
1090         return OperIsShiftOrRotate(OperGet());
1091     }
1092
1093     bool            OperIsArithmetic() const
1094     {
1095         genTreeOps op = OperGet();
1096         return     op==GT_ADD
1097                 || op==GT_SUB
1098                 || op==GT_MUL
1099                 || op==GT_DIV
1100                 || op==GT_MOD
1101
1102                 || op==GT_UDIV
1103                 || op==GT_UMOD
1104
1105                 || op==GT_OR
1106                 || op==GT_XOR
1107                 || op==GT_AND
1108
1109                 || OperIsShiftOrRotate(op);
1110     }
1111
1112 #if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
1113     static
1114     bool            OperIsHigh(genTreeOps gtOper)
1115     {
1116         switch (gtOper)
1117         {
1118         case GT_ADD_HI:
1119         case GT_SUB_HI:
1120         case GT_MUL_HI:
1121         case GT_DIV_HI:
1122         case GT_MOD_HI:
1123             return true;
1124         default:
1125             return false;
1126         }
1127     }
1128
1129     bool            OperIsHigh() const
1130     {
1131         return OperIsHigh(OperGet());
1132     }
1133 #endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
1134
1135     static
1136     bool            OperIsUnary(genTreeOps gtOper)
1137     {
1138         return  (OperKind(gtOper) & GTK_UNOP   ) != 0;
1139     }
1140
1141     bool            OperIsUnary() const
1142     {
1143         return   OperIsUnary(gtOper);
1144     }
1145
1146     static
1147     bool            OperIsBinary(genTreeOps gtOper)
1148     {
1149         return  (OperKind(gtOper) & GTK_BINOP  ) != 0;
1150     }
1151
1152     bool            OperIsBinary() const
1153     {
1154         return   OperIsBinary(gtOper);
1155     }
1156
1157     static
1158     bool            OperIsSimple(genTreeOps gtOper)
1159     {
1160         return (OperKind(gtOper) & GTK_SMPOP  ) != 0;
1161     }
1162
1163     static
1164     bool            OperIsSpecial(genTreeOps gtOper)
1165     {        
1166         return  ((OperKind(gtOper) & GTK_KINDMASK) == GTK_SPECIAL);
1167     }
1168
1169     bool            OperIsSimple() const
1170     {
1171         return  OperIsSimple(gtOper);
1172     }
1173
1174 #ifdef FEATURE_SIMD
1175     bool             isCommutativeSIMDIntrinsic();
1176 #else // !
1177     bool             isCommutativeSIMDIntrinsic()
1178     {
1179         return false;
1180     }
1181 #endif // FEATURE_SIMD
1182
1183     static
1184     bool            OperIsCommutative(genTreeOps gtOper)
1185     {
1186         return  (OperKind(gtOper) & GTK_COMMUTE) != 0;
1187     }
1188
1189     bool            OperIsCommutative()
1190     {
1191         return OperIsCommutative(gtOper) || (OperIsSIMD(gtOper) && isCommutativeSIMDIntrinsic());
1192     }
1193
1194     static
1195     bool            OperIsAssignment(genTreeOps gtOper)
1196     {
1197         return  (OperKind(gtOper) & GTK_ASGOP) != 0;
1198     }
1199
1200     bool            OperIsAssignment() const
1201     {
1202         return  OperIsAssignment(gtOper);
1203     }
1204
1205     static
1206     bool            OperIsIndir(genTreeOps gtOper)
1207     {
1208         return  gtOper == GT_IND || gtOper == GT_STOREIND || gtOper == GT_NULLCHECK;
1209     }
1210
1211     bool            OperIsIndir() const
1212     {
1213         return  OperIsIndir(gtOper);
1214     }
1215
1216     static 
1217     bool            OperIsImplicitIndir(genTreeOps gtOper)
1218     {
1219         switch (gtOper)
1220         {
1221         case GT_LOCKADD:
1222         case GT_XADD:
1223         case GT_CMPXCHG:
1224         case GT_COPYBLK:
1225         case GT_COPYOBJ:
1226         case GT_INITBLK:
1227         case GT_OBJ:
1228         case GT_BOX:
1229         case GT_ARR_INDEX:
1230         case GT_ARR_ELEM:
1231         case GT_ARR_OFFSET:
1232             return true;
1233         default:
1234             return false;
1235         }
1236     }
1237
1238     bool            OperIsImplicitIndir() const
1239     {
1240         return  OperIsImplicitIndir(gtOper);
1241     }
1242
1243     bool            OperIsStore() const
1244     {
1245         return OperIsStore(gtOper);
1246     }
1247
1248     static
1249     bool            OperIsStore(genTreeOps gtOper)
1250     {
1251         return (gtOper == GT_STOREIND
1252                 || gtOper == GT_STORE_LCL_VAR
1253                 || gtOper == GT_STORE_LCL_FLD
1254                 || gtOper == GT_STORE_CLS_VAR);
1255     }
1256
1257     static
1258     bool            OperIsAtomicOp(genTreeOps gtOper)
1259     {
1260         return  (gtOper == GT_XADD 
1261                  || gtOper == GT_XCHG  
1262                  || gtOper == GT_LOCKADD 
1263                  || gtOper == GT_CMPXCHG);
1264     }
1265
1266     bool            OperIsAtomicOp()
1267     {
1268         return  OperIsAtomicOp(gtOper);
1269     }
1270
1271     // This is basically here for cleaner FEATURE_SIMD #ifdefs.
1272     static
1273     bool            OperIsSIMD(genTreeOps gtOper)
1274     {
1275 #ifdef FEATURE_SIMD
1276         return gtOper == GT_SIMD;
1277 #else // !FEATURE_SIMD
1278         return false;
1279 #endif // !FEATURE_SIMD
1280     }
1281
1282     bool            OperIsSIMD()
1283     {
1284         return OperIsSIMD(gtOper);
1285     }
1286
1287     // Requires that "op" is an op= operator.  Returns
1288     // the corresponding "op".
1289     static
1290     genTreeOps      OpAsgToOper(genTreeOps op);
1291
1292 #ifdef DEBUG
1293     bool            NullOp1Legal() const
1294     {
1295         assert(OperIsSimple(gtOper));
1296         switch (gtOper)
1297         {
1298         case GT_PHI: case GT_LEA: case GT_RETFILT: case GT_NOP:
1299             return true;
1300         case GT_RETURN:
1301             return gtType == TYP_VOID;
1302         default:
1303             return false;
1304         }
1305     }
1306
1307     bool            NullOp2Legal() const
1308     {
1309         assert(OperIsSimple(gtOper));
1310         if (!OperIsBinary(gtOper))
1311         {
1312             return true;
1313         }
1314         switch (gtOper)
1315         {
1316         case GT_LIST:
1317         case GT_INTRINSIC:
1318         case GT_LEA:
1319         case GT_STOREIND:
1320         case GT_INITBLK:
1321         case GT_COPYBLK:
1322         case GT_COPYOBJ:
1323 #ifdef FEATURE_SIMD
1324         case GT_SIMD:
1325 #endif // !FEATURE_SIMD
1326             return true;
1327         default:
1328             return false;
1329         }
1330     }
1331
1332     static
1333     inline bool RequiresNonNullOp2(genTreeOps oper);
1334     bool IsListForMultiRegArg();
1335 #endif // DEBUG
1336
1337     inline bool IsFPZero();
1338     inline bool IsIntegralConst(ssize_t constVal);
1339
1340     inline bool IsBoxedValue();
1341
1342     bool IsList() const
1343     {
1344         return gtOper == GT_LIST;
1345     }
1346
1347     inline GenTreePtr MoveNext();
1348
1349     inline GenTreePtr Current();
1350
1351     inline GenTreePtr *pCurrent();
1352
1353     inline GenTreePtr gtGetOp1();
1354
1355     inline GenTreePtr gtGetOp2();
1356
1357     // Given a tree node, if this is a child of that node, return the pointer to the child node so that it
1358     // can be modified; otherwise, return null.
1359     GenTreePtr*       gtGetChildPointer(GenTreePtr parent);
1360
1361     // Get the parent of this node, and optionally capture the pointer to the child so that it can be modified.
1362     GenTreePtr        gtGetParent(GenTreePtr** parentChildPtrPtr);
1363
1364     inline GenTreePtr gtEffectiveVal(bool commaOnly = false);
1365
1366     // Return the child of this node if it is a GT_RELOAD or GT_COPY; otherwise simply return the node itself
1367     inline GenTree*   gtSkipReloadOrCopy();
1368
1369     // Returns true if it is a call node returning its value in more than one register
1370     inline bool     IsMultiRegCall() const;
1371
1372     // Returns true if it is a GT_COPY or GT_RELOAD node
1373     inline bool     IsCopyOrReload() const;
1374
1375     // Returns true if it is a GT_COPY or GT_RELOAD of a multi-reg call node
1376     inline bool     IsCopyOrReloadOfMultiRegCall() const;
1377
1378     bool            OperMayThrow();
1379
1380     unsigned        GetScaleIndexMul();
1381     unsigned        GetScaleIndexShf();
1382     unsigned        GetScaledIndex();
1383
1384     // Returns true if "addr" is a GT_ADD node, at least one of whose arguments is an integer
1385     // (<= 32 bit) constant.  If it returns true, it sets "*offset" to (one of the) constant value(s), and
1386     // "*addr" to the other argument.
1387     bool            IsAddWithI32Const(GenTreePtr* addr, int* offset);
1388
1389     // Insert 'node' after this node in execution order.
1390     void            InsertAfterSelf(GenTree* node, GenTreeStmt* stmt = nullptr);
1391
1392 public:
1393
1394 #if SMALL_TREE_NODES
1395     static
1396     unsigned char   s_gtNodeSizes[];
1397 #endif
1398
1399     static
1400     void            InitNodeSize();
1401
1402     size_t          GetNodeSize() const;
1403
1404     bool            IsNodeProperlySized() const;
1405
1406     void            CopyFrom(const GenTree* src, Compiler* comp);
1407
1408     static
1409     genTreeOps      ReverseRelop(genTreeOps relop);
1410
1411     static
1412     genTreeOps      SwapRelop(genTreeOps relop);
1413
1414     //---------------------------------------------------------------------
1415
1416     static
1417     bool            Compare(GenTreePtr op1, GenTreePtr op2, bool swapOK = false);
1418
1419     //---------------------------------------------------------------------
1420     #ifdef DEBUG
1421     //---------------------------------------------------------------------
1422
1423     static
1424     const   char *  NodeName(genTreeOps op);
1425
1426     static
1427     const   char *  OpName(genTreeOps op);
1428
1429     //---------------------------------------------------------------------
1430     #endif
1431     //---------------------------------------------------------------------
1432
1433     bool                        IsNothingNode       () const;
1434     void                        gtBashToNOP         ();
1435
1436     // Value number update action enumeration
1437     enum ValueNumberUpdate
1438     {
1439         CLEAR_VN,       // Clear value number
1440         PRESERVE_VN     // Preserve value number
1441     };
1442
1443     void                        SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate = CLEAR_VN);  // set gtOper
1444     void                        SetOperResetFlags   (genTreeOps oper);  // set gtOper and reset flags
1445
1446     void                        ChangeOperConst     (genTreeOps oper);  // ChangeOper(constOper)
1447     // set gtOper and only keep GTF_COMMON_MASK flags
1448     void                        ChangeOper(genTreeOps oper, ValueNumberUpdate vnUpdate = CLEAR_VN);
1449     void                        ChangeOperUnchecked (genTreeOps oper);
1450
1451     bool IsLocal() const
1452     {
1453         return OperIsLocal(OperGet());
1454     }
1455
1456     // Returns "true" iff 'this' is a GT_LCL_FLD or GT_STORE_LCL_FLD on which the type
1457     // is not the same size as the type of the GT_LCL_VAR.
1458     bool IsPartialLclFld(Compiler* comp);
1459
1460     // Returns "true" iff "this" defines a local variable.  Requires "comp" to be the 
1461     // current compilation.  If returns "true", sets "*pLclVarTree" to the
1462     // tree for the local that is defined, and, if "pIsEntire" is non-null, sets "*pIsEntire" to
1463     // true or false, depending on whether the assignment writes to the entirety of the local
1464     // variable, or just a portion of it.
1465     bool DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire = nullptr);
1466
1467     // Returns true if "this" represents the address of a local, or a field of a local.  If returns true, sets
1468     // "*pLclVarTree" to the node indicating the local variable.  If the address is that of a field of this node,
1469     // sets "*pFldSeq" to the field sequence representing that field, else null.
1470     bool IsLocalAddrExpr(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, FieldSeqNode** pFldSeq);
1471
1472     // Simpler variant of the above which just returns the local node if this is an expression that 
1473     // yields an address into a local
1474     GenTreeLclVarCommon* IsLocalAddrExpr();
1475
1476     // Determine whether this is an assignment tree of the form X = X (op) Y,
1477     // where Y is an arbitrary tree, and X is a lclVar.
1478     unsigned             IsLclVarUpdateTree(GenTree** otherTree, genTreeOps *updateOper);
1479
1480     // If returns "true", "this" may represent the address of a static or instance field
1481     // (or a field of such a field, in the case of an object field of type struct).  
1482     // If returns "true", then either "*pObj" is set to the object reference, 
1483     // or "*pStatic" is set to the baseAddr or offset to be added to the "*pFldSeq" 
1484     // Only one of "*pObj" or "*pStatic" will be set, the other one will be null.
1485     // The boolean return value only indicates that "this" *may* be a field address 
1486     // -- the field sequence must also be checked.  
1487     // If it is a field address, the field sequence will be a sequence of length >= 1, 
1488     // starting with an instance or static field, and optionally continuing with struct fields.
1489     bool IsFieldAddr(Compiler* comp, GenTreePtr* pObj, GenTreePtr* pStatic, FieldSeqNode** pFldSeq);
1490
1491     // Requires "this" to be the address of an array (the child of a GT_IND labeled with GTF_IND_ARR_INDEX).
1492     // Sets "pArr" to the node representing the array (either an array object pointer, or perhaps a byref to the some element).
1493     // Sets "*pArrayType" to the class handle for the array type.
1494     // Sets "*inxVN" to the value number inferred for the array index.
1495     // Sets "*pFldSeq" to the sequence, if any, of struct fields used to index into the array element.
1496     void ParseArrayAddress(Compiler* comp, 
1497                            struct ArrayInfo* arrayInfo, 
1498                            GenTreePtr* pArr, 
1499                            ValueNum* pInxVN,
1500                            FieldSeqNode** pFldSeq);
1501
1502     // Helper method for the above.
1503     void ParseArrayAddressWork(Compiler* comp, ssize_t inputMul, GenTreePtr* pArr, ValueNum* pInxVN, ssize_t* pOffset, FieldSeqNode** pFldSeq);
1504
1505     // Requires "this" to be a GT_IND.  Requires the outermost caller to set "*pFldSeq" to nullptr.
1506     // Returns true if it is an array index expression, or access to a (sequence of) struct field(s)
1507     // within a struct array element.  If it returns true, sets *arrayInfo to the array information, and sets *pFldSeq to the sequence
1508     // of struct field accesses.
1509     bool ParseArrayElemForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq);
1510
1511     // Requires "this" to be the address of a (possible) array element (or struct field within that).
1512     // If it is, sets "*arrayInfo" to the array access info, "*pFldSeq" to the sequence of struct fields
1513     // accessed within the array element, and returns true.  If not, returns "false".
1514     bool ParseArrayElemAddrForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq);
1515
1516     // Requires "this" to be an int expression.  If it is a sequence of one or more integer constants added together,
1517     // returns true and sets "*pFldSeq" to the sequence of fields with which those constants are annotated.
1518     bool ParseOffsetForm(Compiler* comp, FieldSeqNode** pFldSeq);
1519
1520     // 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
1521     // of the index.
1522     void LabelIndex(Compiler* comp, bool isConst = true);
1523
1524     // Assumes that "this" occurs in a context where it is being dereferenced as the LHS of an assignment-like
1525     // statement (assignment, initblk, or copyblk).  The "width" should be the number of bytes copied by the
1526     // operation.  Returns "true" if "this" is an address of (or within)
1527     // a local variable; sets "*pLclVarTree" to that local variable instance; and, if "pIsEntire" is non-null,
1528     // sets "*pIsEntire" to true if this assignment writes the full width of the local.
1529     bool DefinesLocalAddr(Compiler* comp, unsigned width, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire);
1530
1531     bool                        IsRegVar            () const
1532     {
1533         return OperGet() == GT_REG_VAR?true:false;
1534     }
1535     bool                        InReg() const
1536     {
1537         return (gtFlags & GTF_REG_VAL)?true:false;       
1538     }
1539     void                        SetInReg()
1540     {
1541         gtFlags |= GTF_REG_VAL;
1542     }
1543
1544     regNumber                   GetReg() const
1545     {
1546         return InReg() ? gtRegNum : REG_NA;
1547     }
1548     bool                        IsRegVarDeath       () const
1549     {
1550         assert(OperGet() == GT_REG_VAR);
1551         return (gtFlags & GTF_VAR_DEATH)?true:false;       
1552     }
1553     bool                        IsRegVarBirth       () const
1554     {
1555         assert(OperGet() == GT_REG_VAR);
1556         return (gtFlags & GTF_REG_BIRTH)?true:false;       
1557     }
1558     bool                        IsReverseOp() const
1559     {
1560         return (gtFlags & GTF_REVERSE_OPS)?true:false;
1561     }
1562
1563     inline bool                 IsCnsIntOrI         () const;
1564
1565     inline bool                 IsIntegralConst     () const;
1566
1567     inline bool                 IsIntCnsFitsInI32   ();
1568
1569     inline bool                 IsCnsFltOrDbl() const;
1570
1571     inline bool                 IsCnsNonZeroFltOrDbl();    
1572
1573     bool                        IsIconHandle        () const
1574     {
1575         assert(gtOper == GT_CNS_INT);
1576         return (gtFlags & GTF_ICON_HDL_MASK) ? true : false;
1577     }
1578
1579     bool                        IsIconHandle        (unsigned handleType) const
1580     {
1581         assert(gtOper == GT_CNS_INT);
1582         assert((handleType & GTF_ICON_HDL_MASK) != 0);      // check that handleType is one of the valid GTF_ICON_* values
1583         assert((handleType & ~GTF_ICON_HDL_MASK) == 0);
1584         return (gtFlags & GTF_ICON_HDL_MASK) == handleType;
1585     }
1586
1587     // Return just the part of the flags corresponding to the GTF_ICON_*_HDL flag. For example,
1588     // GTF_ICON_SCOPE_HDL. The tree node must be a const int, but it might not be a handle, in which
1589     // case we'll return zero.
1590     unsigned                    GetIconHandleFlag   () const
1591     {
1592         assert(gtOper == GT_CNS_INT);
1593         return (gtFlags & GTF_ICON_HDL_MASK);
1594     }
1595
1596     // Mark this node as no longer being a handle; clear its GTF_ICON_*_HDL bits.
1597     void                        ClearIconHandleMask()
1598     {
1599         assert(gtOper == GT_CNS_INT);
1600         gtFlags &= ~GTF_ICON_HDL_MASK;
1601     }
1602
1603     // Return true if the two GT_CNS_INT trees have the same handle flag (GTF_ICON_*_HDL).
1604     static bool                 SameIconHandleFlag(GenTree* t1, GenTree* t2)
1605     {
1606         return t1->GetIconHandleFlag() == t2->GetIconHandleFlag();
1607     }
1608
1609     bool                        IsArgPlaceHolderNode() const { return OperGet() == GT_ARGPLACE; }
1610     bool                        IsCall              () const { return OperGet() == GT_CALL; }
1611     bool                        IsStatement         () const { return OperGet() == GT_STMT; }
1612     inline bool                 IsHelperCall        ();
1613
1614     bool                        IsVarAddr           () const;
1615     bool                        gtOverflow          () const;
1616     bool                        gtOverflowEx        () const;
1617     bool                        gtSetFlags          () const;
1618     bool                        gtRequestSetFlags   ();
1619 #ifdef DEBUG
1620     bool                        gtIsValid64RsltMul  ();
1621     static int                  gtDispFlags         (unsigned flags, unsigned debugFlags);
1622 #endif
1623
1624     // cast operations 
1625     inline var_types            CastFromType();
1626     inline var_types&           CastToType();
1627
1628     // Returns true if this gentree node is marked by lowering to indicate
1629     // that codegen can still generate code even if it wasn't allocated a 
1630     // register.
1631     bool IsRegOptional() const;   
1632
1633     // Returns "true" iff "*this" is an assignment (GT_ASG) tree that defines an SSA name (lcl = phi(...));
1634     bool IsPhiDefn();
1635
1636     // Returns "true" iff "*this" is a statement containing an assignment that defines an SSA name (lcl = phi(...));
1637     bool IsPhiDefnStmt();
1638
1639     // Can't use an assignment operator, because we need the extra "comp" argument
1640     // (to provide the allocator necessary for the VarSet assignment).
1641     // TODO-Cleanup: Not really needed now, w/o liveset on tree nodes
1642     void CopyTo(class Compiler* comp, const GenTree& gt);
1643
1644     // Like the above, excepts assumes copying from small node to small node.
1645     // (Following the code it replaces, it does *not* copy the GenTree fields,
1646     // which CopyTo does.)
1647     void CopyToSmall(const GenTree& gt);
1648
1649     // Because of the fact that we hid the assignment operator of "BitSet" (in DEBUG),
1650     // we can't synthesize an assignment operator.
1651     // TODO-Cleanup: Could change this w/o liveset on tree nodes
1652     // (This is also necessary for the VTable trick.)
1653     GenTree() {}
1654
1655     // Returns the number of children of the current node.
1656     unsigned NumChildren();
1657
1658     // Requires "childNum < NumChildren()".  Returns the "n"th child of "this."
1659     GenTreePtr GetChild(unsigned childNum);
1660
1661     // The maximum possible # of children of any node.
1662     static const int MAX_CHILDREN = 6;
1663
1664     bool IsReuseRegVal() const
1665     {
1666         // This can be extended to non-constant nodes, but not to local or indir nodes.
1667         if(OperIsConst() && ((gtFlags & GTF_REUSE_REG_VAL) != 0))
1668         {
1669             return true;
1670         }
1671         return false;
1672     }
1673     void SetReuseRegVal()
1674     {
1675         assert(OperIsConst());
1676         gtFlags |= GTF_REUSE_REG_VAL;
1677     }
1678     void ResetReuseRegVal()
1679     {
1680         assert(OperIsConst());
1681         gtFlags &= ~GTF_REUSE_REG_VAL;
1682     }
1683
1684 #ifdef DEBUG
1685   private:
1686     GenTree& operator=(const GenTree& gt) {
1687         assert(!"Don't copy");
1688         return *this;
1689     }
1690 #endif // DEBUG
1691
1692 #if DEBUGGABLE_GENTREE
1693     // In DEBUG builds, add a dummy virtual method, to give the debugger run-time type information.
1694     virtual void DummyVirt() {}
1695
1696     typedef void* VtablePtr;
1697
1698     VtablePtr GetVtableForOper(genTreeOps oper);
1699     void SetVtableForOper(genTreeOps oper);
1700
1701     static VtablePtr s_vtablesForOpers[GT_COUNT];
1702     static VtablePtr s_vtableForOp;
1703 #endif // DEBUGGABLE_GENTREE
1704
1705   public:
1706     inline void* operator new(size_t sz, class Compiler*, genTreeOps oper);
1707
1708     inline GenTree(genTreeOps oper, var_types type
1709                    DEBUGARG(bool largeNode = false));
1710 };
1711
1712
1713 /*****************************************************************************/
1714 // In the current design, we never instantiate GenTreeUnOp: it exists only to be
1715 // used as a base class.  For unary operators, we instantiate GenTreeOp, with a NULL second
1716 // argument.  We check that this is true dynamically.  We could tighten this and get static
1717 // checking, but that would entail accessing the first child of a unary operator via something
1718 // like gtUnOp.gtOp1 instead of gtOp.gtOp1.
1719 struct GenTreeUnOp: public GenTree
1720 {
1721     GenTreePtr      gtOp1;
1722
1723 protected:
1724     GenTreeUnOp(genTreeOps oper, var_types type 
1725                 DEBUGARG(bool largeNode = false)) : 
1726         GenTree(oper, type 
1727                 DEBUGARG(largeNode)),
1728         gtOp1(nullptr)
1729         {}
1730
1731     GenTreeUnOp(genTreeOps oper, var_types type, GenTreePtr op1 
1732                 DEBUGARG(bool largeNode = false)) : 
1733         GenTree(oper, type 
1734                 DEBUGARG(largeNode)), 
1735         gtOp1(op1)
1736         {
1737             assert(op1 != nullptr || NullOp1Legal());
1738             if (op1 != nullptr)  // Propagate effects flags from child.
1739                 gtFlags |= op1->gtFlags & GTF_ALL_EFFECT;
1740         }
1741
1742 #if DEBUGGABLE_GENTREE
1743     GenTreeUnOp() : GenTree(), gtOp1(nullptr) {}
1744 #endif
1745 };
1746
1747 struct GenTreeOp: public GenTreeUnOp
1748 {
1749     GenTreePtr      gtOp2;
1750
1751     GenTreeOp(genTreeOps oper, var_types type, GenTreePtr op1, GenTreePtr op2 
1752               DEBUGARG(bool largeNode = false)) : 
1753         GenTreeUnOp(oper, type, op1 
1754                     DEBUGARG(largeNode)), 
1755         gtOp2(op2) 
1756         {
1757             // comparisons are always integral types
1758             assert(!GenTree::OperIsCompare(oper) || varTypeIsIntegral(type));
1759             // Binary operators, with a few exceptions, require a non-nullptr
1760             // second argument.
1761             assert(op2 != nullptr || NullOp2Legal());
1762             // Unary operators, on the other hand, require a null second argument.
1763             assert(!OperIsUnary(oper) || op2 == nullptr);
1764             // Propagate effects flags from child.  (UnOp handled this for first child.)
1765             if (op2 != nullptr)
1766             {
1767                 gtFlags |= op2->gtFlags & GTF_ALL_EFFECT;
1768             }
1769         }
1770
1771     // A small set of types are unary operators with optional arguments.  We use
1772     // this constructor to build those.
1773     GenTreeOp(genTreeOps oper, var_types type 
1774               DEBUGARG(bool largeNode = false)) : 
1775         GenTreeUnOp(oper, type 
1776                     DEBUGARG(largeNode)),
1777         gtOp2(nullptr)
1778         {
1779             // Unary operators with optional arguments:
1780             assert(oper == GT_NOP     ||
1781                    oper == GT_RETURN  ||
1782                    oper == GT_RETFILT ||
1783                    OperIsBlkOp(oper));
1784         }
1785
1786 #if DEBUGGABLE_GENTREE
1787     GenTreeOp() : GenTreeUnOp(), gtOp2(nullptr) {}
1788 #endif
1789 };
1790
1791
1792 struct GenTreeVal: public GenTree
1793 {
1794     size_t          gtVal1;
1795
1796     GenTreeVal(genTreeOps oper, var_types type, ssize_t val) : 
1797         GenTree(oper, type),
1798         gtVal1(val)
1799         {}
1800 #if DEBUGGABLE_GENTREE
1801     GenTreeVal() : GenTree() {}
1802 #endif
1803 };
1804
1805 struct GenTreeIntConCommon: public GenTree
1806 {
1807     inline INT64   LngValue();
1808     inline void    SetLngValue(INT64 val);
1809     inline ssize_t IconValue();
1810     inline void SetIconValue(ssize_t val);
1811     
1812     GenTreeIntConCommon(genTreeOps oper, var_types type
1813                         DEBUGARG(bool largeNode = false)) : 
1814         GenTree(oper, type 
1815                 DEBUGARG(largeNode))
1816         {}
1817
1818         bool FitsInI32() 
1819         {  
1820             return FitsInI32(IconValue());
1821         }
1822
1823         static bool FitsInI32(ssize_t val)
1824         {
1825 #ifdef _TARGET_64BIT_
1826             return (int)val == val;
1827 #else
1828             return true;
1829 #endif
1830         }
1831
1832         bool ImmedValNeedsReloc(Compiler* comp);
1833         bool GenTreeIntConCommon::ImmedValCanBeFolded(Compiler* comp, genTreeOps op);
1834
1835 #ifdef _TARGET_XARCH_
1836         bool FitsInAddrBase(Compiler* comp);
1837         bool AddrNeedsReloc(Compiler* comp);
1838 #endif
1839
1840 #if DEBUGGABLE_GENTREE
1841     GenTreeIntConCommon() : GenTree() {}
1842 #endif
1843 };
1844
1845 // node representing a read from a physical register
1846 struct GenTreePhysReg: public GenTree
1847 {
1848     // physregs need a field beyond gtRegNum because 
1849     // gtRegNum indicates the destination (and can be changed)
1850     // whereas reg indicates the source
1851     regNumber gtSrcReg;
1852     GenTreePhysReg(regNumber r, var_types type=TYP_I_IMPL) : 
1853         GenTree(GT_PHYSREG, type), gtSrcReg(r)
1854     {
1855     }
1856 #if DEBUGGABLE_GENTREE
1857     GenTreePhysReg() : GenTree() {}
1858 #endif
1859 };
1860
1861 #ifndef LEGACY_BACKEND
1862 // gtJumpTable - Switch Jump Table
1863 //
1864 // This node stores a DWORD constant that represents the
1865 // absolute address of a jump table for switches.  The code 
1866 // generator uses this table to code the destination for every case
1867 // in an array of addresses which starting position is stored in
1868 // this constant.
1869 struct GenTreeJumpTable : public GenTreeIntConCommon
1870 {
1871     ssize_t        gtJumpTableAddr;
1872
1873     GenTreeJumpTable(var_types type
1874                   DEBUGARG(bool largeNode = false)) : 
1875         GenTreeIntConCommon(GT_JMPTABLE, type 
1876                             DEBUGARG(largeNode)) 
1877         {}
1878 #if DEBUGGABLE_GENTREE
1879     GenTreeJumpTable() : GenTreeIntConCommon() {}
1880 #endif // DEBUG
1881 };
1882 #endif // !LEGACY_BACKEND
1883
1884 /* gtIntCon -- integer constant (GT_CNS_INT) */
1885 struct GenTreeIntCon: public GenTreeIntConCommon
1886 {
1887     /* 
1888      * This is the GT_CNS_INT struct definition.
1889      * It's used to hold for both int constants and pointer handle constants.
1890      * For the 64-bit targets we will only use GT_CNS_INT as it used to represent all the possible sizes
1891      * 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.
1892      * In the future when we retarget the JIT for x86 we should consider eliminating GT_CNS_LNG
1893      */
1894     ssize_t         gtIconVal;   // Must overlap and have the same offset with the gtIconVal field in GenTreeLngCon below.
1895     
1896     /* The InitializeArray intrinsic needs to go back to the newarray statement
1897        to find the class handle of the array so that we can get its size.  However,
1898        in ngen mode, the handle in that statement does not correspond to the compile
1899        time handle (rather it lets you get a handle at run-time).  In that case, we also
1900        need to store a compile time handle, which goes in this gtCompileTimeHandle field.
1901     */
1902     ssize_t         gtCompileTimeHandle;
1903
1904     // TODO-Cleanup: It's not clear what characterizes the cases where the field
1905     // above is used.  It may be that its uses and those of the "gtFieldSeq" field below
1906     // are mutually exclusive, and they could be put in a union.  Or else we should separate
1907     // this type into three subtypes.
1908
1909     // If this constant represents the offset of one or more fields, "gtFieldSeq" represents that
1910     // sequence of fields.
1911     FieldSeqNode*   gtFieldSeq;
1912
1913 #if defined (LATE_DISASM)
1914
1915     /*  If the constant was morphed from some other node,
1916         these fields enable us to get back to what the node
1917         originally represented. See use of gtNewIconHandleNode()
1918      */
1919
1920     union
1921     {
1922         /* Template struct - The significant field of the other
1923          * structs should overlap exactly with this struct
1924          */
1925
1926         struct
1927         {
1928             unsigned        gtIconHdl1;
1929             void *          gtIconHdl2;
1930         }
1931                             gtIconHdl;
1932
1933         /* GT_FIELD, etc */
1934
1935         struct
1936         {
1937             unsigned                gtIconCPX;
1938             CORINFO_CLASS_HANDLE    gtIconCls;
1939         }
1940                                     gtIconFld;
1941     };
1942 #endif
1943
1944     GenTreeIntCon(var_types type, ssize_t value
1945                   DEBUGARG(bool largeNode = false)) : 
1946         GenTreeIntConCommon(GT_CNS_INT, type 
1947                             DEBUGARG(largeNode)),
1948         gtIconVal(value),
1949         gtCompileTimeHandle(0),
1950         gtFieldSeq(FieldSeqStore::NotAField())
1951         {}
1952
1953     GenTreeIntCon(var_types type, ssize_t value, FieldSeqNode* fields
1954                   DEBUGARG(bool largeNode = false)) : 
1955         GenTreeIntConCommon(GT_CNS_INT, type 
1956                             DEBUGARG(largeNode)),
1957         gtIconVal(value),
1958         gtCompileTimeHandle(0),
1959         gtFieldSeq(fields)
1960         {
1961             assert(fields != NULL);
1962         }
1963
1964 #ifdef _TARGET_64BIT_
1965     void TruncateOrSignExtend32()
1966     {        
1967         if (gtFlags & GTF_UNSIGNED)
1968         {
1969             gtIconVal = UINT32(gtIconVal);
1970         }
1971         else
1972         {
1973             gtIconVal = INT32(gtIconVal);
1974         }
1975     }
1976 #endif // _TARGET_64BIT_
1977
1978 #if DEBUGGABLE_GENTREE
1979     GenTreeIntCon() : GenTreeIntConCommon() {}
1980 #endif
1981 };
1982
1983
1984 /* gtLngCon -- long    constant (GT_CNS_LNG) */
1985
1986 struct GenTreeLngCon: public GenTreeIntConCommon
1987 {
1988     INT64 gtLconVal;   // Must overlap and have the same offset with the gtIconVal field in GenTreeIntCon above.
1989     INT32 LoVal()
1990     {
1991         return (INT32)(gtLconVal & 0xffffffff);
1992     }
1993
1994     INT32 HiVal()
1995     {
1996         return (INT32)(gtLconVal >> 32);;
1997     }
1998
1999     GenTreeLngCon(INT64 val) : 
2000         GenTreeIntConCommon(GT_CNS_NATIVELONG, TYP_LONG)
2001         { SetLngValue(val); }
2002 #if DEBUGGABLE_GENTREE
2003     GenTreeLngCon() : GenTreeIntConCommon() {}
2004 #endif
2005 };
2006
2007
2008 inline INT64 GenTreeIntConCommon::LngValue()
2009 {
2010 #ifndef _TARGET_64BIT_
2011     assert(gtOper == GT_CNS_LNG);
2012     return AsLngCon()->gtLconVal;
2013 #else
2014     return IconValue();
2015 #endif
2016 }
2017
2018 inline void GenTreeIntConCommon::SetLngValue(INT64 val)
2019 {
2020 #ifndef _TARGET_64BIT_
2021     assert(gtOper == GT_CNS_LNG);
2022     AsLngCon()->gtLconVal = val;
2023 #else
2024     // Compile time asserts that these two fields overlap and have the same offsets:  gtIconVal and gtLconVal
2025     C_ASSERT(offsetof(GenTreeLngCon, gtLconVal) == offsetof(GenTreeIntCon, gtIconVal));
2026     C_ASSERT(sizeof(AsLngCon()->gtLconVal) == sizeof(AsIntCon()->gtIconVal));
2027
2028     SetIconValue(ssize_t(val));
2029 #endif
2030 }
2031
2032 inline ssize_t GenTreeIntConCommon::IconValue()
2033 {
2034     assert(gtOper == GT_CNS_INT);   //  We should never see a GT_CNS_LNG for a 64-bit target!
2035     return AsIntCon()->gtIconVal;
2036 }
2037
2038 inline void GenTreeIntConCommon::SetIconValue(ssize_t val)
2039 {
2040     assert(gtOper == GT_CNS_INT);   //  We should never see a GT_CNS_LNG for a 64-bit target!
2041     AsIntCon()->gtIconVal = val;
2042 }
2043
2044 /* gtDblCon -- double  constant (GT_CNS_DBL) */
2045
2046 struct GenTreeDblCon: public GenTree
2047 {
2048     double          gtDconVal;
2049
2050     bool            isBitwiseEqual(GenTreeDblCon* other)
2051     {
2052         unsigned __int64 bits = *(unsigned __int64 *)(&gtDconVal);
2053         unsigned __int64 otherBits = *(unsigned __int64 *)(&(other->gtDconVal));
2054         return (bits == otherBits);
2055     }
2056
2057     GenTreeDblCon(double val) : 
2058         GenTree(GT_CNS_DBL, TYP_DOUBLE),
2059         gtDconVal(val)
2060         {}
2061 #if DEBUGGABLE_GENTREE
2062     GenTreeDblCon() : GenTree() {}
2063 #endif
2064 };
2065
2066
2067 /* gtStrCon -- string  constant (GT_CNS_STR) */
2068
2069 struct GenTreeStrCon: public GenTree
2070 {
2071     unsigned              gtSconCPX;
2072     CORINFO_MODULE_HANDLE gtScpHnd;
2073
2074     // Because this node can come from an inlined method we need to
2075     // have the scope handle, since it will become a helper call.
2076     GenTreeStrCon(unsigned sconCPX, CORINFO_MODULE_HANDLE mod
2077                   DEBUGARG(bool largeNode = false)) : 
2078         GenTree(GT_CNS_STR, TYP_REF 
2079                 DEBUGARG(largeNode)),
2080         gtSconCPX(sconCPX), gtScpHnd(mod)
2081         {}
2082 #if DEBUGGABLE_GENTREE
2083     GenTreeStrCon() : GenTree() {}
2084 #endif
2085 };
2086
2087 // Common supertype of LCL_VAR, LCL_FLD, REG_VAR, PHI_ARG
2088 // This inherits from UnOp because lclvar stores are Unops
2089 struct GenTreeLclVarCommon: public GenTreeUnOp
2090 {
2091 private:
2092     unsigned        _gtLclNum;      // The local number. An index into the Compiler::lvaTable array.
2093     unsigned        _gtSsaNum;      // The SSA number.
2094
2095 public:
2096     GenTreeLclVarCommon(genTreeOps oper, var_types type, unsigned lclNum
2097                         DEBUGARG(bool largeNode = false)) : 
2098         GenTreeUnOp(oper, type 
2099                 DEBUGARG(largeNode))
2100     {
2101         SetLclNum(lclNum);
2102     }
2103
2104     unsigned GetLclNum() const
2105     {
2106         return _gtLclNum;
2107     }
2108     __declspec(property(get=GetLclNum))  unsigned  gtLclNum;
2109
2110     void SetLclNum(unsigned lclNum)
2111     {
2112         _gtLclNum = lclNum;
2113         _gtSsaNum = SsaConfig::RESERVED_SSA_NUM;
2114     }
2115
2116     unsigned GetSsaNum() const
2117     {
2118         return _gtSsaNum;
2119     }
2120     __declspec(property(get=GetSsaNum))  unsigned  gtSsaNum;
2121
2122     void SetSsaNum(unsigned ssaNum)
2123     {
2124         _gtSsaNum = ssaNum;
2125     }
2126
2127     bool HasSsaName()
2128     {
2129         return (gtSsaNum != SsaConfig::RESERVED_SSA_NUM);
2130     }
2131
2132 #if DEBUGGABLE_GENTREE
2133     GenTreeLclVarCommon() : GenTreeUnOp() {}
2134 #endif
2135 };
2136
2137 // gtLclVar -- load/store/addr of local variable 
2138
2139 struct GenTreeLclVar: public GenTreeLclVarCommon
2140 {
2141     IL_OFFSET       gtLclILoffs;    // instr offset of ref (only for debug info)
2142
2143     GenTreeLclVar(var_types type, unsigned lclNum, IL_OFFSET ilOffs
2144                   DEBUGARG(bool largeNode = false)) : 
2145         GenTreeLclVarCommon(GT_LCL_VAR, type, lclNum
2146                             DEBUGARG(largeNode)),
2147             gtLclILoffs(ilOffs)
2148             {}
2149     
2150     GenTreeLclVar(genTreeOps oper, var_types type, unsigned lclNum, IL_OFFSET ilOffs
2151               DEBUGARG(bool largeNode = false)) : 
2152         GenTreeLclVarCommon(oper, type, lclNum
2153                             DEBUGARG(largeNode)),
2154             gtLclILoffs(ilOffs)
2155             {
2156                 assert(OperIsLocal(oper) || OperIsLocalAddr(oper));
2157             }
2158     
2159 #if DEBUGGABLE_GENTREE
2160     GenTreeLclVar() : GenTreeLclVarCommon() {}
2161 #endif
2162 };
2163
2164 // gtLclFld -- load/store/addr of local variable field 
2165
2166 struct GenTreeLclFld: public GenTreeLclVarCommon
2167 {
2168     unsigned        gtLclOffs;      // offset into the variable to access
2169
2170     FieldSeqNode*   gtFieldSeq;     // This LclFld node represents some sequences of accesses.
2171
2172     // old/FE style constructor where load/store/addr share same opcode
2173     GenTreeLclFld(var_types type, unsigned lclNum, unsigned lclOffs) : 
2174         GenTreeLclVarCommon(GT_LCL_FLD, type, lclNum),
2175         gtLclOffs(lclOffs), gtFieldSeq(NULL)
2176         {
2177             assert(sizeof(*this) <= s_gtNodeSizes[GT_LCL_FLD]);
2178         }
2179
2180
2181     GenTreeLclFld(genTreeOps oper, var_types type, unsigned lclNum, unsigned lclOffs) : 
2182         GenTreeLclVarCommon(oper, type, lclNum),
2183         gtLclOffs(lclOffs), gtFieldSeq(NULL)
2184         {
2185             assert(sizeof(*this) <= s_gtNodeSizes[GT_LCL_FLD]);
2186         }
2187 #if DEBUGGABLE_GENTREE
2188     GenTreeLclFld() : GenTreeLclVarCommon() {}
2189 #endif
2190 };
2191
2192 struct GenTreeRegVar: public GenTreeLclVarCommon
2193 {
2194     // TODO-Cleanup: Note that the base class GenTree already has a gtRegNum field.
2195     // It's not clear exactly why a GT_REG_VAR has a separate field. When
2196     // GT_REG_VAR is created, the two are identical. It appears that they may
2197     // or may not remain so. In particular, there is a comment in stackfp.cpp
2198     // that states:
2199     //
2200     //      There used to be an assertion: assert(src->gtRegNum == src->gtRegVar.gtRegNum, ...)
2201     //      here, but there's actually no reason to assume that.  AFAICT, for FP vars under stack FP,
2202     //      src->gtRegVar.gtRegNum is the allocated stack pseudo-register, but src->gtRegNum is the
2203     //      FP stack position into which that is loaded to represent a particular use of the variable.
2204     //
2205     // It might be the case that only for stackfp do they ever differ.
2206     //
2207     // The following might be possible: the GT_REG_VAR node has a last use prior to a complex
2208     // subtree being evaluated. It could then be spilled from the register. Later,
2209     // it could be unspilled into a different register, which would be recorded at
2210     // the unspill time in the GenTree::gtRegNum, whereas GenTreeRegVar::gtRegNum
2211     // is left alone. It's not clear why that is useful.
2212     //
2213     // Assuming there is a particular use, like stack fp, that requires it, maybe we
2214     // can get rid of GT_REG_VAR and just leave it as GT_LCL_VAR, using the base class gtRegNum field.
2215     // If we need it for stackfp, we could add a GenTreeStackFPRegVar type, which carries both the
2216     // pieces of information, in a clearer and more specific way (in particular, with
2217     // a different member name).
2218     //
2219
2220 private:
2221
2222     regNumberSmall  _gtRegNum;
2223
2224 public:
2225
2226     GenTreeRegVar(var_types type, unsigned lclNum, regNumber regNum) : 
2227         GenTreeLclVarCommon(GT_REG_VAR, type, lclNum
2228                             )
2229         {
2230             gtRegNum = regNum;
2231         }
2232
2233     // The register number is stored in a small format (8 bits), but the getters return and the setters take
2234     // a full-size (unsigned) format, to localize the casts here.
2235
2236     __declspec(property(get=GetRegNum,put=SetRegNum))
2237     regNumber           gtRegNum;
2238
2239     regNumber GetRegNum() const
2240     {
2241         return (regNumber) _gtRegNum;
2242     }
2243
2244     void SetRegNum(regNumber reg)
2245     {
2246         _gtRegNum = (regNumberSmall) reg;
2247         assert(_gtRegNum == reg);
2248     }
2249
2250 #if DEBUGGABLE_GENTREE
2251     GenTreeRegVar() : GenTreeLclVarCommon() {}
2252 #endif
2253 };
2254                               
2255 /* gtCast -- conversion to a different type  (GT_CAST) */
2256
2257 struct GenTreeCast: public GenTreeOp
2258 {
2259     GenTreePtr&     CastOp() { return gtOp1; }
2260     var_types       gtCastType;
2261
2262     GenTreeCast(var_types type, GenTreePtr op, var_types castType 
2263                 DEBUGARG(bool largeNode = false)) : 
2264         GenTreeOp(GT_CAST, type, op, nullptr
2265                     DEBUGARG(largeNode)), 
2266         gtCastType(castType) 
2267         {}
2268 #if DEBUGGABLE_GENTREE
2269     GenTreeCast() : GenTreeOp() {}
2270 #endif
2271 };
2272
2273
2274 // GT_BOX nodes are place markers for boxed values.  The "real" tree
2275 // for most purposes is in gtBoxOp.
2276 struct GenTreeBox: public GenTreeUnOp
2277 {
2278     // An expanded helper call to implement the "box" if we don't get
2279     // rid of it any other way.  Must be in same position as op1.
2280
2281     GenTreePtr&      BoxOp() { return gtOp1; }
2282     // This is the statement that contains the assignment tree when the node is an inlined GT_BOX on a value
2283     // type            
2284     GenTreePtr       gtAsgStmtWhenInlinedBoxValue;
2285
2286     GenTreeBox(var_types type, GenTreePtr boxOp, GenTreePtr asgStmtWhenInlinedBoxValue) : 
2287         GenTreeUnOp(GT_BOX, type, boxOp),
2288         gtAsgStmtWhenInlinedBoxValue(asgStmtWhenInlinedBoxValue)
2289         {}
2290 #if DEBUGGABLE_GENTREE
2291     GenTreeBox() : GenTreeUnOp() {}
2292 #endif
2293 };
2294
2295
2296
2297 /* gtField  -- data member ref  (GT_FIELD) */
2298
2299 struct GenTreeField: public GenTree
2300 {
2301     GenTreePtr      gtFldObj;
2302     CORINFO_FIELD_HANDLE    gtFldHnd;
2303     DWORD           gtFldOffset;
2304     bool            gtFldMayOverlap;
2305 #ifdef FEATURE_READYTORUN_COMPILER
2306     CORINFO_CONST_LOOKUP gtFieldLookup;
2307 #endif
2308
2309     GenTreeField(var_types type) : 
2310         GenTree(GT_FIELD, type 
2311                 ) 
2312     {
2313         gtFldMayOverlap = false;
2314     }
2315 #if DEBUGGABLE_GENTREE
2316     GenTreeField() : GenTree() {}
2317 #endif
2318 };
2319
2320 // Represents the Argument list of a call node, as a Lisp-style linked list.
2321 // (Originally I had hoped that this could have *only* the m_arg/m_rest fields, but it turns out
2322 // that enough of the GenTree mechanism is used that it makes sense just to make it a subtype.  But
2323 // note that in many ways, this is *not* a "real" node of the tree, but rather a mechanism for
2324 // giving call nodes a flexible number of children.  GenTreeArgListNodes never evaluate to registers,
2325 // for example.)
2326
2327 // Note that while this extends GenTreeOp, it is *not* an EXOP.  We don't add any new fields, and one
2328 // is free to allocate a GenTreeOp of type GT_LIST.  If you use this type, you get the convenient Current/Rest
2329 // method names for the arguments.
2330 struct GenTreeArgList: public GenTreeOp  
2331 {
2332     GenTreePtr&      Current() { return gtOp1; }
2333     GenTreeArgList*& Rest()    { assert(gtOp2 == NULL || gtOp2->OperGet() == GT_LIST); return *reinterpret_cast<GenTreeArgList**>(&gtOp2); }
2334
2335 #if DEBUGGABLE_GENTREE
2336     GenTreeArgList() : GenTreeOp() {}
2337 #endif
2338
2339     GenTreeArgList(GenTreePtr arg) :
2340         GenTreeArgList(arg, nullptr) {}
2341       
2342     GenTreeArgList(GenTreePtr arg, GenTreeArgList* rest) : 
2343         GenTreeOp(GT_LIST, TYP_VOID, arg, rest) 
2344     {
2345         // With structs passed in multiple args we could have an arg
2346         // GT_LIST containing a list of LCL_FLDs, see IsListForMultiRegArg()
2347         //
2348         assert((arg != nullptr) && ((!arg->IsList()) || (arg->IsListForMultiRegArg())));
2349         gtFlags |=  arg->gtFlags & GTF_ALL_EFFECT;
2350         if (rest != NULL)
2351         {
2352             gtFlags |= rest->gtFlags & GTF_ALL_EFFECT;
2353         }
2354     }
2355 };
2356
2357 // There was quite a bit of confusion in the code base about which of gtOp1 and gtOp2 was the
2358 // 'then' and 'else' clause of a colon node.  Adding these accessors, while not enforcing anything,
2359 // at least *allows* the programmer to be obviously correct.
2360 // However, these conventions seem backward.
2361 // TODO-Cleanup: If we could get these accessors used everywhere, then we could switch them.
2362 struct GenTreeColon: public GenTreeOp
2363 {
2364     GenTreePtr&      ThenNode() { return gtOp2; }
2365     GenTreePtr&      ElseNode() { return gtOp1; }
2366
2367 #if DEBUGGABLE_GENTREE
2368     GenTreeColon() : GenTreeOp() {}
2369 #endif
2370
2371     GenTreeColon(var_types typ, GenTreePtr thenNode, GenTreePtr elseNode) : 
2372         GenTreeOp(GT_COLON, typ, elseNode, thenNode)
2373         {}
2374 };
2375
2376 // gtCall   -- method call      (GT_CALL)
2377 typedef class fgArgInfo *  fgArgInfoPtr;
2378 enum class InlineObservation;
2379
2380 // Return type descriptor of a GT_CALL node.
2381 // x64 Unix, Arm64, Arm32 and x86 allow a value to be returned in multiple
2382 // registers. For such calls this struct provides the following info 
2383 // on their return type
2384 //    - type of value returned in each return register
2385 //    - ABI return register numbers in which the value is returned
2386 //    - count of return registers in which the value is returned
2387 //
2388 // TODO-ARM: Update this to meet the needs of Arm64 and Arm32
2389 //
2390 // TODO-AllArch: Right now it is used for describing multi-reg returned types.
2391 // Eventually we would want to use it for describing even single-reg
2392 // returned types (e.g. structs returned in single register x64/arm).
2393 // This would allow us not to lie or normalize single struct return
2394 // values in importer/morph.
2395 struct ReturnTypeDesc
2396 {
2397 private:
2398     var_types m_regType[MAX_RET_REG_COUNT];
2399
2400 #ifdef DEBUG
2401     bool m_inited;
2402 #endif
2403
2404 public:
2405     ReturnTypeDesc()
2406     {
2407         Reset();
2408     }
2409
2410     // Initialize the return type descriptor given its type handle
2411     void InitializeReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd);
2412
2413     // Reset type descriptor to defaults
2414     void Reset()
2415     {
2416         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2417         {
2418             m_regType[i] = TYP_UNKNOWN;
2419         }
2420 #ifdef DEBUG
2421         m_inited = false;
2422 #endif
2423     }
2424
2425     //--------------------------------------------------------------------------------------------
2426     // GetReturnRegCount:  Get the count of return registers in which the return value is returned.
2427     //
2428     // Arguments:
2429     //    None
2430     //
2431     // Return Value:
2432     //   Count of return registers.
2433     //   Returns 0 if the return type is not returned in registers.
2434     unsigned GetReturnRegCount() const
2435     {
2436         assert(m_inited);
2437
2438         int regCount = 0;
2439         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2440         {
2441             if (m_regType[i] == TYP_UNKNOWN)
2442             {
2443                 break;
2444             }
2445             // otherwise
2446             regCount++;
2447         }
2448
2449 #ifdef DEBUG
2450         // Any remaining elements in m_regTypes[] should also be TYP_UNKNOWN
2451         for (unsigned i = regCount+1; i < MAX_RET_REG_COUNT; ++i)
2452         {
2453             assert(m_regType[i] == TYP_UNKNOWN);
2454         }
2455 #endif        
2456
2457         return regCount;
2458     }
2459
2460     //-----------------------------------------------------------------------
2461     // IsMultiRegRetType: check whether the type is returned in multiple 
2462     // return registers.
2463     //
2464     // Arguments: 
2465     //    None
2466     //
2467     // Return Value:
2468     //    Returns true if the type is returned in multiple return registers.
2469     //    False otherwise.
2470     // Note that we only have to examine the first two values to determine this
2471     //
2472     bool IsMultiRegRetType() const
2473     {
2474         if (MAX_RET_REG_COUNT < 2)
2475         {
2476             return false;
2477         }
2478         else
2479         {
2480             return ((m_regType[0] != TYP_UNKNOWN) &&
2481                     (m_regType[1] != TYP_UNKNOWN));
2482         }
2483     }
2484
2485     //--------------------------------------------------------------------------
2486     // GetReturnRegType:  Get var_type of the return register specified by index.
2487     // 
2488     // Arguments:
2489     //    index - Index of the return register.
2490     //            First return register will have an index 0 and so on.
2491     //
2492     // Return Value:
2493     //    var_type of the return register specified by its index.
2494     //    asserts if the index does not have a valid register return type.
2495     
2496     var_types GetReturnRegType(unsigned index)
2497     {
2498         var_types result = m_regType[index];
2499         assert(result != TYP_UNKNOWN);
2500
2501         return result;
2502     }
2503
2504     // Get ith ABI return register 
2505     regNumber GetABIReturnReg(unsigned idx);
2506
2507     // Get reg mask of ABI return registers 
2508     regMaskTP GetABIReturnRegs();
2509 };
2510
2511 struct GenTreeCall final : public GenTree
2512 {
2513     GenTreePtr        gtCallObjp;             // The instance argument ('this' pointer)
2514     GenTreeArgList*   gtCallArgs;             // The list of arguments in original evaluation order
2515     GenTreeArgList*   gtCallLateArgs;         // On x86:     The register arguments in an optimal order
2516                                               // On ARM/x64: - also includes any outgoing arg space arguments
2517                                               //             - that were evaluated into a temp LclVar
2518     fgArgInfoPtr      fgArgInfo;
2519
2520 #if !FEATURE_FIXED_OUT_ARGS
2521     int               regArgListCount;
2522     regList           regArgList;  
2523 #endif
2524     
2525     // TODO-Throughput: Revisit this (this used to be only defined if
2526     // FEATURE_FIXED_OUT_ARGS was enabled, so this makes GenTreeCall 4 bytes bigger on x86). 
2527     CORINFO_SIG_INFO* callSig;                // Used by tail calls and to register callsites with the EE
2528
2529 #ifdef LEGACY_BACKEND
2530     regMaskTP         gtCallRegUsedMask;      // mask of registers used to pass parameters
2531 #endif // LEGACY_BACKEND
2532
2533     // State required to support multi-reg returning call nodes.
2534     // For now it is enabled only for x64 unix.
2535     //
2536     // TODO-AllArch: enable for all call nodes to unify single-reg and multi-reg returns.
2537 #if FEATURE_MULTIREG_RET
2538     ReturnTypeDesc    gtReturnTypeDesc;
2539
2540     // gtRegNum would always be the first return reg.
2541     // The following array holds the other reg numbers of multi-reg return.
2542     regNumber         gtOtherRegs[MAX_RET_REG_COUNT - 1];
2543
2544     // GTF_SPILL or GTF_SPILLED flag on a multi-reg call node indicates that one or
2545     // more of its result regs are in that state.  The spill flag of each of the
2546     // return register is stored in the below array.
2547     unsigned          gtSpillFlags[MAX_RET_REG_COUNT];
2548 #endif 
2549
2550     //-----------------------------------------------------------------------
2551     // GetReturnTypeDesc: get the type descriptor of return value of the call
2552     //
2553     // Arguments:
2554     //    None
2555     //
2556     // Returns
2557     //    Type descriptor of the value returned by call
2558     //
2559     // Note:
2560     //    Right now implemented only for x64 unix and yet to be 
2561     //    implemented for other multi-reg target arch (Arm64/Arm32/x86).
2562     //
2563     // TODO-AllArch: enable for all call nodes to unify single-reg and multi-reg returns.
2564     ReturnTypeDesc*   GetReturnTypeDesc()
2565     {
2566 #if FEATURE_MULTIREG_RET
2567         return &gtReturnTypeDesc;
2568 #else
2569         return nullptr;
2570 #endif
2571     }
2572
2573     //---------------------------------------------------------------------------
2574     // GetRegNumByIdx: get ith return register allocated to this call node.
2575     //
2576     // Arguments:
2577     //     idx   -   index of the return register
2578     //
2579     // Return Value:
2580     //     Return regNumber of ith return register of call node.
2581     //     Returns REG_NA if there is no valid return register for the given index.
2582     //
2583     regNumber  GetRegNumByIdx(unsigned idx) const
2584     {
2585         assert(idx < MAX_RET_REG_COUNT);
2586
2587         if (idx == 0)
2588         {
2589             return gtRegNum;
2590         }
2591
2592 #if FEATURE_MULTIREG_RET
2593         return gtOtherRegs[idx-1];
2594 #else
2595         return REG_NA;
2596 #endif
2597     }
2598
2599     //----------------------------------------------------------------------
2600     // SetRegNumByIdx: set ith return register of this call node
2601     //
2602     // Arguments:
2603     //    reg    -   reg number
2604     //    idx    -   index of the return register
2605     //
2606     // Return Value:
2607     //    None
2608     //
2609     void  SetRegNumByIdx(regNumber reg, unsigned idx)
2610     {
2611         assert(idx < MAX_RET_REG_COUNT);
2612
2613         if (idx == 0)
2614         {
2615             gtRegNum = reg;
2616         }
2617 #if FEATURE_MULTIREG_RET
2618         else
2619         {
2620             gtOtherRegs[idx - 1] = reg;
2621             assert(gtOtherRegs[idx - 1] == reg);
2622         }
2623 #else
2624         unreached();
2625 #endif
2626     }
2627
2628     //----------------------------------------------------------------------------
2629     // ClearOtherRegs: clear multi-reg state to indicate no regs are allocated
2630     //
2631     // Arguments:
2632     //    None
2633     //
2634     // Return Value:
2635     //    None
2636     //
2637     void  ClearOtherRegs()
2638     {
2639 #if FEATURE_MULTIREG_RET
2640         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
2641         {
2642             gtOtherRegs[i] = REG_NA;
2643         }
2644 #endif
2645     }
2646
2647     //----------------------------------------------------------------------------
2648     // CopyOtherRegs: copy multi-reg state from the given call node to this node
2649     //
2650     // Arguments:
2651     //    fromCall  -  GenTreeCall node from which to copy multi-reg state
2652     //
2653     // Return Value:
2654     //    None
2655     //
2656     void CopyOtherRegs(GenTreeCall* fromCall)
2657     {
2658 #if FEATURE_MULTIREG_RET
2659         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
2660         {
2661             this->gtOtherRegs[i] = fromCall->gtOtherRegs[i];
2662         }
2663 #endif
2664     }
2665
2666     // Get reg mask of all the valid registers of gtOtherRegs array
2667     regMaskTP  GetOtherRegMask() const;
2668
2669     //----------------------------------------------------------------------
2670     // GetRegSpillFlagByIdx: get spill flag associated with the return register 
2671     // specified by its index.
2672     //
2673     // Arguments:
2674     //    idx  -  Position or index of the return register
2675     //
2676     // Return Value:
2677     //    Returns GTF_* flags associated with.
2678     unsigned GetRegSpillFlagByIdx(unsigned idx) const
2679     {
2680         assert(idx < MAX_RET_REG_COUNT);
2681
2682 #if FEATURE_MULTIREG_RET
2683         return gtSpillFlags[idx];
2684 #else
2685         assert(!"unreached");
2686         return 0;
2687 #endif
2688     }
2689
2690     //----------------------------------------------------------------------
2691     // SetRegSpillFlagByIdx: set spill flags for the return register 
2692     // specified by its index.
2693     //
2694     // Arguments:
2695     //    flags  -  GTF_* flags
2696     //    idx    -  Position or index of the return register
2697     //
2698     // Return Value:
2699     //    None
2700     void SetRegSpillFlagByIdx(unsigned flags, unsigned idx)
2701     {
2702         assert(idx < MAX_RET_REG_COUNT);
2703
2704 #if FEATURE_MULTIREG_RET
2705         gtSpillFlags[idx] = flags;
2706 #else
2707         unreached();
2708 #endif
2709     }
2710
2711     //-------------------------------------------------------------------
2712     // clearOtherRegFlags: clear GTF_* flags associated with gtOtherRegs
2713     //
2714     // Arguments:
2715     //     None
2716     //
2717     // Return Value:
2718     //     None
2719     void ClearOtherRegFlags()
2720     {
2721 #if FEATURE_MULTIREG_RET
2722         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2723         {
2724             gtSpillFlags[i] = 0;
2725         }
2726 #endif
2727     }
2728
2729     //-------------------------------------------------------------------------
2730     // CopyOtherRegFlags: copy GTF_* flags associated with gtOtherRegs from
2731     // the given call node.
2732     //
2733     // Arguments:
2734     //    fromCall  -  GenTreeCall node from which to copy
2735     //
2736     // Return Value:
2737     //    None
2738     //
2739     void CopyOtherRegFlags(GenTreeCall* fromCall)
2740     {
2741 #if FEATURE_MULTIREG_RET
2742         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2743         {
2744             this->gtSpillFlags[i] = fromCall->gtSpillFlags[i];
2745         }
2746 #endif
2747     }
2748
2749 #define     GTF_CALL_M_EXPLICIT_TAILCALL       0x0001  // GT_CALL -- the call is "tail" prefixed and importer has performed tail call checks
2750 #define     GTF_CALL_M_TAILCALL                0x0002  // GT_CALL -- the call is a tailcall
2751 #define     GTF_CALL_M_VARARGS                 0x0004  // GT_CALL -- the call uses varargs ABI
2752 #define     GTF_CALL_M_RETBUFFARG              0x0008  // GT_CALL -- first parameter is the return buffer argument
2753 #define     GTF_CALL_M_DELEGATE_INV            0x0010  // GT_CALL -- call to Delegate.Invoke
2754 #define     GTF_CALL_M_NOGCCHECK               0x0020  // GT_CALL -- not a call for computing full interruptability
2755 #define     GTF_CALL_M_SPECIAL_INTRINSIC       0x0040  // GT_CALL -- function that could be optimized as an intrinsic 
2756                                                        // in special cases. Used to optimize fast way out in morphing
2757 #define     GTF_CALL_M_UNMGD_THISCALL          0x0080  // "this" pointer (first argument) should be enregistered (only for GTF_CALL_UNMANAGED)
2758 #define     GTF_CALL_M_VIRTSTUB_REL_INDIRECT   0x0080  // the virtstub is indirected through a relative address (only for GTF_CALL_VIRT_STUB)
2759 #define     GTF_CALL_M_NONVIRT_SAME_THIS       0x0080  // callee "this" pointer is equal to caller this pointer (only for GTF_CALL_NONVIRT)
2760 #define     GTF_CALL_M_FRAME_VAR_DEATH         0x0100  // GT_CALL -- the compLvFrameListRoot variable dies here (last use)
2761
2762 #ifndef LEGACY_BACKEND
2763 #define     GTF_CALL_M_TAILCALL_VIA_HELPER     0x0200  // GT_CALL -- call is a tail call dispatched via tail call JIT helper.
2764 #endif // !LEGACY_BACKEND
2765
2766 #if FEATURE_TAILCALL_OPT
2767 #define     GTF_CALL_M_IMPLICIT_TAILCALL       0x0400  // GT_CALL -- call is an opportunistic tail call and importer has performed tail call checks
2768 #define     GTF_CALL_M_TAILCALL_TO_LOOP        0x0800  // GT_CALL -- call is a fast recursive tail call that can be converted into a loop
2769 #endif
2770
2771 #define     GTF_CALL_M_PINVOKE                 0x1000  // GT_CALL -- call is a pinvoke.  This mirrors VM flag CORINFO_FLG_PINVOKE.
2772                                                        // A call marked as Pinvoke is not necessarily a GT_CALL_UNMANAGED. For e.g.
2773                                                        // an IL Stub dynamically generated for a PInvoke declaration is flagged as
2774                                                        // a Pinvoke but not as an unmanaged call. See impCheckForPInvokeCall() to
2775                                                        // know when these flags are set.
2776
2777 #define     GTF_CALL_M_R2R_REL_INDIRECT        0x2000  // GT_CALL -- ready to run call is indirected through a relative address
2778
2779     bool IsUnmanaged()       const { return (gtFlags & GTF_CALL_UNMANAGED) != 0; }
2780     bool NeedsNullCheck()    const { return (gtFlags & GTF_CALL_NULLCHECK) != 0; }
2781     bool CallerPop()         const { return (gtFlags & GTF_CALL_POP_ARGS) != 0;  }
2782     bool IsVirtual()         const { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) != GTF_CALL_NONVIRT; }
2783     bool IsVirtualStub()     const { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) == GTF_CALL_VIRT_STUB; }
2784     bool IsVirtualVtable()   const { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) == GTF_CALL_VIRT_VTABLE; }
2785     bool IsInlineCandidate() const { return (gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0; }
2786
2787 #ifndef LEGACY_BACKEND
2788     bool HasNonStandardAddedArgs(Compiler* compiler) const;
2789     int GetNonStandardAddedArgCount(Compiler* compiler) const;
2790 #endif // !LEGACY_BACKEND
2791
2792     // Returns true if this call uses a retBuf argument and its calling convention
2793     bool HasRetBufArg() const
2794     {
2795          return (gtCallMoreFlags & GTF_CALL_M_RETBUFFARG) != 0;
2796     }
2797
2798     //-------------------------------------------------------------------------
2799     // TreatAsHasRetBufArg:
2800     //
2801     // Arguments:
2802     //     compiler, the compiler instance so that we can call eeGetHelperNum
2803     //
2804     // Return Value:
2805     //     Returns true if we treat the call as if it has a retBuf argument
2806     //     This method may actually have a retBuf argument 
2807     //     or it could be a JIT helper that we are still transforming during 
2808     //     the importer phase.
2809     //
2810     // Notes:
2811     //     On ARM64 marking the method with the GTF_CALL_M_RETBUFFARG flag
2812     //     will make HasRetBufArg() return true, but will also force the 
2813     //     use of register x8 to pass the RetBuf argument.
2814     //
2815     bool TreatAsHasRetBufArg(Compiler* compiler) const;
2816
2817     //-----------------------------------------------------------------------------------------
2818     // HasMultiRegRetVal: whether the call node returns its value in multiple return registers.
2819     //
2820     // Arguments:
2821     //     None
2822     //
2823     // Return Value:
2824     //     True if the call is returning a multi-reg return value. False otherwise.
2825     //
2826     // Note:
2827     //     This is implemented only for x64 Unix and yet to be implemented for
2828     //     other multi-reg return target arch (arm64/arm32/x86).
2829     //
2830     // TODO-ARM: Implement this routine for Arm64 and Arm32
2831     bool HasMultiRegRetVal() const 
2832     { 
2833 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
2834         return varTypeIsStruct(gtType) && !HasRetBufArg(); 
2835 #elif defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)
2836         // LEGACY_BACKEND does not use multi reg returns for calls with long return types
2837         return varTypeIsLong(gtType);
2838 #else
2839         return false;
2840 #endif
2841     }
2842
2843     // Returns true if VM has flagged this method as CORINFO_FLG_PINVOKE.
2844     bool IsPInvoke() const              { return (gtCallMoreFlags & GTF_CALL_M_PINVOKE) != 0; }
2845
2846     // Note that the distinction of whether tail prefixed or an implicit tail call
2847     // is maintained on a call node till fgMorphCall() after which it will be
2848     // either a tail call (i.e. IsTailCall() is true) or a non-tail call.
2849     bool IsTailPrefixedCall() const     { return (gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0; }     
2850
2851     // This method returning "true" implies that tail call flowgraph morhphing has 
2852     // performed final checks and committed to making a tail call.
2853     bool IsTailCall() const             { return (gtCallMoreFlags & GTF_CALL_M_TAILCALL) != 0; }
2854
2855     // This method returning "true" implies that importer has performed tail call checks
2856     // and providing a hint that this can be converted to a tail call.
2857     bool CanTailCall() const            { return IsTailPrefixedCall() || IsImplicitTailCall(); }
2858
2859 #ifndef LEGACY_BACKEND
2860     bool IsTailCallViaHelper() const    { return IsTailCall() && (gtCallMoreFlags & GTF_CALL_M_TAILCALL_VIA_HELPER); } 
2861 #else // LEGACY_BACKEND
2862     bool IsTailCallViaHelper() const    { return true; }
2863 #endif // LEGACY_BACKEND
2864
2865 #if FEATURE_FASTTAILCALL    
2866     bool IsFastTailCall() const         { return IsTailCall() && !(gtCallMoreFlags & GTF_CALL_M_TAILCALL_VIA_HELPER); }
2867 #else // !FEATURE_FASTTAILCALL
2868     bool IsFastTailCall() const         { return false; }    
2869 #endif // !FEATURE_FASTTAILCALL
2870
2871 #if FEATURE_TAILCALL_OPT
2872     // Returns true if this is marked for opportunistic tail calling.
2873     // That is, can be tail called though not explicitly prefixed with "tail" prefix.
2874     bool IsImplicitTailCall() const             { return (gtCallMoreFlags & GTF_CALL_M_IMPLICIT_TAILCALL) != 0; }
2875     bool IsTailCallConvertibleToLoop() const    { return (gtCallMoreFlags & GTF_CALL_M_TAILCALL_TO_LOOP) != 0; }
2876 #else // !FEATURE_TAILCALL_OPT
2877     bool IsImplicitTailCall() const             { return false; }
2878     bool IsTailCallConvertibleToLoop() const    { return false; }
2879 #endif // !FEATURE_TAILCALL_OPT
2880
2881     bool IsSameThis() const                 { return (gtCallMoreFlags & GTF_CALL_M_NONVIRT_SAME_THIS) != 0; } 
2882     bool IsDelegateInvoke() const           { return (gtCallMoreFlags & GTF_CALL_M_DELEGATE_INV) != 0; } 
2883     bool IsVirtualStubRelativeIndir() const { return (gtCallMoreFlags & GTF_CALL_M_VIRTSTUB_REL_INDIRECT) != 0; } 
2884
2885 #ifdef FEATURE_READYTORUN_COMPILER
2886     bool IsR2RRelativeIndir() const         { return (gtCallMoreFlags & GTF_CALL_M_R2R_REL_INDIRECT) != 0; }
2887     void setEntryPoint(CORINFO_CONST_LOOKUP entryPoint)
2888     {
2889         gtEntryPoint = entryPoint;
2890         if (gtEntryPoint.accessType == IAT_PVALUE)
2891         {
2892             gtCallMoreFlags |= GTF_CALL_M_R2R_REL_INDIRECT;
2893         }
2894     }
2895 #endif // FEATURE_READYTORUN_COMPILER
2896
2897     bool IsVarargs() const                  { return (gtCallMoreFlags & GTF_CALL_M_VARARGS) != 0; }
2898
2899     unsigned short  gtCallMoreFlags;        // in addition to gtFlags
2900     
2901     unsigned char   gtCallType   :3;        // value from the gtCallTypes enumeration
2902     unsigned char   gtReturnType :5;        // exact return type
2903
2904     CORINFO_CLASS_HANDLE    gtRetClsHnd;    // The return type handle of the call if it is a struct; always available
2905
2906     union
2907     {
2908         // only used for CALLI unmanaged calls (CT_INDIRECT)
2909         GenTreePtr      gtCallCookie;           
2910         // gtInlineCandidateInfo is only used when inlining methods 
2911         InlineCandidateInfo* gtInlineCandidateInfo;
2912         void* gtStubCallStubAddr;             // GTF_CALL_VIRT_STUB - these are never inlined                
2913         CORINFO_GENERIC_HANDLE compileTimeHelperArgumentHandle; // Used to track type handle argument of dynamic helpers
2914         void* gtDirectCallAddress; // Used to pass direct call address between lower and codegen
2915     };
2916
2917     // expression evaluated after args are placed which determines the control target
2918     GenTree * gtControlExpr; 
2919
2920     union
2921     {
2922         CORINFO_METHOD_HANDLE gtCallMethHnd;  // CT_USER_FUNC
2923         GenTreePtr  gtCallAddr;               // CT_INDIRECT
2924     };
2925
2926 #ifdef FEATURE_READYTORUN_COMPILER
2927     // Call target lookup info for method call from a Ready To Run module
2928     CORINFO_CONST_LOOKUP gtEntryPoint;
2929 #endif
2930
2931 #if defined(DEBUG) || defined(INLINE_DATA)
2932     // For non-inline candidates, track the first observation
2933     // that blocks candidacy.
2934     InlineObservation gtInlineObservation;
2935
2936     // IL offset of the call wrt its parent method.
2937     IL_OFFSET gtRawILOffset;
2938 #endif // defined(DEBUG) || defined(INLINE_DATA)
2939  
2940     bool IsHelperCall() const
2941     {
2942         return gtCallType == CT_HELPER;
2943     }
2944  
2945     bool IsHelperCall(CORINFO_METHOD_HANDLE callMethHnd) const
2946     {
2947         return IsHelperCall() && (callMethHnd == gtCallMethHnd);
2948     }
2949  
2950     bool IsHelperCall(Compiler* compiler, unsigned helper) const;
2951
2952     GenTreeCall(var_types type) : 
2953         GenTree(GT_CALL, type) 
2954     {
2955     }
2956 #if DEBUGGABLE_GENTREE
2957     GenTreeCall() : GenTree()
2958     {
2959     }
2960 #endif
2961 };
2962
2963 struct GenTreeCmpXchg: public GenTree
2964 {
2965     GenTreePtr      gtOpLocation;
2966     GenTreePtr      gtOpValue;
2967     GenTreePtr      gtOpComparand;
2968
2969     GenTreeCmpXchg(var_types type, GenTreePtr loc, GenTreePtr val, GenTreePtr comparand) : 
2970         GenTree(GT_CMPXCHG, type), 
2971         gtOpLocation(loc), gtOpValue(val),  gtOpComparand(comparand)
2972         {
2973             // There's no reason to do a compare-exchange on a local location, so we'll assume that all of these
2974             // have global effects.
2975             gtFlags |= GTF_GLOB_EFFECT;
2976         }
2977 #if DEBUGGABLE_GENTREE
2978     GenTreeCmpXchg() : GenTree() {}
2979 #endif
2980 };
2981
2982
2983
2984 struct GenTreeFptrVal: public GenTree
2985 {
2986     CORINFO_METHOD_HANDLE gtFptrMethod;
2987
2988 #ifdef FEATURE_READYTORUN_COMPILER
2989     CORINFO_CONST_LOOKUP gtEntryPoint;
2990     CORINFO_RESOLVED_TOKEN* gtLdftnResolvedToken;
2991 #endif
2992
2993     GenTreeFptrVal(var_types type, CORINFO_METHOD_HANDLE meth) : 
2994         GenTree(GT_FTN_ADDR, type), 
2995         gtFptrMethod(meth) 
2996         {}
2997 #if DEBUGGABLE_GENTREE
2998     GenTreeFptrVal() : GenTree() {}
2999 #endif
3000 };
3001
3002 /* gtQmark */
3003 struct GenTreeQmark : public GenTreeOp
3004 {
3005     // Livesets on entry to then and else subtrees
3006     VARSET_TP       gtThenLiveSet;
3007     VARSET_TP       gtElseLiveSet;
3008     
3009     // The "Compiler*" argument is not a DEBUGARG here because we use it to keep track of the set of
3010     // (possible) QMark nodes.
3011     GenTreeQmark(var_types type, GenTreePtr cond, GenTreePtr colonOp, class Compiler* comp);
3012
3013 #if DEBUGGABLE_GENTREE
3014     GenTreeQmark() : GenTreeOp(GT_QMARK, TYP_INT, NULL, NULL) {}
3015 #endif
3016 };
3017
3018 /* gtIntrinsic   -- intrinsic   (possibly-binary op [NULL op2 is allowed] with an additional field) */
3019
3020 struct GenTreeIntrinsic: public GenTreeOp
3021 {
3022     CorInfoIntrinsics     gtIntrinsicId;
3023     CORINFO_METHOD_HANDLE gtMethodHandle;    // Method handle of the method which is treated as an intrinsic.
3024
3025 #ifdef FEATURE_READYTORUN_COMPILER
3026     // Call target lookup info for method call from a Ready To Run module
3027     CORINFO_CONST_LOOKUP gtEntryPoint;
3028 #endif
3029
3030     GenTreeIntrinsic(var_types type, GenTreePtr op1, CorInfoIntrinsics intrinsicId, CORINFO_METHOD_HANDLE methodHandle) :
3031         GenTreeOp(GT_INTRINSIC, type, op1, NULL),
3032         gtIntrinsicId(intrinsicId),
3033         gtMethodHandle(methodHandle)
3034         {}
3035
3036     GenTreeIntrinsic(var_types type, GenTreePtr op1, GenTreePtr op2, CorInfoIntrinsics intrinsicId, CORINFO_METHOD_HANDLE methodHandle) :
3037         GenTreeOp(GT_INTRINSIC, type, op1, op2),
3038         gtIntrinsicId(intrinsicId),
3039         gtMethodHandle(methodHandle)
3040         {}
3041
3042 #if DEBUGGABLE_GENTREE
3043     GenTreeIntrinsic() : GenTreeOp() {}
3044 #endif
3045 };
3046
3047 #ifdef FEATURE_SIMD
3048
3049 /* gtSIMD   -- SIMD intrinsic   (possibly-binary op [NULL op2 is allowed] with additional fields) */
3050 struct GenTreeSIMD: public GenTreeOp
3051 {
3052     SIMDIntrinsicID         gtSIMDIntrinsicID;  // operation Id
3053     var_types               gtSIMDBaseType;     // SIMD vector base type
3054     unsigned                gtSIMDSize;         // SIMD vector size in bytes
3055
3056     GenTreeSIMD(var_types type, GenTreePtr op1, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size) : 
3057         GenTreeOp(GT_SIMD, type, op1, nullptr),
3058         gtSIMDIntrinsicID(simdIntrinsicID),
3059         gtSIMDBaseType(baseType),
3060         gtSIMDSize(size)
3061         {}
3062
3063     GenTreeSIMD(var_types type, GenTreePtr op1, GenTreePtr op2, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size) : 
3064         GenTreeOp(GT_SIMD, type, op1, op2),
3065         gtSIMDIntrinsicID(simdIntrinsicID),
3066         gtSIMDBaseType(baseType),
3067         gtSIMDSize(size)
3068         {}
3069
3070 #if DEBUGGABLE_GENTREE
3071     GenTreeSIMD() : GenTreeOp() {}
3072 #endif
3073 };
3074 #endif // FEATURE_SIMD
3075
3076 /* gtIndex -- array access */
3077
3078 struct GenTreeIndex: public GenTreeOp
3079 {
3080     GenTreePtr&     Arr()   { return gtOp1; }
3081     GenTreePtr&     Index() { return gtOp2; }
3082
3083     unsigned        gtIndElemSize;  // size of elements in the array
3084     CORINFO_CLASS_HANDLE gtStructElemClass;   // If the element type is a struct, this is the struct type.
3085
3086     GenTreeIndex(var_types type, GenTreePtr arr, GenTreePtr ind, unsigned indElemSize) :
3087         GenTreeOp(GT_INDEX, type, arr, ind),
3088         gtIndElemSize(indElemSize),
3089         gtStructElemClass(nullptr)  // We always initialize this after construction.
3090         {
3091 #ifdef DEBUG
3092             if (JitConfig.JitSkipArrayBoundCheck() == 1)
3093             {
3094                 // Skip bounds check
3095             }
3096             else
3097 #endif
3098             {
3099                 // Do bounds check
3100                 gtFlags |= GTF_INX_RNGCHK;
3101             }
3102
3103             if (type == TYP_REF)
3104             {
3105                 gtFlags |= GTF_INX_REFARR_LAYOUT;
3106             }
3107
3108             gtFlags |= GTF_EXCEPT|GTF_GLOB_REF;
3109         }
3110 #if DEBUGGABLE_GENTREE
3111     GenTreeIndex() : GenTreeOp() {}
3112 #endif
3113 };
3114
3115 /* gtArrLen -- array length (GT_ARR_LENGTH)
3116    GT_ARR_LENGTH is used for "arr.length" */
3117
3118 struct GenTreeArrLen: public GenTreeUnOp
3119 {
3120     GenTreePtr&     ArrRef() { return gtOp1; }   // the array address node
3121 private:
3122     int             gtArrLenOffset; // constant to add to "gtArrRef" to get the address of the array length.
3123
3124 public:
3125     inline int      ArrLenOffset() {
3126         return gtArrLenOffset;
3127     }
3128
3129     GenTreeArrLen(var_types type, GenTreePtr arrRef, int lenOffset) : 
3130         GenTreeUnOp(GT_ARR_LENGTH, type, arrRef), 
3131         gtArrLenOffset(lenOffset)
3132         {}
3133
3134 #if DEBUGGABLE_GENTREE
3135     GenTreeArrLen() : GenTreeUnOp() {}
3136 #endif
3137 };
3138
3139 // This takes:
3140 // - a comparison value (generally an array length),
3141 // - an index value, and
3142 // - the label to jump to if the index is out of range.
3143 // - the "kind" of the throw block to branch to on failure
3144 // It generates no result.
3145
3146 struct GenTreeBoundsChk: public GenTree
3147 {
3148     GenTreePtr              gtArrLen;       // An expression for the length of the array being indexed.
3149     GenTreePtr              gtIndex;        // The index expression.
3150
3151     GenTreePtr              gtIndRngFailBB; // Label to jump to for array-index-out-of-range
3152     SpecialCodeKind         gtThrowKind;    // Kind of throw block to branch to on failure
3153
3154     /* Only out-of-ranges at same stack depth can jump to the same label (finding return address is easier)
3155        For delayed calling of fgSetRngChkTarget() so that the
3156        optimizer has a chance of eliminating some of the rng checks */
3157     unsigned        gtStkDepth;
3158
3159     GenTreeBoundsChk(genTreeOps oper, var_types type, GenTreePtr arrLen, GenTreePtr index, SpecialCodeKind kind) : 
3160         GenTree(oper, type), 
3161         gtArrLen(arrLen), gtIndex(index), 
3162         gtIndRngFailBB(NULL), 
3163         gtThrowKind(kind),
3164         gtStkDepth(0)
3165         {
3166             // Effects flags propagate upwards.
3167             gtFlags |= (arrLen->gtFlags & GTF_ALL_EFFECT);
3168             gtFlags |= GTF_EXCEPT;
3169         }
3170 #if DEBUGGABLE_GENTREE
3171     GenTreeBoundsChk() : GenTree() {}
3172 #endif
3173
3174     // If the gtArrLen is really an array length, returns array reference, else "NULL".
3175     GenTreePtr GetArray()
3176     {
3177         if (gtArrLen->OperGet() == GT_ARR_LENGTH)
3178         {
3179             return gtArrLen->gtArrLen.ArrRef();
3180         }
3181         else
3182         {
3183             return NULL;
3184         }
3185     }
3186 };
3187
3188 // gtArrElem -- general array element (GT_ARR_ELEM), for non "SZ_ARRAYS"
3189 //              -- multidimensional arrays, or 1-d arrays with non-zero lower bounds.
3190
3191 struct GenTreeArrElem: public GenTree
3192 {
3193     GenTreePtr      gtArrObj;
3194
3195     #define         GT_ARR_MAX_RANK 3
3196     GenTreePtr      gtArrInds[GT_ARR_MAX_RANK]; // Indices
3197     unsigned char   gtArrRank;                  // Rank of the array
3198
3199     unsigned char   gtArrElemSize;              // !!! Caution, this is an "unsigned char", it is used only
3200                                                 // on the optimization path of array intrisics.
3201                                                 // It stores the size of array elements WHEN it can fit
3202                                                 // into an "unsigned char".
3203                                                 // This has caused VSW 571394.
3204     var_types       gtArrElemType;              // The array element type
3205
3206     // Requires that "inds" is a pointer to an array of "rank" GenTreePtrs for the indices.
3207     GenTreeArrElem(var_types type, GenTreePtr arr, unsigned char rank, unsigned char elemSize, var_types elemType, GenTreePtr* inds) : 
3208         GenTree(GT_ARR_ELEM, type), 
3209         gtArrObj(arr), gtArrRank(rank), gtArrElemSize(elemSize), gtArrElemType(elemType)
3210         {
3211             for (unsigned char i = 0; i < rank; i++) gtArrInds[i] = inds[i];
3212             gtFlags |= GTF_EXCEPT;
3213         }
3214 #if DEBUGGABLE_GENTREE
3215     GenTreeArrElem() : GenTree() {}
3216 #endif
3217 };
3218
3219 //--------------------------------------------
3220 // 
3221 // GenTreeArrIndex (gtArrIndex): Expression to bounds-check the index for one dimension of a
3222 //    multi-dimensional or non-zero-based array., and compute the effective index
3223 //    (i.e. subtracting the lower bound).
3224 //
3225 // Notes:
3226 //    This node is similar in some ways to GenTreeBoundsChk, which ONLY performs the check.
3227 //    The reason that this node incorporates the check into the effective index computation is
3228 //    to avoid duplicating the codegen, as the effective index is required to compute the
3229 //    offset anyway.
3230 //    TODO-CQ: Enable optimization of the lower bound and length by replacing this:
3231 //                /--*  <arrObj>
3232 //                +--*  <index0>
3233 //             +--* ArrIndex[i, ]
3234 //    with something like:
3235 //                   /--*  <arrObj>
3236 //                /--*  ArrLowerBound[i, ]
3237 //                |  /--*  <arrObj>
3238 //                +--*  ArrLen[i, ]    (either generalize GT_ARR_LENGTH or add a new node)
3239 //                +--*  <index0>
3240 //             +--* ArrIndex[i, ]
3241 //    Which could, for example, be optimized to the following when known to be within bounds:
3242 //                /--*  TempForLowerBoundDim0
3243 //                +--*  <index0>
3244 //             +--* - (GT_SUB)
3245 //
3246 struct GenTreeArrIndex: public GenTreeOp
3247 {
3248     // The array object - may be any expression producing an Array reference, but is likely to be a lclVar.
3249     GenTreePtr&     ArrObj()    { return gtOp1; }
3250     // The index expression - may be any integral expression.
3251     GenTreePtr&     IndexExpr() { return gtOp2; }
3252     unsigned char   gtCurrDim;      // The current dimension
3253     unsigned char   gtArrRank;      // Rank of the array
3254     var_types       gtArrElemType;  // The array element type
3255
3256     GenTreeArrIndex(var_types type, GenTreePtr arrObj, GenTreePtr indexExpr,
3257                   unsigned char currDim, unsigned char arrRank, var_types elemType) :
3258         GenTreeOp(GT_ARR_INDEX, type, arrObj, indexExpr),
3259                   gtCurrDim(currDim), gtArrRank(arrRank), gtArrElemType(elemType)
3260     {
3261         gtFlags |= GTF_EXCEPT;
3262     }
3263 #if DEBUGGABLE_GENTREE
3264 protected:
3265     friend GenTree;
3266     // Used only for GenTree::GetVtableForOper()
3267     GenTreeArrIndex() : GenTreeOp() {}
3268 #endif
3269 };
3270
3271 // Represents either an InitBlk, InitObj, CpBlk or CpObj 
3272 // MSIL OpCode.
3273 struct GenTreeBlkOp : public GenTreeOp
3274 {
3275 public:
3276     // The destination for the CpBlk/CpObj/InitBlk/InitObj to copy bits to
3277     GenTreePtr Dest()         { 
3278                                 assert(gtOp1->gtOper == GT_LIST);
3279                                 return gtOp1->gtOp.gtOp1;
3280                               }
3281
3282     // True if this BlkOpNode is a volatile memory operation.
3283     bool IsVolatile() const { return (gtFlags & GTF_BLK_VOLATILE) != 0; }
3284
3285     // Instruction selection: during codegen time, what code sequence we will be using
3286     // to encode this operation.
3287     enum
3288     {
3289         BlkOpKindInvalid,
3290         BlkOpKindHelper,
3291         BlkOpKindRepInstr,
3292         BlkOpKindUnroll,
3293     } gtBlkOpKind;
3294
3295     bool gtBlkOpGcUnsafe; 
3296
3297     GenTreeBlkOp(genTreeOps oper) :
3298         GenTreeOp(oper, TYP_VOID DEBUGARG(true)),
3299             gtBlkOpKind(BlkOpKindInvalid),
3300             gtBlkOpGcUnsafe(false)
3301     {
3302         assert(OperIsBlkOp(oper));
3303     }
3304
3305 #if DEBUGGABLE_GENTREE
3306 protected:
3307     friend GenTree;
3308     GenTreeBlkOp() : GenTreeOp(){}
3309 #endif // DEBUGGABLE_GENTREE
3310 };
3311
3312 // gtObj  -- 'object' (GT_OBJ). */
3313
3314 struct GenTreeObj: public GenTreeUnOp
3315 {
3316     // The address of the block.
3317     GenTreePtr&     Addr()          { return gtOp1; }
3318
3319     CORINFO_CLASS_HANDLE gtClass;   // the class of the object
3320
3321     GenTreeObj(var_types type, GenTreePtr addr, CORINFO_CLASS_HANDLE cls) : 
3322         GenTreeUnOp(GT_OBJ, type, addr),
3323         gtClass(cls)
3324         {
3325             gtFlags |= GTF_GLOB_REF; // An Obj is always a global reference.
3326         }
3327
3328 #if DEBUGGABLE_GENTREE
3329     GenTreeObj() : GenTreeUnOp() {}
3330 #endif
3331 };
3332
3333 // Represents a CpObj MSIL Node.
3334 struct GenTreeCpObj : public GenTreeBlkOp
3335 {
3336 public:
3337     // The source for the CpBlk/CpObj to copy bits from
3338     GenTreePtr Source()       {
3339         assert(gtOper == GT_COPYOBJ && gtOp1->gtOper == GT_LIST);
3340         return gtOp1->gtOp.gtOp2;
3341     }
3342
3343     // In the case of CopyObj, this is the class token that represents the type that is being copied.
3344     GenTreePtr ClsTok() { return gtOp2; }
3345
3346     // If non-null, this array represents the gc-layout of the class that is being copied
3347     // with CpObj.
3348     BYTE*       gtGcPtrs;
3349
3350     // If non-zero, this is the number of slots in the class layout that 
3351     // contain gc-pointers.
3352     unsigned    gtGcPtrCount;
3353
3354     // If non-zero, the number of pointer-sized slots that constitutes the class token in CpObj.
3355     unsigned    gtSlots;
3356
3357     GenTreeCpObj(unsigned gcPtrCount, unsigned gtSlots, BYTE* gtGcPtrs) :
3358         GenTreeBlkOp(GT_COPYOBJ),
3359         gtGcPtrs(gtGcPtrs),
3360         gtGcPtrCount(gcPtrCount),
3361         gtSlots(gtSlots){ }
3362
3363 #if DEBUGGABLE_GENTREE
3364 protected:
3365     friend GenTree;
3366     GenTreeCpObj() : GenTreeBlkOp(),
3367         gtGcPtrs(nullptr),
3368         gtGcPtrCount(0),
3369         gtSlots(0) {}
3370 #endif // DEBUGGABLE_GENTREE
3371 };
3372
3373 // Represents either an InitBlk or InitObj MSIL OpCode.
3374 struct GenTreeInitBlk : public GenTreeBlkOp
3375 {
3376 public:
3377
3378     // The value used to fill the destination buffer.
3379     GenTreePtr InitVal() { assert(gtOp1->gtOper == GT_LIST);
3380                            return gtOp1->gtOp.gtOp2; }
3381
3382     // The size of the buffer to be copied.
3383     GenTreePtr Size()    { return gtOp2; }
3384
3385     GenTreeInitBlk() : GenTreeBlkOp(GT_INITBLK){}
3386
3387 #if DEBUGGABLE_GENTREE
3388 protected:
3389     friend GenTree;
3390 #endif // DEBUGGABLE_GENTREE
3391 };
3392
3393 // Represents a CpBlk or CpObj with no GC-pointers MSIL OpCode.
3394 struct GenTreeCpBlk : public GenTreeBlkOp
3395 {
3396 public:
3397
3398     // The value used to fill the destination buffer.
3399     // The source for the CpBlk/CpObj to copy bits from
3400     GenTreePtr Source() { assert(gtOp1->gtOper == GT_LIST);
3401                           return gtOp1->gtOp.gtOp2; }
3402
3403     // The size of the buffer to be copied.
3404     GenTreePtr Size()   { return gtOp2; }
3405
3406     GenTreeCpBlk() : GenTreeBlkOp(GT_COPYBLK){}
3407
3408 #if DEBUGGABLE_GENTREE
3409 protected:
3410     friend GenTree;
3411 #endif // DEBUGGABLE_GENTREE
3412 };
3413
3414 //--------------------------------------------
3415 // 
3416 // GenTreeArrOffset (gtArrOffset): Expression to compute the accumulated offset for the address
3417 //    of an element of a multi-dimensional or non-zero-based array.
3418 //
3419 // Notes:
3420 //    The result of this expression is (gtOffset * dimSize) + gtIndex
3421 //    where dimSize is the length/stride/size of the dimension, and is obtained from gtArrObj.
3422 //    This node is generated in conjunction with the GenTreeArrIndex node, which computes the
3423 //    effective index for a single dimension.  The sub-trees can be separately optimized, e.g.
3424 //    within a loop body where the expression for the 0th dimension may be invariant.
3425 //
3426 //    Here is an example of how the tree might look for a two-dimension array reference:
3427 //                /--*  const 0
3428 //                |  /--* <arrObj>
3429 //                |  +--* <index0>
3430 //                +--* ArrIndex[i, ]
3431 //                +--*  <arrObj>
3432 //             /--| arrOffs[i, ]
3433 //             |  +--*  <arrObj>
3434 //             |  +--*  <index1>
3435 //             +--* ArrIndex[*,j]
3436 //             +--*  <arrObj>
3437 //          /--| arrOffs[*,j]
3438 //    TODO-CQ: see comment on GenTreeArrIndex for how its representation may change.  When that
3439 //    is done, we will also want to replace the <arrObj> argument to arrOffs with the
3440 //    ArrLen as for GenTreeArrIndex.
3441 //
3442 struct GenTreeArrOffs: public GenTree
3443 {
3444     GenTreePtr      gtOffset;       // The accumulated offset for lower dimensions - must be TYP_I_IMPL, and
3445                                     // will either be a CSE temp, the constant 0, or another GenTreeArrOffs node.
3446     GenTreePtr      gtIndex;        // The effective index for the current dimension - must be non-negative
3447                                     // and can be any expression (though it is likely to be either a GenTreeArrIndex,
3448                                     // node, a lclVar, or a constant).
3449     GenTreePtr      gtArrObj;       // The array object - may be any expression producing an Array reference,
3450                                     // but is likely to be a lclVar.
3451     unsigned char   gtCurrDim;      // The current dimension
3452     unsigned char   gtArrRank;      // Rank of the array
3453     var_types       gtArrElemType;  // The array element type
3454
3455     GenTreeArrOffs(var_types type, GenTreePtr offset, GenTreePtr index, GenTreePtr arrObj,
3456                    unsigned char currDim, unsigned char rank, var_types elemType) : 
3457         GenTree(GT_ARR_OFFSET, type), gtOffset(offset), gtIndex(index), gtArrObj(arrObj),
3458                 gtCurrDim(currDim), gtArrRank(rank), gtArrElemType(elemType)
3459     {
3460         assert(index->gtFlags & GTF_EXCEPT);
3461         gtFlags |= GTF_EXCEPT;
3462     }
3463 #if DEBUGGABLE_GENTREE
3464     GenTreeArrOffs() : GenTree() {}
3465 #endif
3466 };
3467
3468 /* gtAddrMode -- Target-specific canonicalized addressing expression (GT_LEA) */
3469
3470 struct GenTreeAddrMode: public GenTreeOp
3471 {
3472     // Address is Base + Index*Scale + Offset.
3473     // These are the legal patterns:
3474     //
3475     //      Base                                // Base != nullptr && Index == nullptr && Scale == 0 && Offset == 0
3476     //      Base + Index*Scale                  // Base != nullptr && Index != nullptr && Scale != 0 && Offset == 0
3477     //      Base + Offset                       // Base != nullptr && Index == nullptr && Scale == 0 && Offset != 0
3478     //      Base + Index*Scale + Offset         // Base != nullptr && Index != nullptr && Scale != 0 && Offset != 0
3479     //             Index*Scale                  // Base == nullptr && Index != nullptr && Scale >  1 && Offset == 0
3480     //             Index*Scale + Offset         // Base == nullptr && Index != nullptr && Scale >  1 && Offset != 0
3481     //                           Offset         // Base == nullptr && Index == nullptr && Scale == 0 && Offset != 0
3482     //
3483     // So, for example:
3484     //      1. Base + Index is legal with Scale==1
3485     //      2. If Index is null, Scale should be zero (or unintialized / unused)
3486     //      3. If Scale==1, then we should have "Base" instead of "Index*Scale", and "Base + Offset" instead of "Index*Scale + Offset".
3487
3488     // First operand is base address/pointer
3489     bool            HasBase() const     { return gtOp1 != nullptr; }
3490     GenTreePtr&     Base()              { return gtOp1; }
3491
3492     // Second operand is scaled index value
3493     bool            HasIndex() const    { return gtOp2 != nullptr; }
3494     GenTreePtr&     Index()             { return gtOp2; }
3495
3496     unsigned        gtScale;        // The scale factor
3497     unsigned        gtOffset;       // The offset to add
3498
3499     GenTreeAddrMode(var_types type, GenTreePtr base, GenTreePtr index,
3500                     unsigned scale, unsigned offset) : 
3501         GenTreeOp(GT_LEA, type, base, index )
3502     {
3503         gtScale = scale;
3504         gtOffset = offset;
3505     }
3506 #if DEBUGGABLE_GENTREE
3507 protected:
3508     friend GenTree;
3509     // Used only for GenTree::GetVtableForOper()
3510     GenTreeAddrMode() : GenTreeOp() {}
3511 #endif
3512 };
3513
3514 // Indir is just an op, no additional data, but some additional abstractions
3515 struct GenTreeIndir: public GenTreeOp
3516 {
3517     // like an assign, op1 is the destination
3518     GenTreePtr&     Addr()      { return gtOp1; }
3519
3520     // these methods provide an interface to the indirection node which 
3521     bool            HasBase();
3522     bool            HasIndex();
3523     GenTree*        Base(); 
3524     GenTree*        Index(); 
3525     unsigned        Scale();
3526     size_t          Offset();
3527
3528     GenTreeIndir(genTreeOps oper, var_types type, GenTree *addr, GenTree *data) : 
3529     GenTreeOp(oper, type, addr, data)
3530     {
3531     }
3532
3533 #if DEBUGGABLE_GENTREE
3534 protected:
3535     friend GenTree;
3536     // Used only for GenTree::GetVtableForOper()
3537     GenTreeIndir() : GenTreeOp() {}
3538 #endif
3539 };
3540
3541 // Read-modify-write status of a RMW memory op rooted at a storeInd 
3542 enum  RMWStatus {    
3543     STOREIND_RMW_STATUS_UNKNOWN,  // RMW status of storeInd unknown
3544                                   // Default status unless modified by IsRMWMemOpRootedAtStoreInd()
3545
3546     // One of these denote storeind is a RMW memory operation.
3547     STOREIND_RMW_DST_IS_OP1,       // StoreInd is known to be a RMW memory op and dst candidate is op1
3548     STOREIND_RMW_DST_IS_OP2,       // StoreInd is known to be a RMW memory op and dst candidate is op2
3549
3550     // One of these denote the reason for storeind is marked as non-RMW operation
3551     STOREIND_RMW_UNSUPPORTED_ADDR, // Addr mode is not yet supported for RMW memory
3552     STOREIND_RMW_UNSUPPORTED_OPER, // Operation is not supported for RMW memory
3553     STOREIND_RMW_UNSUPPORTED_TYPE, // Type is not supported for RMW memory
3554     STOREIND_RMW_INDIR_UNEQUAL     // Indir to read value is not equivalent to indir that writes the value
3555 };
3556
3557 // StoreInd is just a BinOp, with additional RMW status
3558 struct GenTreeStoreInd: public GenTreeIndir
3559 {
3560 #if !CPU_LOAD_STORE_ARCH
3561     // The below flag is set and used during lowering
3562     RMWStatus  gtRMWStatus;
3563
3564     bool  IsRMWStatusUnknown() { return gtRMWStatus == STOREIND_RMW_STATUS_UNKNOWN; }
3565     bool  IsNonRMWMemoryOp() {
3566         return gtRMWStatus == STOREIND_RMW_UNSUPPORTED_ADDR ||
3567                gtRMWStatus == STOREIND_RMW_UNSUPPORTED_OPER ||
3568                gtRMWStatus == STOREIND_RMW_UNSUPPORTED_TYPE ||
3569                gtRMWStatus == STOREIND_RMW_INDIR_UNEQUAL;
3570     }
3571     bool  IsRMWMemoryOp() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP1 || gtRMWStatus == STOREIND_RMW_DST_IS_OP2; }
3572     bool  IsRMWDstOp1() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP1; }
3573     bool  IsRMWDstOp2() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP2; }
3574 #endif //!CPU_LOAD_STORE_ARCH
3575
3576     RMWStatus GetRMWStatus() { 
3577 #if !CPU_LOAD_STORE_ARCH
3578         return gtRMWStatus; 
3579 #else
3580         return STOREIND_RMW_STATUS_UNKNOWN;
3581 #endif
3582     }
3583
3584     void SetRMWStatusDefault() 
3585     {
3586 #if !CPU_LOAD_STORE_ARCH
3587         gtRMWStatus = STOREIND_RMW_STATUS_UNKNOWN;
3588 #endif
3589     }
3590
3591     void SetRMWStatus(RMWStatus status)
3592     {
3593 #if !CPU_LOAD_STORE_ARCH
3594         gtRMWStatus = status;
3595 #endif
3596     }
3597
3598     GenTreePtr&     Data()      { return gtOp2; }
3599
3600     GenTreeStoreInd(var_types type, GenTree *destPtr, GenTree *data) : 
3601     GenTreeIndir(GT_STOREIND, type, destPtr, data)
3602     {
3603         SetRMWStatusDefault();
3604     }
3605
3606 #if DEBUGGABLE_GENTREE
3607 protected:
3608     friend GenTree;
3609     // Used only for GenTree::GetVtableForOper()
3610     GenTreeStoreInd() : GenTreeIndir() { SetRMWStatusDefault(); }
3611 #endif
3612 };
3613
3614
3615 /* gtRetExp -- Place holder for the return expression from an inline candidate (GT_RET_EXPR) */
3616
3617 struct GenTreeRetExpr: public GenTree
3618 {
3619     GenTreePtr      gtInlineCandidate;
3620
3621     CORINFO_CLASS_HANDLE gtRetClsHnd;
3622
3623     GenTreeRetExpr(var_types type) : 
3624         GenTree(GT_RET_EXPR, type) 
3625         {}
3626 #if DEBUGGABLE_GENTREE
3627     GenTreeRetExpr() : GenTree() {}
3628 #endif
3629 };
3630
3631
3632 /* gtStmt   -- 'statement expr' (GT_STMT) */
3633
3634 class InlineContext;
3635
3636 struct GenTreeStmt: public GenTree
3637 {
3638     GenTreePtr      gtStmtExpr;      // root of the expression tree
3639     GenTreePtr      gtStmtList;      // first node (for forward walks)
3640     InlineContext*  gtInlineContext; // The inline context for this statement.
3641   
3642 #if defined(DEBUGGING_SUPPORT) || defined(DEBUG)
3643     IL_OFFSETX      gtStmtILoffsx;   // instr offset (if available)
3644 #endif
3645
3646 #ifdef DEBUG
3647     IL_OFFSET       gtStmtLastILoffs;// instr offset at end of stmt
3648 #endif
3649
3650     bool            gtStmtIsTopLevel()
3651     {
3652         return (gtFlags & GTF_STMT_TOP_LEVEL) != 0;
3653     }
3654
3655     bool            gtStmtIsEmbedded()
3656     {
3657         return !gtStmtIsTopLevel();
3658     }
3659
3660     // Return the next statement, if it is embedded, otherwise nullptr
3661     GenTreeStmt*    gtStmtNextIfEmbedded()
3662     {
3663         GenTree* nextStmt = gtNext;
3664         if (nextStmt != nullptr && nextStmt->gtStmt.gtStmtIsEmbedded())
3665         {
3666             return nextStmt->AsStmt();
3667         }
3668         else
3669         {
3670             return nullptr;
3671         }
3672     }
3673
3674     GenTree*    gtStmtNextTopLevelStmt()
3675     {
3676         GenTree* nextStmt = gtNext;
3677         while (nextStmt != nullptr && nextStmt->gtStmt.gtStmtIsEmbedded())
3678         {
3679             nextStmt = nextStmt->gtNext;
3680         }
3681         return nextStmt;
3682     }
3683
3684     __declspec(property(get=getNextStmt))
3685     GenTreeStmt* gtNextStmt;
3686
3687     __declspec(property(get=getPrevStmt))
3688     GenTreeStmt* gtPrevStmt;
3689
3690     GenTreeStmt* getNextStmt() 
3691     {
3692         if (gtNext == nullptr)
3693             return nullptr;
3694         else
3695             return gtNext->AsStmt();
3696     }
3697
3698     GenTreeStmt* getPrevStmt() 
3699     {
3700         if (gtPrev == nullptr)
3701             return nullptr;
3702         else
3703             return gtPrev->AsStmt();
3704     }
3705
3706     GenTreeStmt(GenTreePtr expr, IL_OFFSETX offset)
3707         : GenTree(GT_STMT, TYP_VOID)
3708         , gtStmtExpr(expr)
3709         , gtStmtList(nullptr)
3710         , gtInlineContext(nullptr)
3711 #if defined(DEBUGGING_SUPPORT) || defined(DEBUG)
3712         , gtStmtILoffsx(offset)
3713 #endif
3714 #ifdef DEBUG
3715         , gtStmtLastILoffs(BAD_IL_OFFSET)
3716 #endif
3717     {
3718         // Statements can't have statements as part of their expression tree.
3719         assert(expr->gtOper != GT_STMT);
3720
3721         gtFlags |= GTF_STMT_TOP_LEVEL;
3722
3723         // Set the statement to have the same costs as the top node of the tree.
3724         // This is used long before costs have been assigned, so we need to copy
3725         // the raw costs.
3726         CopyRawCosts(expr);
3727     }
3728
3729 #if DEBUGGABLE_GENTREE
3730     GenTreeStmt() : GenTree(GT_STMT, TYP_VOID) {}
3731 #endif
3732 };
3733
3734
3735
3736
3737 /*  NOTE: Any tree nodes that are larger than 8 bytes (two ints or
3738     pointers) must be flagged as 'large' in GenTree::InitNodeSize().
3739  */
3740
3741                 
3742 /* gtClsVar -- 'static data member' (GT_CLS_VAR) */
3743
3744 struct GenTreeClsVar: public GenTree
3745 {
3746     CORINFO_FIELD_HANDLE    gtClsVarHnd;
3747     FieldSeqNode*           gtFieldSeq;
3748
3749     GenTreeClsVar(var_types type, CORINFO_FIELD_HANDLE clsVarHnd, FieldSeqNode* fldSeq) : 
3750         GenTree(GT_CLS_VAR, type), 
3751         gtClsVarHnd(clsVarHnd),
3752         gtFieldSeq(fldSeq)
3753         {
3754             gtFlags |= GTF_GLOB_REF;
3755         }
3756 #if DEBUGGABLE_GENTREE
3757     GenTreeClsVar() : GenTree() {}
3758 #endif
3759 };
3760
3761 /* gtArgPlace -- 'register argument placeholder' (GT_ARGPLACE) */
3762
3763 struct GenTreeArgPlace: public GenTree
3764 {
3765     CORINFO_CLASS_HANDLE    gtArgPlaceClsHnd;    // Needed when we have a TYP_STRUCT argument
3766
3767     GenTreeArgPlace(var_types type, CORINFO_CLASS_HANDLE clsHnd) : 
3768         GenTree(GT_ARGPLACE, type), 
3769         gtArgPlaceClsHnd(clsHnd) 
3770         {}
3771 #if DEBUGGABLE_GENTREE
3772     GenTreeArgPlace() : GenTree() {}
3773 #endif
3774 };
3775
3776 /* gtLabel  -- code label target    (GT_LABEL) */
3777
3778 struct GenTreeLabel: public GenTree
3779 {
3780     BasicBlock* gtLabBB;
3781
3782     GenTreeLabel(BasicBlock* bb) : 
3783         GenTree(GT_LABEL, TYP_VOID), 
3784         gtLabBB(bb) 
3785         {}
3786 #if DEBUGGABLE_GENTREE
3787     GenTreeLabel() : GenTree() {}
3788 #endif
3789 };
3790
3791 /* gtPhiArg -- phi node rhs argument, var = phi(phiarg, phiarg, phiarg...); GT_PHI_ARG */
3792 struct GenTreePhiArg: public GenTreeLclVarCommon
3793 {
3794     BasicBlock  *   gtPredBB;
3795
3796     GenTreePhiArg(var_types type, unsigned lclNum, unsigned snum, BasicBlock* block)
3797         : GenTreeLclVarCommon(GT_PHI_ARG, type, lclNum)
3798         , gtPredBB(block)
3799     { 
3800         SetSsaNum(snum);
3801     }
3802
3803 #if DEBUGGABLE_GENTREE
3804     GenTreePhiArg() : GenTreeLclVarCommon() {}
3805 #endif
3806 };
3807
3808 /* gtPutArgStk -- Argument passed on stack */
3809
3810 struct GenTreePutArgStk: public GenTreeUnOp
3811 {
3812     unsigned gtSlotNum;        // Slot number of the argument to be passed on stack
3813
3814 #if FEATURE_FASTTAILCALL
3815     bool putInIncomingArgArea;    // Whether this arg needs to be placed in incoming arg area.
3816                                   // By default this is false and will be placed in out-going arg area.
3817                                   // Fast tail calls set this to true.
3818                                   // In future if we need to add more such bool fields consider bit fields.
3819
3820     GenTreePutArgStk(
3821             genTreeOps oper,
3822             var_types type,
3823             unsigned slotNum
3824             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3825             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct),
3826             bool _putInIncomingArgArea = false
3827             DEBUGARG(GenTreePtr callNode = NULL)
3828             DEBUGARG(bool largeNode = false))
3829         : 
3830         GenTreeUnOp(oper, type DEBUGARG(largeNode)),
3831         gtSlotNum(slotNum),
3832         putInIncomingArgArea(_putInIncomingArgArea)
3833 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3834         , gtPutArgStkKind(PutArgStkKindInvalid),
3835         gtNumSlots(numSlots),
3836         gtIsStruct(isStruct),
3837         gtNumberReferenceSlots(0),
3838         gtGcPtrs(nullptr)
3839 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3840     {
3841 #ifdef DEBUG
3842         gtCall = callNode;
3843 #endif
3844     }
3845
3846
3847     GenTreePutArgStk(
3848             genTreeOps oper,
3849             var_types type,
3850             GenTreePtr op1,
3851             unsigned slotNum
3852             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3853             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct),
3854             bool _putInIncomingArgArea = false
3855             DEBUGARG(GenTreePtr callNode = NULL)
3856             DEBUGARG(bool largeNode = false))
3857         :
3858         GenTreeUnOp(oper, type, op1 DEBUGARG(largeNode)), 
3859         gtSlotNum(slotNum),
3860         putInIncomingArgArea(_putInIncomingArgArea)
3861 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3862         , gtPutArgStkKind(PutArgStkKindInvalid),
3863         gtNumSlots(numSlots),
3864         gtIsStruct(isStruct),
3865         gtNumberReferenceSlots(0),
3866         gtGcPtrs(nullptr)
3867 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3868     {
3869 #ifdef DEBUG
3870         gtCall = callNode;
3871 #endif
3872     }
3873
3874 #else  // !FEATURE_FASTTAILCALL
3875
3876     GenTreePutArgStk(
3877             genTreeOps oper,
3878             var_types type,
3879             unsigned slotNum
3880             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3881             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct)
3882             DEBUGARG(GenTreePtr callNode = NULL)
3883             DEBUGARG(bool largeNode = false))
3884         :
3885         GenTreeUnOp(oper, type DEBUGARG(largeNode)),
3886         gtSlotNum(slotNum)
3887 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3888         , gtPutArgStkKind(PutArgStkKindInvalid),
3889         gtNumSlots(numSlots),
3890         gtIsStruct(isStruct),
3891         gtNumberReferenceSlots(0),
3892         gtGcPtrs(nullptr)
3893 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3894     {
3895 #ifdef DEBUG
3896         gtCall = callNode;
3897 #endif
3898     }
3899
3900
3901     GenTreePutArgStk(
3902             genTreeOps oper,
3903             var_types type,
3904             GenTreePtr op1,
3905             unsigned slotNum
3906             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3907             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct)
3908             DEBUGARG(GenTreePtr callNode = NULL)
3909             DEBUGARG(bool largeNode = false))
3910         :
3911         GenTreeUnOp(oper, type, op1 DEBUGARG(largeNode)), 
3912         gtSlotNum(slotNum)
3913 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3914         , gtPutArgStkKind(PutArgStkKindInvalid),
3915         gtNumSlots(numSlots),
3916         gtIsStruct(isStruct),
3917         gtNumberReferenceSlots(0),
3918         gtGcPtrs(nullptr)
3919 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3920     {
3921 #ifdef DEBUG
3922         gtCall = callNode;
3923 #endif
3924     }
3925 #endif // FEATURE_FASTTAILCALL
3926
3927     unsigned getArgOffset() { return gtSlotNum * TARGET_POINTER_SIZE; }
3928
3929 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3930     unsigned getArgSize() { return gtNumSlots * TARGET_POINTER_SIZE; }
3931 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3932
3933 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3934     //------------------------------------------------------------------------
3935     // setGcPointers: Sets the number of references and the layout of the struct object returned by the VM.
3936     //
3937     // Arguments:
3938     //    numPointers - Number of pointer references.
3939     //    pointers    - layout of the struct (with pointers marked.)
3940     //
3941     // Return Value:
3942     //    None
3943     //
3944     // Notes:
3945     //    This data is used in the codegen for GT_PUTARG_STK to decide how to copy the struct to the stack by value.
3946     //    If no pointer references are used, block copying instructions are used.
3947     //    Otherwise the pointer reference slots are copied atomically in a way that gcinfo is emitted.
3948     //    Any non pointer references between the pointer reference slots are copied in block fashion.
3949     //
3950     void setGcPointers(unsigned numPointers, BYTE* pointers)
3951     {
3952         gtNumberReferenceSlots = numPointers;
3953         gtGcPtrs = pointers;
3954     }
3955 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3956
3957 #ifdef DEBUG
3958     GenTreePtr      gtCall;                // the call node to which this argument belongs
3959 #endif
3960
3961 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3962     // Instruction selection: during codegen time, what code sequence we will be using
3963     // to encode this operation.
3964
3965     enum PutArgStkKind : __int8
3966     {
3967         PutArgStkKindInvalid,
3968         PutArgStkKindRepInstr,
3969         PutArgStkKindUnroll,
3970     };
3971
3972     PutArgStkKind gtPutArgStkKind;
3973
3974     unsigned gtNumSlots;              // Number of slots for the argument to be passed on stack
3975     bool     gtIsStruct;              // This stack arg is a struct.
3976     unsigned gtNumberReferenceSlots;  // Number of reference slots.
3977     BYTE*    gtGcPtrs;                // gcPointers
3978 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3979
3980 #if DEBUGGABLE_GENTREE
3981     GenTreePutArgStk() : GenTreeUnOp() {}
3982 #endif
3983 };
3984
3985 // Represents GT_COPY or GT_RELOAD node
3986 struct GenTreeCopyOrReload : public GenTreeUnOp
3987 {
3988     // State required to support copy/reload of a multi-reg call node.
3989     // First register is is always given by gtRegNum.
3990     //
3991 #if FEATURE_MULTIREG_RET
3992     regNumber gtOtherRegs[MAX_RET_REG_COUNT - 1];
3993 #endif
3994
3995     //----------------------------------------------------------
3996     // ClearOtherRegs: set gtOtherRegs to REG_NA.
3997     //
3998     // Arguments:
3999     //    None
4000     //
4001     // Return Value:
4002     //    None
4003     //
4004     void ClearOtherRegs()
4005     {
4006 #if FEATURE_MULTIREG_RET
4007         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
4008         {
4009             gtOtherRegs[i] = REG_NA;
4010         }
4011 #endif
4012     }
4013
4014     //-----------------------------------------------------------
4015     // GetRegNumByIdx: Get regNumber of ith position.
4016     //
4017     // Arguments:
4018     //    idx   -   register position.
4019     //
4020     // Return Value:
4021     //    Returns regNumber assigned to ith position.
4022     //
4023     regNumber GetRegNumByIdx(unsigned idx) const
4024     {
4025         assert(idx < MAX_RET_REG_COUNT);
4026
4027         if (idx == 0)
4028         {
4029             return gtRegNum;
4030         }
4031
4032 #if FEATURE_MULTIREG_RET
4033         return gtOtherRegs[idx - 1];
4034 #else
4035         return REG_NA;
4036 #endif
4037     }
4038
4039     //-----------------------------------------------------------
4040     // SetRegNumByIdx: Set the regNumber for ith position.
4041     //
4042     // Arguments:
4043     //    reg   -   reg number 
4044     //    idx   -   register position.
4045     //
4046     // Return Value:
4047     //    None.
4048     //
4049     void SetRegNumByIdx(regNumber reg, unsigned idx)
4050     {
4051         assert(idx < MAX_RET_REG_COUNT);
4052
4053         if (idx == 0)
4054         {
4055             gtRegNum = reg;
4056         }
4057 #if FEATURE_MULTIREG_RET
4058         else
4059         {
4060             gtOtherRegs[idx - 1] = reg;
4061             assert(gtOtherRegs[idx - 1] == reg);
4062         }
4063 #else
4064         else
4065         {
4066             unreached();
4067         }
4068 #endif
4069     }
4070
4071     //----------------------------------------------------------------------------
4072     // CopyOtherRegs: copy multi-reg state from the given copy/reload node to this
4073     // node.
4074     //
4075     // Arguments:
4076     //    from  -  GenTree node from which to copy multi-reg state
4077     //
4078     // Return Value:
4079     //    None
4080     //
4081     // TODO-ARM: Implement this routine for Arm64 and Arm32
4082     // TODO-X86: Implement this routine for x86
4083     void CopyOtherRegs(GenTreeCopyOrReload* from)
4084     {
4085         assert(OperGet() == from->OperGet());
4086
4087 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
4088         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
4089         {
4090             gtOtherRegs[i] = from->gtOtherRegs[i];
4091         }
4092 #endif
4093     }
4094
4095     GenTreeCopyOrReload(genTreeOps oper,
4096         var_types type,
4097         GenTree* op1) : GenTreeUnOp(oper, type, op1)
4098     {
4099         gtRegNum = REG_NA;
4100         ClearOtherRegs();
4101     }
4102
4103 #if DEBUGGABLE_GENTREE
4104     GenTreeCopyOrReload() : GenTreeUnOp() {}
4105 #endif
4106 };
4107
4108 //------------------------------------------------------------------------
4109 // Deferred inline functions of GenTree -- these need the subtypes above to
4110 // be defined already.
4111 //------------------------------------------------------------------------
4112
4113 //------------------------------------------------------------------------
4114 // IsFPZero: Checks whether this is a floating point constant with value 0.0
4115 //
4116 // Return Value:
4117 //    Returns true iff the tree is an GT_CNS_DBL, with value of 0.0.
4118
4119 inline bool GenTree::IsFPZero()
4120 {
4121     if ((gtOper == GT_CNS_DBL) && (gtDblCon.gtDconVal == 0.0))
4122         return true;
4123     return false;
4124 }
4125
4126 //------------------------------------------------------------------------
4127 // IsIntegralConst: Checks whether this is a constant node with the given value
4128 //
4129 // Arguments:
4130 //    constVal - the value of interest
4131 //
4132 // Return Value:
4133 //    Returns true iff the tree is an integral constant opcode, with
4134 //    the given value.
4135 //
4136 // Notes:
4137 //    Like gtIconVal, the argument is of ssize_t, so cannot check for
4138 //    long constants in a target-independent way.
4139
4140 inline bool GenTree::IsIntegralConst(ssize_t constVal)
4141
4142 {
4143     if ((gtOper == GT_CNS_INT) && (gtIntConCommon.IconValue() == constVal))
4144         return true;
4145
4146     if ((gtOper == GT_CNS_LNG) && (gtIntConCommon.LngValue() == constVal))
4147         return true;
4148
4149     return false;
4150 }
4151
4152 inline bool GenTree::IsBoxedValue()
4153 {
4154     assert(gtOper != GT_BOX || gtBox.BoxOp() != NULL);
4155     return (gtOper == GT_BOX) && (gtFlags & GTF_BOX_VALUE);
4156 }
4157
4158 inline GenTreePtr GenTree::MoveNext()
4159 {
4160     assert(IsList());
4161     return gtOp.gtOp2;
4162 }
4163
4164 #ifdef DEBUG
4165 //------------------------------------------------------------------------
4166 // IsListForMultiRegArg: Given an GenTree node that represents an argument
4167 //                       enforce (or don't enforce) the following invariant.
4168 //
4169 // For LEGACY_BACKEND or architectures that don't support MultiReg args
4170 // we don't allow a GT_LIST at all.
4171 //
4172 // Currently for AMD64 UNIX we allow a limited case where a GT_LIST is 
4173 // allowed but every element must be a GT_LCL_FLD.
4174 //
4175 // For the future targets that allow for Multireg args (and this includes
4176 //  the current ARM64 target) we allow a GT_LIST of arbitrary nodes, these
4177 //  would typically start out as GT_LCL_VARs or GT_LCL_FLDS or GT_INDs, 
4178 //  but could be changed into constants or GT_COMMA trees by the later 
4179 //  optimization phases.
4180 // 
4181 // Arguments:
4182 //    instance method for a GenTree node
4183 //
4184 // Return values:
4185 //    true:      the GenTree node is accepted as a valid argument
4186 //    false:     the GenTree node is not accepted as a valid argumeny
4187 //
4188 inline bool GenTree::IsListForMultiRegArg()
4189 {
4190     if (!IsList())
4191     {
4192         // We don't have a GT_LIST, so just return true.
4193         return true;
4194     }
4195     else  // We do have a GT_LIST
4196     {
4197 #if defined(LEGACY_BACKEND) || !FEATURE_MULTIREG_ARGS
4198
4199         // Not allowed to have a GT_LIST for an argument 
4200         // unless we have a RyuJIT backend and FEATURE_MULTIREG_ARGS
4201
4202         return false;
4203
4204 #else  // we have RyuJIT backend and FEATURE_MULTIREG_ARGS
4205
4206 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
4207         // For UNIX ABI we currently only allow a GT_LIST of GT_LCL_FLDs nodes 
4208         GenTree* gtListPtr = this;
4209         while (gtListPtr != nullptr) 
4210         {
4211             // ToDo: fix UNIX_AMD64 so that we do not generate this kind of a List
4212             //  Note the list as currently created is malformed, as the last entry is a nullptr
4213             if (gtListPtr->Current() == nullptr)
4214                 break;
4215
4216             // Only a list of GT_LCL_FLDs is allowed
4217             if (gtListPtr->Current()->OperGet() != GT_LCL_FLD)
4218             {
4219                 return false;
4220             }
4221             gtListPtr = gtListPtr->MoveNext();
4222         }
4223 #endif  // FEATURE_UNIX_AMD64_STRUCT_PASSING
4224
4225         // Note that for non-UNIX ABI the GT_LIST may contain any node
4226         //
4227         // We allow this GT_LIST as an argument 
4228         return true;
4229
4230 #endif  // RyuJIT backend and FEATURE_MULTIREG_ARGS
4231     }
4232 }
4233 #endif // DEBUG
4234
4235 inline GenTreePtr GenTree::Current()
4236 {
4237     assert(IsList());
4238     return gtOp.gtOp1;
4239 }
4240
4241 inline GenTreePtr *GenTree::pCurrent()
4242 {
4243     assert(IsList());
4244     return &(gtOp.gtOp1);
4245 }
4246
4247 inline GenTreePtr      GenTree::gtGetOp1() 
4248 {
4249     return gtOp.gtOp1;
4250 }
4251
4252 #ifdef DEBUG
4253 /* static */
4254 inline bool GenTree::RequiresNonNullOp2(genTreeOps oper)
4255 {
4256     switch (oper)
4257     {
4258     case GT_ADD:
4259     case GT_SUB:
4260     case GT_MUL:
4261     case GT_DIV:
4262     case GT_MOD:
4263     case GT_UDIV:
4264     case GT_UMOD:
4265     case GT_OR:
4266     case GT_XOR:
4267     case GT_AND:
4268     case GT_LSH:
4269     case GT_RSH:
4270     case GT_RSZ:
4271     case GT_ROL:
4272     case GT_ROR:
4273     case GT_INDEX:
4274     case GT_ASG:
4275     case GT_ASG_ADD:
4276     case GT_ASG_SUB:
4277     case GT_ASG_MUL:
4278     case GT_ASG_DIV:
4279     case GT_ASG_MOD:
4280     case GT_ASG_UDIV:
4281     case GT_ASG_UMOD:
4282     case GT_ASG_OR:
4283     case GT_ASG_XOR:
4284     case GT_ASG_AND:
4285     case GT_ASG_LSH:
4286     case GT_ASG_RSH:
4287     case GT_ASG_RSZ:
4288     case GT_EQ:
4289     case GT_NE:
4290     case GT_LT:
4291     case GT_LE:
4292     case GT_GE:
4293     case GT_GT:
4294     case GT_COMMA:
4295     case GT_QMARK:
4296     case GT_COLON:
4297     case GT_MKREFANY:
4298     case GT_INITBLK:
4299     case GT_COPYBLK:
4300         return true;
4301     default:
4302         return false;
4303     }
4304 }
4305 #endif // DEBUG
4306
4307 inline GenTreePtr      GenTree::gtGetOp2() 
4308 {
4309     /* gtOp.gtOp2 is only valid for GTK_BINOP nodes. */
4310
4311     GenTreePtr op2 = OperIsBinary() ? gtOp.gtOp2 : nullptr;
4312
4313     // This documents the genTreeOps for which gtOp.gtOp2 cannot be nullptr.
4314     // This helps prefix in its analyis of code which calls gtGetOp2()
4315
4316     assert((op2 != nullptr) || !RequiresNonNullOp2(gtOper));
4317
4318     return op2;
4319 }
4320
4321 inline GenTreePtr      GenTree::gtEffectiveVal(bool commaOnly)
4322 {
4323     switch (gtOper)
4324     {
4325     case GT_COMMA:
4326         return gtOp.gtOp2->gtEffectiveVal(commaOnly);
4327
4328     case GT_NOP:
4329         if (!commaOnly && gtOp.gtOp1 != NULL) 
4330             return gtOp.gtOp1->gtEffectiveVal();
4331         break;
4332
4333     default:
4334         break;
4335     }       
4336
4337     return this;
4338 }
4339
4340 inline GenTree*         GenTree::gtSkipReloadOrCopy()
4341 {
4342     // There can be only one reload or copy (we can't have a reload/copy of a reload/copy)
4343     if (gtOper == GT_RELOAD || gtOper == GT_COPY)
4344     {
4345         assert(gtGetOp1()->OperGet() != GT_RELOAD && gtGetOp1()->OperGet() != GT_COPY);
4346         return gtGetOp1();
4347     }
4348     return this;
4349 }
4350
4351 //-----------------------------------------------------------------------------------
4352 // IsMultiRegCall: whether a call node returning its value in more than one register
4353 //
4354 // Arguments:
4355 //     None
4356 //
4357 // Return Value:
4358 //     Returns true if this GenTree is a multi register returning call 
4359 inline bool  GenTree::IsMultiRegCall() const
4360 {
4361     if (this->IsCall())
4362     {
4363         // We cannot use AsCall() as it is not declared const
4364         const GenTreeCall* call = reinterpret_cast<const GenTreeCall *>(this);
4365         return call->HasMultiRegRetVal();
4366     }
4367
4368     return false;
4369 }
4370
4371 //-------------------------------------------------------------------------
4372 // IsCopyOrReload: whether this is a GT_COPY or GT_RELOAD node.
4373 //
4374 // Arguments:
4375 //     None
4376 //
4377 // Return Value:
4378 //     Returns true if this GenTree is a copy or reload node.
4379 inline bool GenTree::IsCopyOrReload() const
4380 {
4381     return (gtOper == GT_COPY || gtOper == GT_RELOAD);
4382 }
4383
4384 //-----------------------------------------------------------------------------------
4385 // IsCopyOrReloadOfMultiRegCall: whether this is a GT_COPY or GT_RELOAD of a multi-reg
4386 // call node.
4387 //
4388 // Arguments:
4389 //     None
4390 //
4391 // Return Value:
4392 //     Returns true if this GenTree is a copy or reload of multi-reg call node.
4393 inline bool GenTree::IsCopyOrReloadOfMultiRegCall() const
4394 {
4395     if (IsCopyOrReload())
4396     {
4397         GenTree* t = const_cast<GenTree*>(this);
4398         return t->gtGetOp1()->IsMultiRegCall();
4399     }
4400
4401     return false;
4402 }
4403
4404 inline bool GenTree::IsCnsIntOrI() const
4405 {
4406     return (gtOper == GT_CNS_INT);
4407 }
4408
4409 inline bool GenTree::IsIntegralConst() const
4410 {
4411 #ifdef _TARGET_64BIT_
4412     return IsCnsIntOrI();
4413 #else // !_TARGET_64BIT_
4414     return ((gtOper == GT_CNS_INT) || (gtOper == GT_CNS_LNG));
4415 #endif // !_TARGET_64BIT_
4416 }
4417
4418 inline bool GenTree::IsIntCnsFitsInI32()
4419 {
4420 #ifdef _TARGET_64BIT_
4421     return IsCnsIntOrI() && ((int)gtIntConCommon.IconValue() == gtIntConCommon.IconValue());
4422 #else // !_TARGET_64BIT_
4423     return IsCnsIntOrI();
4424 #endif // !_TARGET_64BIT_
4425 }
4426
4427 inline bool GenTree::IsCnsFltOrDbl() const
4428 {
4429     return OperGet() == GT_CNS_DBL;
4430 }
4431
4432 inline bool GenTree::IsCnsNonZeroFltOrDbl()
4433 {
4434     if (OperGet() == GT_CNS_DBL)
4435     {
4436         double constValue = gtDblCon.gtDconVal;
4437         return *(__int64*)&constValue != 0;
4438     }
4439
4440     return false;
4441 }
4442
4443 inline bool GenTree::IsHelperCall() { return OperGet() == GT_CALL && gtCall.gtCallType == CT_HELPER; }
4444
4445 inline var_types GenTree::CastFromType() { return this->gtCast.CastOp()->TypeGet(); }
4446 inline var_types& GenTree::CastToType()  { return this->gtCast.gtCastType; }
4447
4448
4449 /*****************************************************************************/
4450
4451 #ifndef _HOST_64BIT_
4452 #include <poppack.h>
4453 #endif
4454
4455 /*****************************************************************************/
4456
4457 #if     SMALL_TREE_NODES
4458
4459 // In debug, on some platforms (e.g., when LATE_DISASM is defined), GenTreeIntCon is bigger than GenTreeLclFld.
4460 const
4461 size_t              TREE_NODE_SZ_SMALL = max(sizeof(GenTreeIntCon), sizeof(GenTreeLclFld));
4462
4463 #endif // SMALL_TREE_NODES
4464
4465 const
4466 size_t              TREE_NODE_SZ_LARGE = sizeof(GenTreeCall);
4467
4468 /*****************************************************************************
4469  * Types returned by GenTree::lvaLclVarRefs()
4470  */
4471
4472 enum varRefKinds
4473 {
4474     VR_INVARIANT  = 0x00,      // an invariant value
4475     VR_NONE       = 0x00,
4476     VR_IND_REF    = 0x01,      // an object reference
4477     VR_IND_SCL    = 0x02,      // a non-object reference
4478     VR_GLB_VAR    = 0x04,      // a global (clsVar)
4479 };
4480 // Add a temp define to avoid merge conflict.
4481 #define VR_IND_PTR VR_IND_REF
4482
4483 /*****************************************************************************/
4484 #endif  // !GENTREE_H
4485 /*****************************************************************************/
4486