Merge pull request #21589 from CarolEidt/Fix21546
[platform/upstream/coreclr.git] / src / jit / gentree.cpp
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 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 #include "jitpch.h"
15 #include "hwintrinsic.h"
16 #include "simd.h"
17
18 #ifdef _MSC_VER
19 #pragma hdrstop
20 #endif
21
22 /*****************************************************************************/
23
24 const unsigned short GenTree::gtOperKindTable[] = {
25 #define GTNODE(en, st, cm, ok) ok + GTK_COMMUTE *cm,
26 #include "gtlist.h"
27 };
28
29 /*****************************************************************************
30  *
31  *  The types of different GenTree nodes
32  */
33
34 #ifdef DEBUG
35
36 #define INDENT_SIZE 3
37
38 //--------------------------------------------
39 //
40 // IndentStack: This struct is used, along with its related enums and strings,
41 //    to control both the indendtation and the printing of arcs.
42 //
43 // Notes:
44 //    The mode of printing is set in the Constructor, using its 'compiler' argument.
45 //    Currently it only prints arcs when fgOrder == fgOrderLinear.
46 //    The type of arc to print is specified by the IndentInfo enum, and is controlled
47 //    by the caller of the Push() method.
48
49 enum IndentChars
50 {
51     ICVertical,
52     ICBottom,
53     ICTop,
54     ICMiddle,
55     ICDash,
56     ICEmbedded,
57     ICTerminal,
58     ICError,
59     IndentCharCount
60 };
61
62 // clang-format off
63 // Sets of strings for different dumping options            vert             bot             top             mid             dash       embedded    terminal    error
64 static const char*  emptyIndents[IndentCharCount]   = {     " ",             " ",            " ",            " ",            " ",           "{",      "",        "?"  };
65 static const char*  asciiIndents[IndentCharCount]   = {     "|",            "\\",            "/",            "+",            "-",           "{",      "*",       "?"  };
66 static const char*  unicodeIndents[IndentCharCount] = { "\xe2\x94\x82", "\xe2\x94\x94", "\xe2\x94\x8c", "\xe2\x94\x9c", "\xe2\x94\x80",     "{", "\xe2\x96\x8c", "?"  };
67 // clang-format on
68
69 typedef ArrayStack<Compiler::IndentInfo> IndentInfoStack;
70 struct IndentStack
71 {
72     IndentInfoStack stack;
73     const char**    indents;
74
75     // Constructor for IndentStack.  Uses 'compiler' to determine the mode of printing.
76     IndentStack(Compiler* compiler) : stack(compiler->getAllocator(CMK_DebugOnly))
77     {
78         if (compiler->asciiTrees)
79         {
80             indents = asciiIndents;
81         }
82         else
83         {
84             indents = unicodeIndents;
85         }
86     }
87
88     // Return the depth of the current indentation.
89     unsigned Depth()
90     {
91         return stack.Height();
92     }
93
94     // Push a new indentation onto the stack, of the given type.
95     void Push(Compiler::IndentInfo info)
96     {
97         stack.Push(info);
98     }
99
100     // Pop the most recent indentation type off the stack.
101     Compiler::IndentInfo Pop()
102     {
103         return stack.Pop();
104     }
105
106     // Print the current indentation and arcs.
107     void print()
108     {
109         unsigned indentCount = Depth();
110         for (unsigned i = 0; i < indentCount; i++)
111         {
112             unsigned index = indentCount - 1 - i;
113             switch (stack.Index(index))
114             {
115                 case Compiler::IndentInfo::IINone:
116                     printf("   ");
117                     break;
118                 case Compiler::IndentInfo::IIEmbedded:
119                     printf("%s  ", indents[ICEmbedded]);
120                     break;
121                 case Compiler::IndentInfo::IIArc:
122                     if (index == 0)
123                     {
124                         printf("%s%s%s", indents[ICMiddle], indents[ICDash], indents[ICDash]);
125                     }
126                     else
127                     {
128                         printf("%s  ", indents[ICVertical]);
129                     }
130                     break;
131                 case Compiler::IndentInfo::IIArcBottom:
132                     printf("%s%s%s", indents[ICBottom], indents[ICDash], indents[ICDash]);
133                     break;
134                 case Compiler::IndentInfo::IIArcTop:
135                     printf("%s%s%s", indents[ICTop], indents[ICDash], indents[ICDash]);
136                     break;
137                 case Compiler::IndentInfo::IIError:
138                     printf("%s%s%s", indents[ICError], indents[ICDash], indents[ICDash]);
139                     break;
140                 default:
141                     unreached();
142             }
143         }
144         printf("%s", indents[ICTerminal]);
145     }
146 };
147
148 //------------------------------------------------------------------------
149 // printIndent: This is a static method which simply invokes the 'print'
150 //    method on its 'indentStack' argument.
151 //
152 // Arguments:
153 //    indentStack - specifies the information for the indentation & arcs to be printed
154 //
155 // Notes:
156 //    This method exists to localize the checking for the case where indentStack is null.
157
158 static void printIndent(IndentStack* indentStack)
159 {
160     if (indentStack == nullptr)
161     {
162         return;
163     }
164     indentStack->print();
165 }
166
167 #endif
168
169 #if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
170
171 static const char* opNames[] = {
172 #define GTNODE(en, st, cm, ok) #en,
173 #include "gtlist.h"
174 };
175
176 const char* GenTree::OpName(genTreeOps op)
177 {
178     assert((unsigned)op < _countof(opNames));
179
180     return opNames[op];
181 }
182
183 #endif
184
185 #if MEASURE_NODE_SIZE && SMALL_TREE_NODES
186
187 static const char* opStructNames[] = {
188 #define GTNODE(en, st, cm, ok) #st,
189 #include "gtlist.h"
190 };
191
192 const char* GenTree::OpStructName(genTreeOps op)
193 {
194     assert((unsigned)op < _countof(opStructNames));
195
196     return opStructNames[op];
197 }
198
199 #endif
200
201 /*****************************************************************************
202  *
203  *  When 'SMALL_TREE_NODES' is enabled, we allocate tree nodes in 2 different
204  *  sizes: 'TREE_NODE_SZ_SMALL' for most nodes and 'TREE_NODE_SZ_LARGE' for the
205  *  few nodes (such as calls) that have more fields and take up a lot more space.
206  */
207
208 #if SMALL_TREE_NODES
209
210 /* GT_COUNT'th oper is overloaded as 'undefined oper', so allocate storage for GT_COUNT'th oper also */
211 /* static */
212 unsigned char GenTree::s_gtNodeSizes[GT_COUNT + 1];
213
214 #if NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
215
216 unsigned char GenTree::s_gtTrueSizes[GT_COUNT + 1]{
217 #define GTNODE(en, st, cm, ok) sizeof(st),
218 #include "gtlist.h"
219 };
220
221 #endif // NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
222
223 #if COUNT_AST_OPERS
224 LONG GenTree::s_gtNodeCounts[GT_COUNT + 1] = {0};
225 #endif // COUNT_AST_OPERS
226
227 /* static */
228 void GenTree::InitNodeSize()
229 {
230     /* Set all sizes to 'small' first */
231
232     for (unsigned op = 0; op <= GT_COUNT; op++)
233     {
234         GenTree::s_gtNodeSizes[op] = TREE_NODE_SZ_SMALL;
235     }
236
237     // Now set all of the appropriate entries to 'large'
238     CLANG_FORMAT_COMMENT_ANCHOR;
239
240 // clang-format off
241 #if defined(FEATURE_HFA) || defined(UNIX_AMD64_ABI)
242     // On ARM32, ARM64 and System V for struct returning
243     // there is code that does GT_ASG-tree.CopyObj call.
244     // CopyObj is a large node and the GT_ASG is small, which triggers an exception.
245     GenTree::s_gtNodeSizes[GT_ASG]              = TREE_NODE_SZ_LARGE;
246     GenTree::s_gtNodeSizes[GT_RETURN]           = TREE_NODE_SZ_LARGE;
247 #endif // defined(FEATURE_HFA) || defined(UNIX_AMD64_ABI)
248
249     GenTree::s_gtNodeSizes[GT_CALL]             = TREE_NODE_SZ_LARGE;
250     GenTree::s_gtNodeSizes[GT_CAST]             = TREE_NODE_SZ_LARGE;
251     GenTree::s_gtNodeSizes[GT_FTN_ADDR]         = TREE_NODE_SZ_LARGE;
252     GenTree::s_gtNodeSizes[GT_BOX]              = TREE_NODE_SZ_LARGE;
253     GenTree::s_gtNodeSizes[GT_INDEX]            = TREE_NODE_SZ_LARGE;
254     GenTree::s_gtNodeSizes[GT_INDEX_ADDR]        = TREE_NODE_SZ_LARGE;
255     GenTree::s_gtNodeSizes[GT_ARR_BOUNDS_CHECK] = TREE_NODE_SZ_LARGE;
256 #ifdef FEATURE_SIMD
257     GenTree::s_gtNodeSizes[GT_SIMD_CHK] = TREE_NODE_SZ_LARGE;
258 #endif // FEATURE_SIMD
259 #ifdef FEATURE_HW_INTRINSICS
260     GenTree::s_gtNodeSizes[GT_HW_INTRINSIC_CHK] = TREE_NODE_SZ_LARGE;
261 #endif // FEATURE_HW_INTRINSICS
262
263     GenTree::s_gtNodeSizes[GT_ARR_ELEM]         = TREE_NODE_SZ_LARGE;
264     GenTree::s_gtNodeSizes[GT_ARR_INDEX]        = TREE_NODE_SZ_LARGE;
265     GenTree::s_gtNodeSizes[GT_ARR_OFFSET]       = TREE_NODE_SZ_LARGE;
266     GenTree::s_gtNodeSizes[GT_RET_EXPR]         = TREE_NODE_SZ_LARGE;
267     GenTree::s_gtNodeSizes[GT_OBJ]              = TREE_NODE_SZ_LARGE;
268     GenTree::s_gtNodeSizes[GT_FIELD]            = TREE_NODE_SZ_LARGE;
269     GenTree::s_gtNodeSizes[GT_STMT]             = TREE_NODE_SZ_LARGE;
270     GenTree::s_gtNodeSizes[GT_CMPXCHG]          = TREE_NODE_SZ_LARGE;
271     GenTree::s_gtNodeSizes[GT_QMARK]            = TREE_NODE_SZ_LARGE;
272     GenTree::s_gtNodeSizes[GT_LEA]              = TREE_NODE_SZ_LARGE;
273     GenTree::s_gtNodeSizes[GT_STORE_OBJ]        = TREE_NODE_SZ_LARGE;
274     GenTree::s_gtNodeSizes[GT_DYN_BLK]          = TREE_NODE_SZ_LARGE;
275     GenTree::s_gtNodeSizes[GT_STORE_DYN_BLK]    = TREE_NODE_SZ_LARGE;
276     GenTree::s_gtNodeSizes[GT_INTRINSIC]        = TREE_NODE_SZ_LARGE;
277     GenTree::s_gtNodeSizes[GT_ALLOCOBJ]         = TREE_NODE_SZ_LARGE;
278 #if USE_HELPERS_FOR_INT_DIV
279     GenTree::s_gtNodeSizes[GT_DIV]              = TREE_NODE_SZ_LARGE;
280     GenTree::s_gtNodeSizes[GT_UDIV]             = TREE_NODE_SZ_LARGE;
281     GenTree::s_gtNodeSizes[GT_MOD]              = TREE_NODE_SZ_LARGE;
282     GenTree::s_gtNodeSizes[GT_UMOD]             = TREE_NODE_SZ_LARGE;
283 #endif
284 #ifdef FEATURE_PUT_STRUCT_ARG_STK
285     // TODO-Throughput: This should not need to be a large node. The object info should be
286     // obtained from the child node.
287     GenTree::s_gtNodeSizes[GT_PUTARG_STK]       = TREE_NODE_SZ_LARGE;
288 #if FEATURE_ARG_SPLIT
289     GenTree::s_gtNodeSizes[GT_PUTARG_SPLIT]     = TREE_NODE_SZ_LARGE;
290 #endif // FEATURE_ARG_SPLIT
291 #endif // FEATURE_PUT_STRUCT_ARG_STK
292
293     assert(GenTree::s_gtNodeSizes[GT_RETURN] == GenTree::s_gtNodeSizes[GT_ASG]);
294
295     // This list of assertions should come to contain all GenTree subtypes that are declared
296     // "small".
297     assert(sizeof(GenTreeLclFld) <= GenTree::s_gtNodeSizes[GT_LCL_FLD]);
298     assert(sizeof(GenTreeLclVar) <= GenTree::s_gtNodeSizes[GT_LCL_VAR]);
299
300     static_assert_no_msg(sizeof(GenTree)             <= TREE_NODE_SZ_SMALL);
301     static_assert_no_msg(sizeof(GenTreeUnOp)         <= TREE_NODE_SZ_SMALL);
302     static_assert_no_msg(sizeof(GenTreeOp)           <= TREE_NODE_SZ_SMALL);
303     static_assert_no_msg(sizeof(GenTreeVal)          <= TREE_NODE_SZ_SMALL);
304     static_assert_no_msg(sizeof(GenTreeIntConCommon) <= TREE_NODE_SZ_SMALL);
305     static_assert_no_msg(sizeof(GenTreePhysReg)      <= TREE_NODE_SZ_SMALL);
306     static_assert_no_msg(sizeof(GenTreeJumpTable)    <= TREE_NODE_SZ_SMALL);
307     static_assert_no_msg(sizeof(GenTreeIntCon)       <= TREE_NODE_SZ_SMALL);
308     static_assert_no_msg(sizeof(GenTreeLngCon)       <= TREE_NODE_SZ_SMALL);
309     static_assert_no_msg(sizeof(GenTreeDblCon)       <= TREE_NODE_SZ_SMALL);
310     static_assert_no_msg(sizeof(GenTreeStrCon)       <= TREE_NODE_SZ_SMALL);
311     static_assert_no_msg(sizeof(GenTreeLclVarCommon) <= TREE_NODE_SZ_SMALL);
312     static_assert_no_msg(sizeof(GenTreeLclVar)       <= TREE_NODE_SZ_SMALL);
313     static_assert_no_msg(sizeof(GenTreeLclFld)       <= TREE_NODE_SZ_SMALL);
314     static_assert_no_msg(sizeof(GenTreeCC)           <= TREE_NODE_SZ_SMALL);
315     static_assert_no_msg(sizeof(GenTreeCast)         <= TREE_NODE_SZ_LARGE); // *** large node
316     static_assert_no_msg(sizeof(GenTreeBox)          <= TREE_NODE_SZ_LARGE); // *** large node
317     static_assert_no_msg(sizeof(GenTreeField)        <= TREE_NODE_SZ_LARGE); // *** large node
318     static_assert_no_msg(sizeof(GenTreeArgList)      <= TREE_NODE_SZ_SMALL);
319     static_assert_no_msg(sizeof(GenTreeFieldList)    <= TREE_NODE_SZ_SMALL);
320     static_assert_no_msg(sizeof(GenTreeColon)        <= TREE_NODE_SZ_SMALL);
321     static_assert_no_msg(sizeof(GenTreeCall)         <= TREE_NODE_SZ_LARGE); // *** large node
322     static_assert_no_msg(sizeof(GenTreeCmpXchg)      <= TREE_NODE_SZ_LARGE); // *** large node
323     static_assert_no_msg(sizeof(GenTreeFptrVal)      <= TREE_NODE_SZ_LARGE); // *** large node
324     static_assert_no_msg(sizeof(GenTreeQmark)        <= TREE_NODE_SZ_LARGE); // *** large node
325     static_assert_no_msg(sizeof(GenTreeIntrinsic)    <= TREE_NODE_SZ_LARGE); // *** large node
326     static_assert_no_msg(sizeof(GenTreeIndex)        <= TREE_NODE_SZ_LARGE); // *** large node
327     static_assert_no_msg(sizeof(GenTreeArrLen)       <= TREE_NODE_SZ_LARGE); // *** large node
328     static_assert_no_msg(sizeof(GenTreeBoundsChk)    <= TREE_NODE_SZ_LARGE); // *** large node
329     static_assert_no_msg(sizeof(GenTreeArrElem)      <= TREE_NODE_SZ_LARGE); // *** large node
330     static_assert_no_msg(sizeof(GenTreeArrIndex)     <= TREE_NODE_SZ_LARGE); // *** large node
331     static_assert_no_msg(sizeof(GenTreeArrOffs)      <= TREE_NODE_SZ_LARGE); // *** large node
332     static_assert_no_msg(sizeof(GenTreeIndir)        <= TREE_NODE_SZ_SMALL);
333     static_assert_no_msg(sizeof(GenTreeStoreInd)     <= TREE_NODE_SZ_SMALL);
334     static_assert_no_msg(sizeof(GenTreeAddrMode)     <= TREE_NODE_SZ_SMALL);
335     static_assert_no_msg(sizeof(GenTreeObj)          <= TREE_NODE_SZ_LARGE); // *** large node
336     static_assert_no_msg(sizeof(GenTreeBlk)          <= TREE_NODE_SZ_SMALL);
337     static_assert_no_msg(sizeof(GenTreeRetExpr)      <= TREE_NODE_SZ_LARGE); // *** large node
338     static_assert_no_msg(sizeof(GenTreeStmt)         <= TREE_NODE_SZ_LARGE); // *** large node
339     static_assert_no_msg(sizeof(GenTreeClsVar)       <= TREE_NODE_SZ_SMALL);
340     static_assert_no_msg(sizeof(GenTreeArgPlace)     <= TREE_NODE_SZ_SMALL);
341     static_assert_no_msg(sizeof(GenTreeLabel)        <= TREE_NODE_SZ_SMALL);
342     static_assert_no_msg(sizeof(GenTreePhiArg)       <= TREE_NODE_SZ_SMALL);
343     static_assert_no_msg(sizeof(GenTreeAllocObj)     <= TREE_NODE_SZ_LARGE); // *** large node
344 #ifndef FEATURE_PUT_STRUCT_ARG_STK
345     static_assert_no_msg(sizeof(GenTreePutArgStk)    <= TREE_NODE_SZ_SMALL);
346 #else  // FEATURE_PUT_STRUCT_ARG_STK
347     // TODO-Throughput: This should not need to be a large node. The object info should be
348     // obtained from the child node.
349     static_assert_no_msg(sizeof(GenTreePutArgStk)    <= TREE_NODE_SZ_LARGE);
350 #if FEATURE_ARG_SPLIT
351     static_assert_no_msg(sizeof(GenTreePutArgSplit)  <= TREE_NODE_SZ_LARGE);
352 #endif // FEATURE_ARG_SPLIT
353 #endif // FEATURE_PUT_STRUCT_ARG_STK
354
355 #ifdef FEATURE_SIMD
356     static_assert_no_msg(sizeof(GenTreeSIMD)         <= TREE_NODE_SZ_SMALL);
357 #endif // FEATURE_SIMD
358
359 #ifdef FEATURE_HW_INTRINSICS
360     static_assert_no_msg(sizeof(GenTreeHWIntrinsic)  <= TREE_NODE_SZ_SMALL);
361 #endif // FEATURE_HW_INTRINSICS
362     // clang-format on
363 }
364
365 size_t GenTree::GetNodeSize() const
366 {
367     return GenTree::s_gtNodeSizes[gtOper];
368 }
369
370 #ifdef DEBUG
371 bool GenTree::IsNodeProperlySized() const
372 {
373     size_t size;
374
375     if (gtDebugFlags & GTF_DEBUG_NODE_SMALL)
376     {
377         size = TREE_NODE_SZ_SMALL;
378     }
379     else
380     {
381         assert(gtDebugFlags & GTF_DEBUG_NODE_LARGE);
382         size = TREE_NODE_SZ_LARGE;
383     }
384
385     return GenTree::s_gtNodeSizes[gtOper] <= size;
386 }
387 #endif
388
389 #if SMALL_TREE_NODES
390 //------------------------------------------------------------------------
391 // ReplaceWith: replace this with the src node. The source must be an isolated node
392 //              and cannot be used after the replacement.
393 //
394 // Arguments:
395 //    src  - source tree, that replaces this.
396 //    comp - the compiler instance to transfer annotations for arrays.
397 //
398 void GenTree::ReplaceWith(GenTree* src, Compiler* comp)
399 {
400     // The source may be big only if the target is also a big node
401     assert((gtDebugFlags & GTF_DEBUG_NODE_LARGE) || GenTree::s_gtNodeSizes[src->gtOper] == TREE_NODE_SZ_SMALL);
402
403     // The check is effective only if nodes have been already threaded.
404     assert((src->gtPrev == nullptr) && (src->gtNext == nullptr));
405
406     RecordOperBashing(OperGet(), src->OperGet()); // nop unless NODEBASH_STATS is enabled
407
408     GenTree* prev = gtPrev;
409     GenTree* next = gtNext;
410     // The VTable pointer is copied intentionally here
411     memcpy((void*)this, (void*)src, src->GetNodeSize());
412     this->gtPrev = prev;
413     this->gtNext = next;
414
415 #ifdef DEBUG
416     gtSeqNum = 0;
417 #endif
418     // Transfer any annotations.
419     if (src->OperGet() == GT_IND && src->gtFlags & GTF_IND_ARR_INDEX)
420     {
421         ArrayInfo arrInfo;
422         bool      b = comp->GetArrayInfoMap()->Lookup(src, &arrInfo);
423         assert(b);
424         comp->GetArrayInfoMap()->Set(this, arrInfo);
425     }
426     DEBUG_DESTROY_NODE(src);
427 }
428
429 #endif
430
431 /*****************************************************************************
432  *
433  *  When 'NODEBASH_STATS' is enabled in "jit.h" we record all instances of
434  *  an existing GenTree node having its operator changed. This can be useful
435  *  for two (related) things - to see what is being bashed (and what isn't),
436  *  and to verify that the existing choices for what nodes are marked 'large'
437  *  are reasonable (to minimize "wasted" space).
438  *
439  *  And yes, the hash function / logic is simplistic, but it is conflict-free
440  *  and transparent for what we need.
441  */
442
443 #if NODEBASH_STATS
444
445 #define BASH_HASH_SIZE 211
446
447 inline unsigned hashme(genTreeOps op1, genTreeOps op2)
448 {
449     return ((op1 * 104729) ^ (op2 * 56569)) % BASH_HASH_SIZE;
450 }
451
452 struct BashHashDsc
453 {
454     unsigned __int32 bhFullHash; // the hash value (unique for all old->new pairs)
455     unsigned __int32 bhCount;    // the same old->new bashings seen so far
456     unsigned __int8  bhOperOld;  // original gtOper
457     unsigned __int8  bhOperNew;  // new      gtOper
458 };
459
460 static BashHashDsc BashHash[BASH_HASH_SIZE];
461
462 void GenTree::RecordOperBashing(genTreeOps operOld, genTreeOps operNew)
463 {
464     unsigned     hash = hashme(operOld, operNew);
465     BashHashDsc* desc = BashHash + hash;
466
467     if (desc->bhFullHash != hash)
468     {
469         noway_assert(desc->bhCount == 0); // if this ever fires, need fix the hash fn
470         desc->bhFullHash = hash;
471     }
472
473     desc->bhCount += 1;
474     desc->bhOperOld = operOld;
475     desc->bhOperNew = operNew;
476 }
477
478 void GenTree::ReportOperBashing(FILE* f)
479 {
480     unsigned total = 0;
481
482     fflush(f);
483
484     fprintf(f, "\n");
485     fprintf(f, "Bashed gtOper stats:\n");
486     fprintf(f, "\n");
487     fprintf(f, "    Old operator        New operator     #bytes old->new      Count\n");
488     fprintf(f, "    ---------------------------------------------------------------\n");
489
490     for (unsigned h = 0; h < BASH_HASH_SIZE; h++)
491     {
492         unsigned count = BashHash[h].bhCount;
493         if (count == 0)
494             continue;
495
496         unsigned opOld = BashHash[h].bhOperOld;
497         unsigned opNew = BashHash[h].bhOperNew;
498
499         fprintf(f, "    GT_%-13s -> GT_%-13s [size: %3u->%3u] %c %7u\n", OpName((genTreeOps)opOld),
500                 OpName((genTreeOps)opNew), s_gtTrueSizes[opOld], s_gtTrueSizes[opNew],
501                 (s_gtTrueSizes[opOld] < s_gtTrueSizes[opNew]) ? 'X' : ' ', count);
502         total += count;
503     }
504     fprintf(f, "\n");
505     fprintf(f, "Total bashings: %u\n", total);
506     fprintf(f, "\n");
507
508     fflush(f);
509 }
510
511 #endif // NODEBASH_STATS
512
513 #else // SMALL_TREE_NODES
514
515 #ifdef DEBUG
516 bool GenTree::IsNodeProperlySized() const
517 {
518     return true;
519 }
520 #endif
521
522 #endif // SMALL_TREE_NODES
523
524 /*****************************************************************************/
525
526 #if MEASURE_NODE_SIZE
527
528 void GenTree::DumpNodeSizes(FILE* fp)
529 {
530 // Dump the sizes of the various GenTree flavors
531
532 #if SMALL_TREE_NODES
533     fprintf(fp, "Small tree node size = %3u bytes\n", TREE_NODE_SZ_SMALL);
534 #endif
535     fprintf(fp, "Large tree node size = %3u bytes\n", TREE_NODE_SZ_LARGE);
536     fprintf(fp, "\n");
537
538 #if SMALL_TREE_NODES
539
540     // Verify that node sizes are set kosherly and dump sizes
541     for (unsigned op = GT_NONE + 1; op < GT_COUNT; op++)
542     {
543         unsigned needSize = s_gtTrueSizes[op];
544         unsigned nodeSize = s_gtNodeSizes[op];
545
546         const char* structNm = OpStructName((genTreeOps)op);
547         const char* operName = OpName((genTreeOps)op);
548
549         bool repeated = false;
550
551         // Have we seen this struct flavor before?
552         for (unsigned mop = GT_NONE + 1; mop < op; mop++)
553         {
554             if (strcmp(structNm, OpStructName((genTreeOps)mop)) == 0)
555             {
556                 repeated = true;
557                 break;
558             }
559         }
560
561         // Don't repeat the same GenTree flavor unless we have an error
562         if (!repeated || needSize > nodeSize)
563         {
564             unsigned sizeChar = '?';
565
566             if (nodeSize == TREE_NODE_SZ_SMALL)
567                 sizeChar = 'S';
568             else if (nodeSize == TREE_NODE_SZ_LARGE)
569                 sizeChar = 'L';
570
571             fprintf(fp, "GT_%-16s ... %-19s = %3u bytes (%c)", operName, structNm, needSize, sizeChar);
572             if (needSize > nodeSize)
573             {
574                 fprintf(fp, " -- ERROR -- allocation is only %u bytes!", nodeSize);
575             }
576             else if (needSize <= TREE_NODE_SZ_SMALL && nodeSize == TREE_NODE_SZ_LARGE)
577             {
578                 fprintf(fp, " ... could be small");
579             }
580
581             fprintf(fp, "\n");
582         }
583     }
584
585 #endif
586 }
587
588 #endif // MEASURE_NODE_SIZE
589
590 /*****************************************************************************
591  *
592  *  Walk all basic blocks and call the given function pointer for all tree
593  *  nodes contained therein.
594  */
595
596 void Compiler::fgWalkAllTreesPre(fgWalkPreFn* visitor, void* pCallBackData)
597 {
598     BasicBlock* block;
599
600     for (block = fgFirstBB; block; block = block->bbNext)
601     {
602         GenTree* tree;
603
604         for (tree = block->bbTreeList; tree; tree = tree->gtNext)
605         {
606             assert(tree->gtOper == GT_STMT);
607
608             fgWalkTreePre(&tree->gtStmt.gtStmtExpr, visitor, pCallBackData);
609         }
610     }
611 }
612
613 //-----------------------------------------------------------
614 // CopyReg: Copy the _gtRegNum/gtRegTag fields.
615 //
616 // Arguments:
617 //     from   -  GenTree node from which to copy
618 //
619 // Return Value:
620 //     None
621 void GenTree::CopyReg(GenTree* from)
622 {
623     _gtRegNum = from->_gtRegNum;
624     INDEBUG(gtRegTag = from->gtRegTag;)
625
626     // Also copy multi-reg state if this is a call node
627     if (IsCall())
628     {
629         assert(from->IsCall());
630         this->AsCall()->CopyOtherRegs(from->AsCall());
631     }
632     else if (IsCopyOrReload())
633     {
634         this->AsCopyOrReload()->CopyOtherRegs(from->AsCopyOrReload());
635     }
636 }
637
638 //------------------------------------------------------------------
639 // gtHasReg: Whether node beeen assigned a register by LSRA
640 //
641 // Arguments:
642 //    None
643 //
644 // Return Value:
645 //    Returns true if the node was assigned a register.
646 //
647 //    In case of multi-reg call nodes, it is considered
648 //    having a reg if regs are allocated for all its
649 //    return values.
650 //
651 //    In case of GT_COPY or GT_RELOAD of a multi-reg call,
652 //    GT_COPY/GT_RELOAD is considered having a reg if it
653 //    has a reg assigned to any of its positions.
654 //
655 // Assumption:
656 //    In order for this to work properly, gtClearReg must be called
657 //    prior to setting the register value.
658 //
659 bool GenTree::gtHasReg() const
660 {
661     bool hasReg;
662
663     if (IsMultiRegCall())
664     {
665         // Have to cast away const-ness because GetReturnTypeDesc() is a non-const method
666         GenTree*     tree     = const_cast<GenTree*>(this);
667         GenTreeCall* call     = tree->AsCall();
668         unsigned     regCount = call->GetReturnTypeDesc()->GetReturnRegCount();
669         hasReg                = false;
670
671         // A Multi-reg call node is said to have regs, if it has
672         // reg assigned to each of its result registers.
673         for (unsigned i = 0; i < regCount; ++i)
674         {
675             hasReg = (call->GetRegNumByIdx(i) != REG_NA);
676             if (!hasReg)
677             {
678                 break;
679             }
680         }
681     }
682     else if (IsCopyOrReloadOfMultiRegCall())
683     {
684         GenTree*             tree         = const_cast<GenTree*>(this);
685         GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload();
686         GenTreeCall*         call         = copyOrReload->gtGetOp1()->AsCall();
687         unsigned             regCount     = call->GetReturnTypeDesc()->GetReturnRegCount();
688         hasReg                            = false;
689
690         // A Multi-reg copy or reload node is said to have regs,
691         // if it has valid regs in any of the positions.
692         for (unsigned i = 0; i < regCount; ++i)
693         {
694             hasReg = (copyOrReload->GetRegNumByIdx(i) != REG_NA);
695             if (hasReg)
696             {
697                 break;
698             }
699         }
700     }
701     else
702     {
703         hasReg = (gtRegNum != REG_NA);
704     }
705
706     return hasReg;
707 }
708
709 //-----------------------------------------------------------------------------
710 // GetRegisterDstCount: Get the number of registers defined by the node.
711 //
712 // Arguments:
713 //    None
714 //
715 // Return Value:
716 //    The number of registers that this node defines.
717 //
718 // Notes:
719 //    This should not be called on a contained node.
720 //    This does not look at the actual register assignments, if any, and so
721 //    is valid after Lowering.
722 //
723 int GenTree::GetRegisterDstCount() const
724 {
725     assert(!isContained());
726     if (!IsMultiRegNode())
727     {
728         return (IsValue()) ? 1 : 0;
729     }
730     else if (IsMultiRegCall())
731     {
732         // temporarily cast away const-ness as AsCall() method is not declared const
733         GenTree* temp = const_cast<GenTree*>(this);
734         return temp->AsCall()->GetReturnTypeDesc()->GetReturnRegCount();
735     }
736     else if (IsCopyOrReload())
737     {
738         return gtGetOp1()->GetRegisterDstCount();
739     }
740 #if FEATURE_ARG_SPLIT
741     else if (OperIsPutArgSplit())
742     {
743         return (const_cast<GenTree*>(this))->AsPutArgSplit()->gtNumRegs;
744     }
745 #endif
746 #if !defined(_TARGET_64BIT_)
747     else if (OperIsMultiRegOp())
748     {
749         // A MultiRegOp is a GT_MUL_LONG, GT_PUTARG_REG, or GT_BITCAST.
750         // For the latter two (ARM-only), they only have multiple registers if they produce a long value
751         // (GT_MUL_LONG always produces a long value).
752         CLANG_FORMAT_COMMENT_ANCHOR;
753 #ifdef _TARGET_ARM_
754         return (TypeGet() == TYP_LONG) ? 2 : 1;
755 #else
756         assert(OperIs(GT_MUL_LONG));
757         return 2;
758 #endif
759     }
760 #endif
761     assert(!"Unexpected multi-reg node");
762     return 0;
763 }
764
765 //---------------------------------------------------------------
766 // gtGetRegMask: Get the reg mask of the node.
767 //
768 // Arguments:
769 //    None
770 //
771 // Return Value:
772 //    Reg Mask of GenTree node.
773 //
774 regMaskTP GenTree::gtGetRegMask() const
775 {
776     regMaskTP resultMask;
777
778     if (IsMultiRegCall())
779     {
780         // temporarily cast away const-ness as AsCall() method is not declared const
781         resultMask    = genRegMask(gtRegNum);
782         GenTree* temp = const_cast<GenTree*>(this);
783         resultMask |= temp->AsCall()->GetOtherRegMask();
784     }
785     else if (IsCopyOrReloadOfMultiRegCall())
786     {
787         // A multi-reg copy or reload, will have valid regs for only those
788         // positions that need to be copied or reloaded.  Hence we need
789         // to consider only those registers for computing reg mask.
790
791         GenTree*             tree         = const_cast<GenTree*>(this);
792         GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload();
793         GenTreeCall*         call         = copyOrReload->gtGetOp1()->AsCall();
794         unsigned             regCount     = call->GetReturnTypeDesc()->GetReturnRegCount();
795
796         resultMask = RBM_NONE;
797         for (unsigned i = 0; i < regCount; ++i)
798         {
799             regNumber reg = copyOrReload->GetRegNumByIdx(i);
800             if (reg != REG_NA)
801             {
802                 resultMask |= genRegMask(reg);
803             }
804         }
805     }
806 #if FEATURE_ARG_SPLIT
807     else if (OperIsPutArgSplit())
808     {
809         GenTree*            tree     = const_cast<GenTree*>(this);
810         GenTreePutArgSplit* splitArg = tree->AsPutArgSplit();
811         unsigned            regCount = splitArg->gtNumRegs;
812
813         resultMask = RBM_NONE;
814         for (unsigned i = 0; i < regCount; ++i)
815         {
816             regNumber reg = splitArg->GetRegNumByIdx(i);
817             assert(reg != REG_NA);
818             resultMask |= genRegMask(reg);
819         }
820     }
821 #endif // FEATURE_ARG_SPLIT
822     else
823     {
824         resultMask = genRegMask(gtRegNum);
825     }
826
827     return resultMask;
828 }
829
830 //---------------------------------------------------------------
831 // GetOtherRegMask: Get the reg mask of gtOtherRegs of call node
832 //
833 // Arguments:
834 //    None
835 //
836 // Return Value:
837 //    Reg mask of gtOtherRegs of call node.
838 //
839 regMaskTP GenTreeCall::GetOtherRegMask() const
840 {
841     regMaskTP resultMask = RBM_NONE;
842
843 #if FEATURE_MULTIREG_RET
844     for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
845     {
846         if (gtOtherRegs[i] != REG_NA)
847         {
848             resultMask |= genRegMask((regNumber)gtOtherRegs[i]);
849             continue;
850         }
851         break;
852     }
853 #endif
854
855     return resultMask;
856 }
857
858 //-------------------------------------------------------------------------
859 // IsPure:
860 //    Returns true if this call is pure. For now, this uses the same
861 //    definition of "pure" that is that used by HelperCallProperties: a
862 //    pure call does not read or write any aliased (e.g. heap) memory or
863 //    have other global side effects (e.g. class constructors, finalizers),
864 //    but is allowed to throw an exception.
865 //
866 //    NOTE: this call currently only returns true if the call target is a
867 //    helper method that is known to be pure. No other analysis is
868 //    performed.
869 //
870 // Arguments:
871 //    Copiler - the compiler context.
872 //
873 // Returns:
874 //    True if the call is pure; false otherwise.
875 //
876 bool GenTreeCall::IsPure(Compiler* compiler) const
877 {
878     return (gtCallType == CT_HELPER) &&
879            compiler->s_helperCallProperties.IsPure(compiler->eeGetHelperNum(gtCallMethHnd));
880 }
881
882 //-------------------------------------------------------------------------
883 // HasSideEffects:
884 //    Returns true if this call has any side effects. All non-helpers are considered to have side-effects. Only helpers
885 //    that do not mutate the heap, do not run constructors, may not throw, and are either a) pure or b) non-finalizing
886 //    allocation functions are considered side-effect-free.
887 //
888 // Arguments:
889 //     compiler         - the compiler instance
890 //     ignoreExceptions - when `true`, ignores exception side effects
891 //     ignoreCctors     - when `true`, ignores class constructor side effects
892 //
893 // Return Value:
894 //      true if this call has any side-effects; false otherwise.
895 bool GenTreeCall::HasSideEffects(Compiler* compiler, bool ignoreExceptions, bool ignoreCctors) const
896 {
897     // Generally all GT_CALL nodes are considered to have side-effects, but we may have extra information about helper
898     // calls that can prove them side-effect-free.
899     if (gtCallType != CT_HELPER)
900     {
901         return true;
902     }
903
904     CorInfoHelpFunc       helper           = compiler->eeGetHelperNum(gtCallMethHnd);
905     HelperCallProperties& helperProperties = compiler->s_helperCallProperties;
906
907     // We definitely care about the side effects if MutatesHeap is true
908     if (helperProperties.MutatesHeap(helper))
909     {
910         return true;
911     }
912
913     // Unless we have been instructed to ignore cctors (CSE, for example, ignores cctors), consider them side effects.
914     if (!ignoreCctors && helperProperties.MayRunCctor(helper))
915     {
916         return true;
917     }
918
919     // If we also care about exceptions then check if the helper can throw
920     if (!ignoreExceptions && !helperProperties.NoThrow(helper))
921     {
922         return true;
923     }
924
925     // If this is not a Pure helper call or an allocator (that will not need to run a finalizer)
926     // then this call has side effects.
927     return !helperProperties.IsPure(helper) &&
928            (!helperProperties.IsAllocator(helper) || helperProperties.MayFinalize(helper));
929 }
930
931 //-------------------------------------------------------------------------
932 // HasNonStandardAddedArgs: Return true if the method has non-standard args added to the call
933 // argument list during argument morphing (fgMorphArgs), e.g., passed in R10 or R11 on AMD64.
934 // See also GetNonStandardAddedArgCount().
935 //
936 // Arguments:
937 //     compiler - the compiler instance
938 //
939 // Return Value:
940 //      true if there are any such args, false otherwise.
941 //
942 bool GenTreeCall::HasNonStandardAddedArgs(Compiler* compiler) const
943 {
944     return GetNonStandardAddedArgCount(compiler) != 0;
945 }
946
947 //-------------------------------------------------------------------------
948 // GetNonStandardAddedArgCount: Get the count of non-standard arguments that have been added
949 // during call argument morphing (fgMorphArgs). Do not count non-standard args that are already
950 // counted in the argument list prior to morphing.
951 //
952 // This function is used to help map the caller and callee arguments during tail call setup.
953 //
954 // Arguments:
955 //     compiler - the compiler instance
956 //
957 // Return Value:
958 //      The count of args, as described.
959 //
960 // Notes:
961 //      It would be more general to have fgMorphArgs set a bit on the call node when such
962 //      args are added to a call, and a bit on each such arg, and then have this code loop
963 //      over the call args when the special call bit is set, counting the args with the special
964 //      arg bit. This seems pretty heavyweight, though. Instead, this logic needs to be kept
965 //      in sync with fgMorphArgs.
966 //
967 int GenTreeCall::GetNonStandardAddedArgCount(Compiler* compiler) const
968 {
969     if (IsUnmanaged() && !compiler->opts.ShouldUsePInvokeHelpers())
970     {
971         // R11 = PInvoke cookie param
972         return 1;
973     }
974     else if (IsVirtualStub())
975     {
976         // R11 = Virtual stub param
977         return 1;
978     }
979     else if ((gtCallType == CT_INDIRECT) && (gtCallCookie != nullptr))
980     {
981         // R10 = PInvoke target param
982         // R11 = PInvoke cookie param
983         return 2;
984     }
985     return 0;
986 }
987
988 //-------------------------------------------------------------------------
989 // TreatAsHasRetBufArg:
990 //
991 // Arguments:
992 //     compiler, the compiler instance so that we can call eeGetHelperNum
993 //
994 // Return Value:
995 //     Returns true if we treat the call as if it has a retBuf argument
996 //     This method may actually have a retBuf argument
997 //     or it could be a JIT helper that we are still transforming during
998 //     the importer phase.
999 //
1000 // Notes:
1001 //     On ARM64 marking the method with the GTF_CALL_M_RETBUFFARG flag
1002 //     will make HasRetBufArg() return true, but will also force the
1003 //     use of register x8 to pass the RetBuf argument.
1004 //
1005 //     These two Jit Helpers that we handle here by returning true
1006 //     aren't actually defined to return a struct, so they don't expect
1007 //     their RetBuf to be passed in x8, instead they  expect it in x0.
1008 //
1009 bool GenTreeCall::TreatAsHasRetBufArg(Compiler* compiler) const
1010 {
1011     if (HasRetBufArg())
1012     {
1013         return true;
1014     }
1015     else
1016     {
1017         // If we see a Jit helper call that returns a TYP_STRUCT we will
1018         // transform it as if it has a Return Buffer Argument
1019         //
1020         if (IsHelperCall() && (gtReturnType == TYP_STRUCT))
1021         {
1022             // There are two possible helper calls that use this path:
1023             //  CORINFO_HELP_GETFIELDSTRUCT and CORINFO_HELP_UNBOX_NULLABLE
1024             //
1025             CorInfoHelpFunc helpFunc = compiler->eeGetHelperNum(gtCallMethHnd);
1026
1027             if (helpFunc == CORINFO_HELP_GETFIELDSTRUCT)
1028             {
1029                 return true;
1030             }
1031             else if (helpFunc == CORINFO_HELP_UNBOX_NULLABLE)
1032             {
1033                 return true;
1034             }
1035             else
1036             {
1037                 assert(!"Unexpected JIT helper in TreatAsHasRetBufArg");
1038             }
1039         }
1040     }
1041     return false;
1042 }
1043
1044 //-------------------------------------------------------------------------
1045 // IsHelperCall: Determine if this GT_CALL node is a specific helper call.
1046 //
1047 // Arguments:
1048 //     compiler - the compiler instance so that we can call eeFindHelper
1049 //
1050 // Return Value:
1051 //     Returns true if this GT_CALL node is a call to the specified helper.
1052 //
1053 bool GenTreeCall::IsHelperCall(Compiler* compiler, unsigned helper) const
1054 {
1055     return IsHelperCall(compiler->eeFindHelper(helper));
1056 }
1057
1058 //------------------------------------------------------------------------
1059 // GenTreeCall::ReplaceCallOperand:
1060 //    Replaces a given operand to a call node and updates the call
1061 //    argument table if necessary.
1062 //
1063 // Arguments:
1064 //    useEdge - the use edge that points to the operand to be replaced.
1065 //    replacement - the replacement node.
1066 //
1067 void GenTreeCall::ReplaceCallOperand(GenTree** useEdge, GenTree* replacement)
1068 {
1069     assert(useEdge != nullptr);
1070     assert(replacement != nullptr);
1071     assert(TryGetUse(*useEdge, &useEdge));
1072
1073     GenTree* originalOperand = *useEdge;
1074     *useEdge                 = replacement;
1075
1076     const bool isArgument =
1077         (replacement != gtControlExpr) &&
1078         ((gtCallType != CT_INDIRECT) || ((replacement != gtCallCookie) && (replacement != gtCallAddr)));
1079
1080     if (isArgument)
1081     {
1082         if ((originalOperand->gtFlags & GTF_LATE_ARG) != 0)
1083         {
1084             replacement->gtFlags |= GTF_LATE_ARG;
1085         }
1086         else
1087         {
1088             assert((replacement->gtFlags & GTF_LATE_ARG) == 0);
1089
1090             fgArgTabEntry* fp = Compiler::gtArgEntryByNode(this, originalOperand);
1091             assert(fp->node == originalOperand);
1092             fp->node = replacement;
1093         }
1094     }
1095 }
1096
1097 //-------------------------------------------------------------------------
1098 // AreArgsComplete: Determine if this GT_CALL node's arguments have been processed.
1099 //
1100 // Return Value:
1101 //     Returns true if fgMorphArgs has processed the arguments.
1102 //
1103 bool GenTreeCall::AreArgsComplete() const
1104 {
1105     if (fgArgInfo == nullptr)
1106     {
1107         return false;
1108     }
1109     if (fgArgInfo->AreArgsComplete())
1110     {
1111         assert((gtCallLateArgs != nullptr) || !fgArgInfo->HasRegArgs());
1112         return true;
1113     }
1114     assert(gtCallArgs == nullptr);
1115     return false;
1116 }
1117
1118 #if !defined(FEATURE_PUT_STRUCT_ARG_STK)
1119 unsigned GenTreePutArgStk::getArgSize()
1120 {
1121     return genTypeSize(genActualType(gtOp1->gtType));
1122 }
1123 #endif // !defined(FEATURE_PUT_STRUCT_ARG_STK)
1124
1125 /*****************************************************************************
1126  *
1127  *  Returns non-zero if the two trees are identical.
1128  */
1129
1130 bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK)
1131 {
1132     genTreeOps oper;
1133     unsigned   kind;
1134
1135 //  printf("tree1:\n"); gtDispTree(op1);
1136 //  printf("tree2:\n"); gtDispTree(op2);
1137
1138 AGAIN:
1139
1140     if (op1 == nullptr)
1141     {
1142         return (op2 == nullptr);
1143     }
1144     if (op2 == nullptr)
1145     {
1146         return false;
1147     }
1148     if (op1 == op2)
1149     {
1150         return true;
1151     }
1152
1153     assert(op1->gtOper != GT_STMT);
1154     assert(op2->gtOper != GT_STMT);
1155
1156     oper = op1->OperGet();
1157
1158     /* The operators must be equal */
1159
1160     if (oper != op2->gtOper)
1161     {
1162         return false;
1163     }
1164
1165     /* The types must be equal */
1166
1167     if (op1->gtType != op2->gtType)
1168     {
1169         return false;
1170     }
1171
1172     /* Overflow must be equal */
1173     if (op1->gtOverflowEx() != op2->gtOverflowEx())
1174     {
1175         return false;
1176     }
1177
1178     /* Sensible flags must be equal */
1179     if ((op1->gtFlags & (GTF_UNSIGNED)) != (op2->gtFlags & (GTF_UNSIGNED)))
1180     {
1181         return false;
1182     }
1183
1184     /* Figure out what kind of nodes we're comparing */
1185
1186     kind = op1->OperKind();
1187
1188     /* Is this a constant node? */
1189
1190     if (kind & GTK_CONST)
1191     {
1192         switch (oper)
1193         {
1194             case GT_CNS_INT:
1195                 if (op1->gtIntCon.gtIconVal == op2->gtIntCon.gtIconVal)
1196                 {
1197                     return true;
1198                 }
1199                 break;
1200 #if 0
1201             // TODO-CQ: Enable this in the future
1202         case GT_CNS_LNG:
1203             if  (op1->gtLngCon.gtLconVal == op2->gtLngCon.gtLconVal)
1204                 return true;
1205             break;
1206
1207         case GT_CNS_DBL:
1208             if  (op1->gtDblCon.gtDconVal == op2->gtDblCon.gtDconVal)
1209                 return true;
1210             break;
1211 #endif
1212             default:
1213                 break;
1214         }
1215
1216         return false;
1217     }
1218
1219     /* Is this a leaf node? */
1220
1221     if (kind & GTK_LEAF)
1222     {
1223         switch (oper)
1224         {
1225             case GT_LCL_VAR:
1226                 if (op1->gtLclVarCommon.gtLclNum != op2->gtLclVarCommon.gtLclNum)
1227                 {
1228                     break;
1229                 }
1230
1231                 return true;
1232
1233             case GT_LCL_FLD:
1234                 if (op1->gtLclFld.gtLclNum != op2->gtLclFld.gtLclNum ||
1235                     op1->gtLclFld.gtLclOffs != op2->gtLclFld.gtLclOffs)
1236                 {
1237                     break;
1238                 }
1239
1240                 return true;
1241
1242             case GT_CLS_VAR:
1243                 if (op1->gtClsVar.gtClsVarHnd != op2->gtClsVar.gtClsVarHnd)
1244                 {
1245                     break;
1246                 }
1247
1248                 return true;
1249
1250             case GT_LABEL:
1251                 return true;
1252
1253             case GT_ARGPLACE:
1254                 if ((op1->gtType == TYP_STRUCT) &&
1255                     (op1->gtArgPlace.gtArgPlaceClsHnd != op2->gtArgPlace.gtArgPlaceClsHnd))
1256                 {
1257                     break;
1258                 }
1259                 return true;
1260
1261             default:
1262                 break;
1263         }
1264
1265         return false;
1266     }
1267
1268     /* Is it a 'simple' unary/binary operator? */
1269
1270     if (kind & GTK_UNOP)
1271     {
1272         if (IsExOp(kind))
1273         {
1274             // ExOp operators extend unary operator with extra, non-GenTree* members.  In many cases,
1275             // these should be included in the comparison.
1276             switch (oper)
1277             {
1278                 case GT_ARR_LENGTH:
1279                     if (op1->gtArrLen.ArrLenOffset() != op2->gtArrLen.ArrLenOffset())
1280                     {
1281                         return false;
1282                     }
1283                     break;
1284                 case GT_CAST:
1285                     if (op1->gtCast.gtCastType != op2->gtCast.gtCastType)
1286                     {
1287                         return false;
1288                     }
1289                     break;
1290                 case GT_OBJ:
1291                     if (op1->AsObj()->gtClass != op2->AsObj()->gtClass)
1292                     {
1293                         return false;
1294                     }
1295                     break;
1296
1297                 // For the ones below no extra argument matters for comparison.
1298                 case GT_BOX:
1299                 case GT_RUNTIMELOOKUP:
1300                     break;
1301
1302                 default:
1303                     assert(!"unexpected unary ExOp operator");
1304             }
1305         }
1306         return Compare(op1->gtOp.gtOp1, op2->gtOp.gtOp1);
1307     }
1308
1309     if (kind & GTK_BINOP)
1310     {
1311         if (IsExOp(kind))
1312         {
1313             // ExOp operators extend unary operator with extra, non-GenTree* members.  In many cases,
1314             // these should be included in the hash code.
1315             switch (oper)
1316             {
1317                 case GT_INTRINSIC:
1318                     if (op1->gtIntrinsic.gtIntrinsicId != op2->gtIntrinsic.gtIntrinsicId)
1319                     {
1320                         return false;
1321                     }
1322                     break;
1323                 case GT_LEA:
1324                     if (op1->gtAddrMode.gtScale != op2->gtAddrMode.gtScale)
1325                     {
1326                         return false;
1327                     }
1328                     if (op1->gtAddrMode.Offset() != op2->gtAddrMode.Offset())
1329                     {
1330                         return false;
1331                     }
1332                     break;
1333                 case GT_INDEX:
1334                     if (op1->gtIndex.gtIndElemSize != op2->gtIndex.gtIndElemSize)
1335                     {
1336                         return false;
1337                     }
1338                     break;
1339                 case GT_INDEX_ADDR:
1340                     if (op1->AsIndexAddr()->gtElemSize != op2->AsIndexAddr()->gtElemSize)
1341                     {
1342                         return false;
1343                     }
1344                     break;
1345 #ifdef FEATURE_SIMD
1346                 case GT_SIMD:
1347                     if ((op1->AsSIMD()->gtSIMDIntrinsicID != op2->AsSIMD()->gtSIMDIntrinsicID) ||
1348                         (op1->AsSIMD()->gtSIMDBaseType != op2->AsSIMD()->gtSIMDBaseType) ||
1349                         (op1->AsSIMD()->gtSIMDSize != op2->AsSIMD()->gtSIMDSize))
1350                     {
1351                         return false;
1352                     }
1353                     break;
1354 #endif // FEATURE_SIMD
1355
1356 #ifdef FEATURE_HW_INTRINSICS
1357                 case GT_HWIntrinsic:
1358                     if ((op1->AsHWIntrinsic()->gtHWIntrinsicId != op2->AsHWIntrinsic()->gtHWIntrinsicId) ||
1359                         (op1->AsHWIntrinsic()->gtSIMDBaseType != op2->AsHWIntrinsic()->gtSIMDBaseType) ||
1360                         (op1->AsHWIntrinsic()->gtSIMDSize != op2->AsHWIntrinsic()->gtSIMDSize) ||
1361                         (op1->AsHWIntrinsic()->gtIndexBaseType != op2->AsHWIntrinsic()->gtIndexBaseType))
1362                     {
1363                         return false;
1364                     }
1365                     break;
1366 #endif
1367
1368                 // For the ones below no extra argument matters for comparison.
1369                 case GT_QMARK:
1370                     break;
1371
1372                 default:
1373                     assert(!"unexpected binary ExOp operator");
1374             }
1375         }
1376
1377         if (op1->gtOp.gtOp2)
1378         {
1379             if (!Compare(op1->gtOp.gtOp1, op2->gtOp.gtOp1, swapOK))
1380             {
1381                 if (swapOK && OperIsCommutative(oper) &&
1382                     ((op1->gtOp.gtOp1->gtFlags | op1->gtOp.gtOp2->gtFlags | op2->gtOp.gtOp1->gtFlags |
1383                       op2->gtOp.gtOp2->gtFlags) &
1384                      GTF_ALL_EFFECT) == 0)
1385                 {
1386                     if (Compare(op1->gtOp.gtOp1, op2->gtOp.gtOp2, swapOK))
1387                     {
1388                         op1 = op1->gtOp.gtOp2;
1389                         op2 = op2->gtOp.gtOp1;
1390                         goto AGAIN;
1391                     }
1392                 }
1393
1394                 return false;
1395             }
1396
1397             op1 = op1->gtOp.gtOp2;
1398             op2 = op2->gtOp.gtOp2;
1399
1400             goto AGAIN;
1401         }
1402         else
1403         {
1404
1405             op1 = op1->gtOp.gtOp1;
1406             op2 = op2->gtOp.gtOp1;
1407
1408             if (!op1)
1409             {
1410                 return (op2 == nullptr);
1411             }
1412             if (!op2)
1413             {
1414                 return false;
1415             }
1416
1417             goto AGAIN;
1418         }
1419     }
1420
1421     /* See what kind of a special operator we have here */
1422
1423     switch (oper)
1424     {
1425         case GT_FIELD:
1426             if (op1->gtField.gtFldHnd != op2->gtField.gtFldHnd)
1427             {
1428                 break;
1429             }
1430
1431             op1 = op1->gtField.gtFldObj;
1432             op2 = op2->gtField.gtFldObj;
1433
1434             if (op1 || op2)
1435             {
1436                 if (op1 && op2)
1437                 {
1438                     goto AGAIN;
1439                 }
1440             }
1441
1442             return true;
1443
1444         case GT_CALL:
1445
1446             if (op1->gtCall.gtCallType != op2->gtCall.gtCallType)
1447             {
1448                 return false;
1449             }
1450
1451             if (op1->gtCall.gtCallType != CT_INDIRECT)
1452             {
1453                 if (op1->gtCall.gtCallMethHnd != op2->gtCall.gtCallMethHnd)
1454                 {
1455                     return false;
1456                 }
1457
1458 #ifdef FEATURE_READYTORUN_COMPILER
1459                 if (op1->gtCall.gtEntryPoint.addr != op2->gtCall.gtEntryPoint.addr)
1460                 {
1461                     return false;
1462                 }
1463 #endif
1464             }
1465             else
1466             {
1467                 if (!Compare(op1->gtCall.gtCallAddr, op2->gtCall.gtCallAddr))
1468                 {
1469                     return false;
1470                 }
1471             }
1472
1473             if (Compare(op1->gtCall.gtCallLateArgs, op2->gtCall.gtCallLateArgs) &&
1474                 Compare(op1->gtCall.gtCallArgs, op2->gtCall.gtCallArgs) &&
1475                 Compare(op1->gtCall.gtControlExpr, op2->gtCall.gtControlExpr) &&
1476                 Compare(op1->gtCall.gtCallObjp, op2->gtCall.gtCallObjp))
1477             {
1478                 return true;
1479             }
1480             break;
1481
1482         case GT_ARR_ELEM:
1483
1484             if (op1->gtArrElem.gtArrRank != op2->gtArrElem.gtArrRank)
1485             {
1486                 return false;
1487             }
1488
1489             // NOTE: gtArrElemSize may need to be handled
1490
1491             unsigned dim;
1492             for (dim = 0; dim < op1->gtArrElem.gtArrRank; dim++)
1493             {
1494                 if (!Compare(op1->gtArrElem.gtArrInds[dim], op2->gtArrElem.gtArrInds[dim]))
1495                 {
1496                     return false;
1497                 }
1498             }
1499
1500             op1 = op1->gtArrElem.gtArrObj;
1501             op2 = op2->gtArrElem.gtArrObj;
1502             goto AGAIN;
1503
1504         case GT_ARR_OFFSET:
1505             if (op1->gtArrOffs.gtCurrDim != op2->gtArrOffs.gtCurrDim ||
1506                 op1->gtArrOffs.gtArrRank != op2->gtArrOffs.gtArrRank)
1507             {
1508                 return false;
1509             }
1510             return (Compare(op1->gtArrOffs.gtOffset, op2->gtArrOffs.gtOffset) &&
1511                     Compare(op1->gtArrOffs.gtIndex, op2->gtArrOffs.gtIndex) &&
1512                     Compare(op1->gtArrOffs.gtArrObj, op2->gtArrOffs.gtArrObj));
1513
1514         case GT_CMPXCHG:
1515             return Compare(op1->gtCmpXchg.gtOpLocation, op2->gtCmpXchg.gtOpLocation) &&
1516                    Compare(op1->gtCmpXchg.gtOpValue, op2->gtCmpXchg.gtOpValue) &&
1517                    Compare(op1->gtCmpXchg.gtOpComparand, op2->gtCmpXchg.gtOpComparand);
1518
1519         case GT_ARR_BOUNDS_CHECK:
1520 #ifdef FEATURE_SIMD
1521         case GT_SIMD_CHK:
1522 #endif // FEATURE_SIMD
1523 #ifdef FEATURE_HW_INTRINSICS
1524         case GT_HW_INTRINSIC_CHK:
1525 #endif // FEATURE_HW_INTRINSICS
1526             return Compare(op1->gtBoundsChk.gtIndex, op2->gtBoundsChk.gtIndex) &&
1527                    Compare(op1->gtBoundsChk.gtArrLen, op2->gtBoundsChk.gtArrLen) &&
1528                    (op1->gtBoundsChk.gtThrowKind == op2->gtBoundsChk.gtThrowKind);
1529
1530         case GT_STORE_DYN_BLK:
1531         case GT_DYN_BLK:
1532             return Compare(op1->gtDynBlk.Addr(), op2->gtDynBlk.Addr()) &&
1533                    Compare(op1->gtDynBlk.Data(), op2->gtDynBlk.Data()) &&
1534                    Compare(op1->gtDynBlk.gtDynamicSize, op2->gtDynBlk.gtDynamicSize);
1535
1536         default:
1537             assert(!"unexpected operator");
1538     }
1539
1540     return false;
1541 }
1542
1543 /*****************************************************************************
1544  *
1545  *  Returns non-zero if the given tree contains a use of a local #lclNum.
1546  */
1547
1548 bool Compiler::gtHasRef(GenTree* tree, ssize_t lclNum, bool defOnly)
1549 {
1550     genTreeOps oper;
1551     unsigned   kind;
1552
1553 AGAIN:
1554
1555     assert(tree);
1556
1557     oper = tree->OperGet();
1558     kind = tree->OperKind();
1559
1560     assert(oper != GT_STMT);
1561
1562     /* Is this a constant node? */
1563
1564     if (kind & GTK_CONST)
1565     {
1566         return false;
1567     }
1568
1569     /* Is this a leaf node? */
1570
1571     if (kind & GTK_LEAF)
1572     {
1573         if (oper == GT_LCL_VAR)
1574         {
1575             if (tree->gtLclVarCommon.gtLclNum == (unsigned)lclNum)
1576             {
1577                 if (!defOnly)
1578                 {
1579                     return true;
1580                 }
1581             }
1582         }
1583         else if (oper == GT_RET_EXPR)
1584         {
1585             return gtHasRef(tree->gtRetExpr.gtInlineCandidate, lclNum, defOnly);
1586         }
1587
1588         return false;
1589     }
1590
1591     /* Is it a 'simple' unary/binary operator? */
1592
1593     if (kind & GTK_SMPOP)
1594     {
1595         if (tree->gtGetOp2IfPresent())
1596         {
1597             if (gtHasRef(tree->gtOp.gtOp1, lclNum, defOnly))
1598             {
1599                 return true;
1600             }
1601
1602             tree = tree->gtOp.gtOp2;
1603             goto AGAIN;
1604         }
1605         else
1606         {
1607             tree = tree->gtOp.gtOp1;
1608
1609             if (!tree)
1610             {
1611                 return false;
1612             }
1613
1614             if (oper == GT_ASG)
1615             {
1616                 // 'tree' is the gtOp1 of an assignment node. So we can handle
1617                 // the case where defOnly is either true or false.
1618
1619                 if (tree->gtOper == GT_LCL_VAR && tree->gtLclVarCommon.gtLclNum == (unsigned)lclNum)
1620                 {
1621                     return true;
1622                 }
1623                 else if (tree->gtOper == GT_FIELD && lclNum == (ssize_t)tree->gtField.gtFldHnd)
1624                 {
1625                     return true;
1626                 }
1627             }
1628
1629             goto AGAIN;
1630         }
1631     }
1632
1633     /* See what kind of a special operator we have here */
1634
1635     switch (oper)
1636     {
1637         case GT_FIELD:
1638             if (lclNum == (ssize_t)tree->gtField.gtFldHnd)
1639             {
1640                 if (!defOnly)
1641                 {
1642                     return true;
1643                 }
1644             }
1645
1646             tree = tree->gtField.gtFldObj;
1647             if (tree)
1648             {
1649                 goto AGAIN;
1650             }
1651             break;
1652
1653         case GT_CALL:
1654
1655             if (tree->gtCall.gtCallObjp)
1656             {
1657                 if (gtHasRef(tree->gtCall.gtCallObjp, lclNum, defOnly))
1658                 {
1659                     return true;
1660                 }
1661             }
1662
1663             if (tree->gtCall.gtCallArgs)
1664             {
1665                 if (gtHasRef(tree->gtCall.gtCallArgs, lclNum, defOnly))
1666                 {
1667                     return true;
1668                 }
1669             }
1670
1671             if (tree->gtCall.gtCallLateArgs)
1672             {
1673                 if (gtHasRef(tree->gtCall.gtCallLateArgs, lclNum, defOnly))
1674                 {
1675                     return true;
1676                 }
1677             }
1678
1679             if (tree->gtCall.gtControlExpr)
1680             {
1681                 if (gtHasRef(tree->gtCall.gtControlExpr, lclNum, defOnly))
1682                 {
1683                     return true;
1684                 }
1685             }
1686
1687             if (tree->gtCall.gtCallType == CT_INDIRECT)
1688             {
1689                 // pinvoke-calli cookie is a constant, or constant indirection
1690                 assert(tree->gtCall.gtCallCookie == nullptr || tree->gtCall.gtCallCookie->gtOper == GT_CNS_INT ||
1691                        tree->gtCall.gtCallCookie->gtOper == GT_IND);
1692
1693                 tree = tree->gtCall.gtCallAddr;
1694             }
1695             else
1696             {
1697                 tree = nullptr;
1698             }
1699
1700             if (tree)
1701             {
1702                 goto AGAIN;
1703             }
1704
1705             break;
1706
1707         case GT_ARR_ELEM:
1708             if (gtHasRef(tree->gtArrElem.gtArrObj, lclNum, defOnly))
1709             {
1710                 return true;
1711             }
1712
1713             unsigned dim;
1714             for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
1715             {
1716                 if (gtHasRef(tree->gtArrElem.gtArrInds[dim], lclNum, defOnly))
1717                 {
1718                     return true;
1719                 }
1720             }
1721
1722             break;
1723
1724         case GT_ARR_OFFSET:
1725             if (gtHasRef(tree->gtArrOffs.gtOffset, lclNum, defOnly) ||
1726                 gtHasRef(tree->gtArrOffs.gtIndex, lclNum, defOnly) ||
1727                 gtHasRef(tree->gtArrOffs.gtArrObj, lclNum, defOnly))
1728             {
1729                 return true;
1730             }
1731             break;
1732
1733         case GT_CMPXCHG:
1734             if (gtHasRef(tree->gtCmpXchg.gtOpLocation, lclNum, defOnly))
1735             {
1736                 return true;
1737             }
1738             if (gtHasRef(tree->gtCmpXchg.gtOpValue, lclNum, defOnly))
1739             {
1740                 return true;
1741             }
1742             if (gtHasRef(tree->gtCmpXchg.gtOpComparand, lclNum, defOnly))
1743             {
1744                 return true;
1745             }
1746             break;
1747
1748         case GT_ARR_BOUNDS_CHECK:
1749 #ifdef FEATURE_SIMD
1750         case GT_SIMD_CHK:
1751 #endif // FEATURE_SIMD
1752 #ifdef FEATURE_HW_INTRINSICS
1753         case GT_HW_INTRINSIC_CHK:
1754 #endif // FEATURE_HW_INTRINSICS
1755             if (gtHasRef(tree->gtBoundsChk.gtIndex, lclNum, defOnly))
1756             {
1757                 return true;
1758             }
1759             if (gtHasRef(tree->gtBoundsChk.gtArrLen, lclNum, defOnly))
1760             {
1761                 return true;
1762             }
1763             break;
1764
1765         case GT_STORE_DYN_BLK:
1766             if (gtHasRef(tree->gtDynBlk.Data(), lclNum, defOnly))
1767             {
1768                 return true;
1769             }
1770             __fallthrough;
1771         case GT_DYN_BLK:
1772             if (gtHasRef(tree->gtDynBlk.Addr(), lclNum, defOnly))
1773             {
1774                 return true;
1775             }
1776             if (gtHasRef(tree->gtDynBlk.gtDynamicSize, lclNum, defOnly))
1777             {
1778                 return true;
1779             }
1780             break;
1781
1782         default:
1783 #ifdef DEBUG
1784             gtDispTree(tree);
1785 #endif
1786             assert(!"unexpected operator");
1787     }
1788
1789     return false;
1790 }
1791
1792 struct AddrTakenDsc
1793 {
1794     Compiler* comp;
1795     bool      hasAddrTakenLcl;
1796 };
1797
1798 /* static */
1799 Compiler::fgWalkResult Compiler::gtHasLocalsWithAddrOpCB(GenTree** pTree, fgWalkData* data)
1800 {
1801     GenTree*  tree = *pTree;
1802     Compiler* comp = data->compiler;
1803
1804     if (tree->gtOper == GT_LCL_VAR)
1805     {
1806         unsigned   lclNum = tree->gtLclVarCommon.gtLclNum;
1807         LclVarDsc* varDsc = &comp->lvaTable[lclNum];
1808
1809         if (varDsc->lvHasLdAddrOp || varDsc->lvAddrExposed)
1810         {
1811             ((AddrTakenDsc*)data->pCallbackData)->hasAddrTakenLcl = true;
1812             return WALK_ABORT;
1813         }
1814     }
1815
1816     return WALK_CONTINUE;
1817 }
1818
1819 /*****************************************************************************
1820  *
1821  *  Return true if this tree contains locals with lvHasLdAddrOp or lvAddrExposed
1822  *  flag(s) set.
1823  */
1824
1825 bool Compiler::gtHasLocalsWithAddrOp(GenTree* tree)
1826 {
1827     AddrTakenDsc desc;
1828
1829     desc.comp            = this;
1830     desc.hasAddrTakenLcl = false;
1831
1832     fgWalkTreePre(&tree, gtHasLocalsWithAddrOpCB, &desc);
1833
1834     return desc.hasAddrTakenLcl;
1835 }
1836
1837 #ifdef DEBUG
1838
1839 /*****************************************************************************
1840  *
1841  *  Helper used to compute hash values for trees.
1842  */
1843
1844 inline unsigned genTreeHashAdd(unsigned old, unsigned add)
1845 {
1846     return (old + old / 2) ^ add;
1847 }
1848
1849 inline unsigned genTreeHashAdd(unsigned old, void* add)
1850 {
1851     return genTreeHashAdd(old, (unsigned)(size_t)add);
1852 }
1853
1854 /*****************************************************************************
1855  *
1856  *  Given an arbitrary expression tree, compute a hash value for it.
1857  */
1858
1859 unsigned Compiler::gtHashValue(GenTree* tree)
1860 {
1861     genTreeOps oper;
1862     unsigned   kind;
1863
1864     unsigned hash = 0;
1865
1866     GenTree* temp;
1867
1868 AGAIN:
1869     assert(tree);
1870     assert(tree->gtOper != GT_STMT);
1871
1872     /* Figure out what kind of a node we have */
1873
1874     oper = tree->OperGet();
1875     kind = tree->OperKind();
1876
1877     /* Include the operator value in the hash */
1878
1879     hash = genTreeHashAdd(hash, oper);
1880
1881     /* Is this a constant or leaf node? */
1882
1883     if (kind & (GTK_CONST | GTK_LEAF))
1884     {
1885         size_t add;
1886
1887         switch (oper)
1888         {
1889             UINT64 bits;
1890             case GT_LCL_VAR:
1891                 add = tree->gtLclVar.gtLclNum;
1892                 break;
1893             case GT_LCL_FLD:
1894                 hash = genTreeHashAdd(hash, tree->gtLclFld.gtLclNum);
1895                 add  = tree->gtLclFld.gtLclOffs;
1896                 break;
1897
1898             case GT_CNS_INT:
1899                 add = tree->gtIntCon.gtIconVal;
1900                 break;
1901             case GT_CNS_LNG:
1902                 bits = (UINT64)tree->gtLngCon.gtLconVal;
1903 #ifdef _HOST_64BIT_
1904                 add = bits;
1905 #else // 32-bit host
1906                 add = genTreeHashAdd(uhi32(bits), ulo32(bits));
1907 #endif
1908                 break;
1909             case GT_CNS_DBL:
1910                 bits = *(UINT64*)(&tree->gtDblCon.gtDconVal);
1911 #ifdef _HOST_64BIT_
1912                 add = bits;
1913 #else // 32-bit host
1914                 add = genTreeHashAdd(uhi32(bits), ulo32(bits));
1915 #endif
1916                 break;
1917             case GT_CNS_STR:
1918                 add = tree->gtStrCon.gtSconCPX;
1919                 break;
1920
1921             case GT_JMP:
1922                 add = tree->gtVal.gtVal1;
1923                 break;
1924
1925             default:
1926                 add = 0;
1927                 break;
1928         }
1929
1930         // clang-format off
1931         // narrow 'add' into a 32-bit 'val'
1932         unsigned val;
1933 #ifdef _HOST_64BIT_
1934         val = genTreeHashAdd(uhi32(add), ulo32(add));
1935 #else // 32-bit host
1936         val = add;
1937 #endif
1938         // clang-format on
1939
1940         hash = genTreeHashAdd(hash, val);
1941         goto DONE;
1942     }
1943
1944     /* Is it a 'simple' unary/binary operator? */
1945
1946     GenTree* op1;
1947
1948     if (kind & GTK_UNOP)
1949     {
1950         op1 = tree->gtOp.gtOp1;
1951         /* Special case: no sub-operand at all */
1952
1953         if (GenTree::IsExOp(kind))
1954         {
1955             // ExOp operators extend operators with extra, non-GenTree* members.  In many cases,
1956             // these should be included in the hash code.
1957             switch (oper)
1958             {
1959                 case GT_ARR_LENGTH:
1960                     hash += tree->gtArrLen.ArrLenOffset();
1961                     break;
1962                 case GT_CAST:
1963                     hash ^= tree->gtCast.gtCastType;
1964                     break;
1965                 case GT_INDEX:
1966                     hash += tree->gtIndex.gtIndElemSize;
1967                     break;
1968                 case GT_INDEX_ADDR:
1969                     hash += tree->AsIndexAddr()->gtElemSize;
1970                     break;
1971                 case GT_ALLOCOBJ:
1972                     hash = genTreeHashAdd(hash, static_cast<unsigned>(
1973                                                     reinterpret_cast<uintptr_t>(tree->gtAllocObj.gtAllocObjClsHnd)));
1974                     hash = genTreeHashAdd(hash, tree->gtAllocObj.gtNewHelper);
1975                     break;
1976                 case GT_RUNTIMELOOKUP:
1977                     hash =
1978                         genTreeHashAdd(hash,
1979                                        static_cast<unsigned>(reinterpret_cast<uintptr_t>(tree->gtRuntimeLookup.gtHnd)));
1980                     break;
1981
1982                 case GT_OBJ:
1983                     hash =
1984                         genTreeHashAdd(hash, static_cast<unsigned>(reinterpret_cast<uintptr_t>(tree->gtObj.gtClass)));
1985                     break;
1986                 // For the ones below no extra argument matters for comparison.
1987                 case GT_BOX:
1988                     break;
1989
1990                 default:
1991                     assert(!"unexpected unary ExOp operator");
1992             }
1993         }
1994
1995         if (!op1)
1996         {
1997             goto DONE;
1998         }
1999
2000         tree = op1;
2001         goto AGAIN;
2002     }
2003
2004     if (kind & GTK_BINOP)
2005     {
2006         if (GenTree::IsExOp(kind))
2007         {
2008             // ExOp operators extend operators with extra, non-GenTree* members.  In many cases,
2009             // these should be included in the hash code.
2010             switch (oper)
2011             {
2012                 case GT_INTRINSIC:
2013                     hash += tree->gtIntrinsic.gtIntrinsicId;
2014                     break;
2015                 case GT_LEA:
2016                     hash += static_cast<unsigned>(tree->gtAddrMode.Offset() << 3) + tree->gtAddrMode.gtScale;
2017                     break;
2018
2019                 case GT_BLK:
2020                 case GT_STORE_BLK:
2021                     hash += tree->gtBlk.gtBlkSize;
2022                     break;
2023
2024                 case GT_OBJ:
2025                 case GT_STORE_OBJ:
2026                     hash ^= PtrToUlong(tree->AsObj()->gtClass);
2027                     break;
2028
2029                 case GT_DYN_BLK:
2030                 case GT_STORE_DYN_BLK:
2031                     hash += gtHashValue(tree->AsDynBlk()->gtDynamicSize);
2032                     break;
2033
2034                 // For the ones below no extra argument matters for comparison.
2035                 case GT_ARR_INDEX:
2036                 case GT_QMARK:
2037                 case GT_INDEX:
2038                 case GT_INDEX_ADDR:
2039                     break;
2040
2041 #ifdef FEATURE_SIMD
2042                 case GT_SIMD:
2043                     hash += tree->gtSIMD.gtSIMDIntrinsicID;
2044                     hash += tree->gtSIMD.gtSIMDBaseType;
2045                     hash += tree->gtSIMD.gtSIMDSize;
2046                     break;
2047 #endif // FEATURE_SIMD
2048
2049 #ifdef FEATURE_HW_INTRINSICS
2050                 case GT_HWIntrinsic:
2051                     hash += tree->gtHWIntrinsic.gtHWIntrinsicId;
2052                     hash += tree->gtHWIntrinsic.gtSIMDBaseType;
2053                     hash += tree->gtHWIntrinsic.gtSIMDSize;
2054                     hash += tree->gtHWIntrinsic.gtIndexBaseType;
2055                     break;
2056 #endif // FEATURE_HW_INTRINSICS
2057
2058                 default:
2059                     assert(!"unexpected binary ExOp operator");
2060             }
2061         }
2062
2063         op1          = tree->gtOp.gtOp1;
2064         GenTree* op2 = tree->gtOp.gtOp2;
2065
2066         /* Is there a second sub-operand? */
2067
2068         if (!op2)
2069         {
2070             /* Special case: no sub-operands at all */
2071
2072             if (!op1)
2073             {
2074                 goto DONE;
2075             }
2076
2077             /* This is a unary operator */
2078
2079             tree = op1;
2080             goto AGAIN;
2081         }
2082
2083         /* This is a binary operator */
2084
2085         unsigned hsh1 = gtHashValue(op1);
2086
2087         /* Add op1's hash to the running value and continue with op2 */
2088
2089         hash = genTreeHashAdd(hash, hsh1);
2090
2091         tree = op2;
2092         goto AGAIN;
2093     }
2094
2095     /* See what kind of a special operator we have here */
2096     switch (tree->gtOper)
2097     {
2098         case GT_FIELD:
2099             if (tree->gtField.gtFldObj)
2100             {
2101                 temp = tree->gtField.gtFldObj;
2102                 assert(temp);
2103                 hash = genTreeHashAdd(hash, gtHashValue(temp));
2104             }
2105             break;
2106
2107         case GT_STMT:
2108             temp = tree->gtStmt.gtStmtExpr;
2109             assert(temp);
2110             hash = genTreeHashAdd(hash, gtHashValue(temp));
2111             break;
2112
2113         case GT_ARR_ELEM:
2114
2115             hash = genTreeHashAdd(hash, gtHashValue(tree->gtArrElem.gtArrObj));
2116
2117             unsigned dim;
2118             for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
2119             {
2120                 hash = genTreeHashAdd(hash, gtHashValue(tree->gtArrElem.gtArrInds[dim]));
2121             }
2122
2123             break;
2124
2125         case GT_ARR_OFFSET:
2126             hash = genTreeHashAdd(hash, gtHashValue(tree->gtArrOffs.gtOffset));
2127             hash = genTreeHashAdd(hash, gtHashValue(tree->gtArrOffs.gtIndex));
2128             hash = genTreeHashAdd(hash, gtHashValue(tree->gtArrOffs.gtArrObj));
2129             break;
2130
2131         case GT_CALL:
2132
2133             if (tree->gtCall.gtCallObjp && tree->gtCall.gtCallObjp->gtOper != GT_NOP)
2134             {
2135                 temp = tree->gtCall.gtCallObjp;
2136                 assert(temp);
2137                 hash = genTreeHashAdd(hash, gtHashValue(temp));
2138             }
2139
2140             if (tree->gtCall.gtCallArgs)
2141             {
2142                 temp = tree->gtCall.gtCallArgs;
2143                 assert(temp);
2144                 hash = genTreeHashAdd(hash, gtHashValue(temp));
2145             }
2146
2147             if (tree->gtCall.gtCallType == CT_INDIRECT)
2148             {
2149                 temp = tree->gtCall.gtCallAddr;
2150                 assert(temp);
2151                 hash = genTreeHashAdd(hash, gtHashValue(temp));
2152             }
2153             else
2154             {
2155                 hash = genTreeHashAdd(hash, tree->gtCall.gtCallMethHnd);
2156             }
2157
2158             if (tree->gtCall.gtCallLateArgs)
2159             {
2160                 temp = tree->gtCall.gtCallLateArgs;
2161                 assert(temp);
2162                 hash = genTreeHashAdd(hash, gtHashValue(temp));
2163             }
2164             break;
2165
2166         case GT_CMPXCHG:
2167             hash = genTreeHashAdd(hash, gtHashValue(tree->gtCmpXchg.gtOpLocation));
2168             hash = genTreeHashAdd(hash, gtHashValue(tree->gtCmpXchg.gtOpValue));
2169             hash = genTreeHashAdd(hash, gtHashValue(tree->gtCmpXchg.gtOpComparand));
2170             break;
2171
2172         case GT_ARR_BOUNDS_CHECK:
2173 #ifdef FEATURE_SIMD
2174         case GT_SIMD_CHK:
2175 #endif // FEATURE_SIMD
2176 #ifdef FEATURE_HW_INTRINSICS
2177         case GT_HW_INTRINSIC_CHK:
2178 #endif // FEATURE_HW_INTRINSICS
2179             hash = genTreeHashAdd(hash, gtHashValue(tree->gtBoundsChk.gtIndex));
2180             hash = genTreeHashAdd(hash, gtHashValue(tree->gtBoundsChk.gtArrLen));
2181             hash = genTreeHashAdd(hash, tree->gtBoundsChk.gtThrowKind);
2182             break;
2183
2184         case GT_STORE_DYN_BLK:
2185             hash = genTreeHashAdd(hash, gtHashValue(tree->gtDynBlk.Data()));
2186             __fallthrough;
2187         case GT_DYN_BLK:
2188             hash = genTreeHashAdd(hash, gtHashValue(tree->gtDynBlk.Addr()));
2189             hash = genTreeHashAdd(hash, gtHashValue(tree->gtDynBlk.gtDynamicSize));
2190             break;
2191
2192         default:
2193 #ifdef DEBUG
2194             gtDispTree(tree);
2195 #endif
2196             assert(!"unexpected operator");
2197             break;
2198     }
2199
2200 DONE:
2201
2202     return hash;
2203 }
2204
2205 #endif // DEBUG
2206
2207 /*****************************************************************************
2208  *
2209  *  Return a relational operator that is the reverse of the given one.
2210  */
2211
2212 /* static */
2213 genTreeOps GenTree::ReverseRelop(genTreeOps relop)
2214 {
2215     static const genTreeOps reverseOps[] = {
2216         GT_NE,      // GT_EQ
2217         GT_EQ,      // GT_NE
2218         GT_GE,      // GT_LT
2219         GT_GT,      // GT_LE
2220         GT_LT,      // GT_GE
2221         GT_LE,      // GT_GT
2222         GT_TEST_NE, // GT_TEST_EQ
2223         GT_TEST_EQ, // GT_TEST_NE
2224     };
2225
2226     assert(reverseOps[GT_EQ - GT_EQ] == GT_NE);
2227     assert(reverseOps[GT_NE - GT_EQ] == GT_EQ);
2228
2229     assert(reverseOps[GT_LT - GT_EQ] == GT_GE);
2230     assert(reverseOps[GT_LE - GT_EQ] == GT_GT);
2231     assert(reverseOps[GT_GE - GT_EQ] == GT_LT);
2232     assert(reverseOps[GT_GT - GT_EQ] == GT_LE);
2233
2234     assert(reverseOps[GT_TEST_EQ - GT_EQ] == GT_TEST_NE);
2235     assert(reverseOps[GT_TEST_NE - GT_EQ] == GT_TEST_EQ);
2236
2237     assert(OperIsCompare(relop));
2238     assert(relop >= GT_EQ && (unsigned)(relop - GT_EQ) < sizeof(reverseOps));
2239
2240     return reverseOps[relop - GT_EQ];
2241 }
2242
2243 /*****************************************************************************
2244  *
2245  *  Return a relational operator that will work for swapped operands.
2246  */
2247
2248 /* static */
2249 genTreeOps GenTree::SwapRelop(genTreeOps relop)
2250 {
2251     static const genTreeOps swapOps[] = {
2252         GT_EQ,      // GT_EQ
2253         GT_NE,      // GT_NE
2254         GT_GT,      // GT_LT
2255         GT_GE,      // GT_LE
2256         GT_LE,      // GT_GE
2257         GT_LT,      // GT_GT
2258         GT_TEST_EQ, // GT_TEST_EQ
2259         GT_TEST_NE, // GT_TEST_NE
2260     };
2261
2262     assert(swapOps[GT_EQ - GT_EQ] == GT_EQ);
2263     assert(swapOps[GT_NE - GT_EQ] == GT_NE);
2264
2265     assert(swapOps[GT_LT - GT_EQ] == GT_GT);
2266     assert(swapOps[GT_LE - GT_EQ] == GT_GE);
2267     assert(swapOps[GT_GE - GT_EQ] == GT_LE);
2268     assert(swapOps[GT_GT - GT_EQ] == GT_LT);
2269
2270     assert(swapOps[GT_TEST_EQ - GT_EQ] == GT_TEST_EQ);
2271     assert(swapOps[GT_TEST_NE - GT_EQ] == GT_TEST_NE);
2272
2273     assert(OperIsCompare(relop));
2274     assert(relop >= GT_EQ && (unsigned)(relop - GT_EQ) < sizeof(swapOps));
2275
2276     return swapOps[relop - GT_EQ];
2277 }
2278
2279 /*****************************************************************************
2280  *
2281  *  Reverse the meaning of the given test condition.
2282  */
2283
2284 GenTree* Compiler::gtReverseCond(GenTree* tree)
2285 {
2286     if (tree->OperIsCompare())
2287     {
2288         tree->SetOper(GenTree::ReverseRelop(tree->OperGet()));
2289
2290         // Flip the GTF_RELOP_NAN_UN bit
2291         //     a ord b   === (a != NaN && b != NaN)
2292         //     a unord b === (a == NaN || b == NaN)
2293         // => !(a ord b) === (a unord b)
2294         if (varTypeIsFloating(tree->gtOp.gtOp1->TypeGet()))
2295         {
2296             tree->gtFlags ^= GTF_RELOP_NAN_UN;
2297         }
2298     }
2299     else if (tree->OperIs(GT_JCC, GT_SETCC))
2300     {
2301         GenTreeCC* cc   = tree->AsCC();
2302         cc->gtCondition = GenTree::ReverseRelop(cc->gtCondition);
2303     }
2304     else if (tree->OperIs(GT_JCMP))
2305     {
2306         // Flip the GTF_JCMP_EQ
2307         //
2308         // This causes switching
2309         //     cbz <=> cbnz
2310         //     tbz <=> tbnz
2311         tree->gtFlags ^= GTF_JCMP_EQ;
2312     }
2313     else
2314     {
2315         tree = gtNewOperNode(GT_NOT, TYP_INT, tree);
2316     }
2317
2318     return tree;
2319 }
2320
2321 /*****************************************************************************/
2322
2323 #ifdef DEBUG
2324
2325 bool GenTree::gtIsValid64RsltMul()
2326 {
2327     if ((gtOper != GT_MUL) || !(gtFlags & GTF_MUL_64RSLT))
2328     {
2329         return false;
2330     }
2331
2332     GenTree* op1 = gtOp.gtOp1;
2333     GenTree* op2 = gtOp.gtOp2;
2334
2335     if (TypeGet() != TYP_LONG || op1->TypeGet() != TYP_LONG || op2->TypeGet() != TYP_LONG)
2336     {
2337         return false;
2338     }
2339
2340     if (gtOverflow())
2341     {
2342         return false;
2343     }
2344
2345     // op1 has to be conv.i8(i4Expr)
2346     if ((op1->gtOper != GT_CAST) || (genActualType(op1->CastFromType()) != TYP_INT))
2347     {
2348         return false;
2349     }
2350
2351     // op2 has to be conv.i8(i4Expr)
2352     if ((op2->gtOper != GT_CAST) || (genActualType(op2->CastFromType()) != TYP_INT))
2353     {
2354         return false;
2355     }
2356
2357     // The signedness of both casts must be the same
2358     if (((op1->gtFlags & GTF_UNSIGNED) != 0) != ((op2->gtFlags & GTF_UNSIGNED) != 0))
2359     {
2360         return false;
2361     }
2362
2363     // Do unsigned mul iff both the casts are unsigned
2364     if (((op1->gtFlags & GTF_UNSIGNED) != 0) != ((gtFlags & GTF_UNSIGNED) != 0))
2365     {
2366         return false;
2367     }
2368
2369     return true;
2370 }
2371
2372 #endif // DEBUG
2373
2374 //------------------------------------------------------------------------------
2375 // gtSetListOrder : Figure out the evaluation order for a list of values.
2376 //
2377 //
2378 // Arguments:
2379 //    list  - List to figure out the evaluation order for
2380 //    isListCallArgs - True iff the list is a list of call arguments
2381 //    callArgsInRegs -  True iff the list is a list of call arguments and they are passed in registers
2382 //
2383 // Return Value:
2384 //    True if the operation can be a root of a bitwise rotation tree; false otherwise.
2385
2386 unsigned Compiler::gtSetListOrder(GenTree* list, bool isListCallArgs, bool callArgsInRegs)
2387 {
2388     assert((list != nullptr) && list->OperIsAnyList());
2389     assert(!callArgsInRegs || isListCallArgs);
2390
2391     ArrayStack<GenTree*> listNodes(getAllocator(CMK_ArrayStack));
2392
2393     do
2394     {
2395         listNodes.Push(list);
2396         list = list->gtOp.gtOp2;
2397     } while ((list != nullptr) && (list->OperIsAnyList()));
2398
2399     unsigned nxtlvl = (list == nullptr) ? 0 : gtSetEvalOrder(list);
2400     while (listNodes.Height() > 0)
2401     {
2402         list = listNodes.Pop();
2403         assert(list && list->OperIsAnyList());
2404         GenTree* next = list->gtOp.gtOp2;
2405
2406         unsigned level = 0;
2407
2408         // TODO: Do we have to compute costs differently for argument lists and
2409         // all other lists?
2410         // https://github.com/dotnet/coreclr/issues/7095
2411         unsigned costSz = (isListCallArgs || (next == nullptr)) ? 0 : 1;
2412         unsigned costEx = (isListCallArgs || (next == nullptr)) ? 0 : 1;
2413
2414         if (next != nullptr)
2415         {
2416             if (isListCallArgs)
2417             {
2418                 if (level < nxtlvl)
2419                 {
2420                     level = nxtlvl;
2421                 }
2422             }
2423             costEx += next->gtCostEx;
2424             costSz += next->gtCostSz;
2425         }
2426
2427         GenTree* op1 = list->gtOp.gtOp1;
2428         unsigned lvl = gtSetEvalOrder(op1);
2429
2430         // Swap the level counts
2431         if (list->gtFlags & GTF_REVERSE_OPS)
2432         {
2433             unsigned tmpl;
2434
2435             tmpl   = lvl;
2436             lvl    = nxtlvl;
2437             nxtlvl = tmpl;
2438         }
2439
2440         // TODO: Do we have to compute levels differently for argument lists and
2441         // all other lists?
2442         // https://github.com/dotnet/coreclr/issues/7095
2443         if (isListCallArgs)
2444         {
2445             if (level < lvl)
2446             {
2447                 level = lvl;
2448             }
2449         }
2450         else
2451         {
2452             if (lvl < 1)
2453             {
2454                 level = nxtlvl;
2455             }
2456             else if (lvl == nxtlvl)
2457             {
2458                 level = lvl + 1;
2459             }
2460             else
2461             {
2462                 level = lvl;
2463             }
2464         }
2465
2466         if (op1->gtCostEx != 0)
2467         {
2468             costEx += op1->gtCostEx;
2469             costEx += (callArgsInRegs || !isListCallArgs) ? 0 : IND_COST_EX;
2470         }
2471
2472         if (op1->gtCostSz != 0)
2473         {
2474             costSz += op1->gtCostSz;
2475 #ifdef _TARGET_XARCH_
2476             if (callArgsInRegs) // push is smaller than mov to reg
2477 #endif
2478             {
2479                 costSz += 1;
2480             }
2481         }
2482
2483         list->SetCosts(costEx, costSz);
2484
2485         nxtlvl = level;
2486     }
2487
2488     return nxtlvl;
2489 }
2490
2491 //-----------------------------------------------------------------------------
2492 // gtWalkOp: Traverse and mark an address expression
2493 //
2494 // Arguments:
2495 //    op1WB - An out parameter which is either the address expression, or one
2496 //            of its operands.
2497 //    op2WB - An out parameter which starts as either null or one of the operands
2498 //            of the address expression.
2499 //    base  - The base address of the addressing mode, or null if 'constOnly' is false
2500 //    constOnly - True if we will only traverse into ADDs with constant op2.
2501 //
2502 // This routine is a helper routine for gtSetEvalOrder() and is used to identify the
2503 // base and index nodes, which will be validated against those identified by
2504 // genCreateAddrMode().
2505 // It also marks the ADD nodes involved in the address expression with the
2506 // GTF_ADDRMODE_NO_CSE flag which prevents them from being considered for CSE's.
2507 //
2508 // Its two output parameters are modified under the following conditions:
2509 //
2510 // It is called once with the original address expression as 'op1WB', and
2511 // with 'constOnly' set to false. On this first invocation, *op1WB is always
2512 // an ADD node, and it will consider the operands of the ADD even if its op2 is
2513 // not a constant. However, when it encounters a non-constant or the base in the
2514 // op2 position, it stops iterating. That operand is returned in the 'op2WB' out
2515 // parameter, and will be considered on the third invocation of this method if
2516 // it is an ADD.
2517 //
2518 // It is called the second time with the two operands of the original expression, in
2519 // the original order, and the third time in reverse order. For these invocations
2520 // 'constOnly' is true, so it will only traverse cascaded ADD nodes if they have a
2521 // constant op2.
2522 //
2523 // The result, after three invocations, is that the values of the two out parameters
2524 // correspond to the base and index in some fashion. This method doesn't attempt
2525 // to determine or validate the scale or offset, if any.
2526 //
2527 // Assumptions (presumed to be ensured by genCreateAddrMode()):
2528 //    If an ADD has a constant operand, it is in the op2 position.
2529 //
2530 // Notes:
2531 //    This method, and its invocation sequence, are quite confusing, and since they
2532 //    were not originally well-documented, this specification is a possibly-imperfect
2533 //    reconstruction.
2534 //    The motivation for the handling of the NOP case is unclear.
2535 //    Note that 'op2WB' is only modified in the initial (!constOnly) case,
2536 //    or if a NOP is encountered in the op1 position.
2537 //
2538 void Compiler::gtWalkOp(GenTree** op1WB, GenTree** op2WB, GenTree* base, bool constOnly)
2539 {
2540     GenTree* op1 = *op1WB;
2541     GenTree* op2 = *op2WB;
2542
2543     op1 = op1->gtEffectiveVal();
2544
2545     // Now we look for op1's with non-overflow GT_ADDs [of constants]
2546     while ((op1->gtOper == GT_ADD) && (!op1->gtOverflow()) && (!constOnly || (op1->gtOp.gtOp2->IsCnsIntOrI())))
2547     {
2548         // mark it with GTF_ADDRMODE_NO_CSE
2549         op1->gtFlags |= GTF_ADDRMODE_NO_CSE;
2550
2551         if (!constOnly)
2552         {
2553             op2 = op1->gtOp.gtOp2;
2554         }
2555         op1 = op1->gtOp.gtOp1;
2556
2557         // If op1 is a GT_NOP then swap op1 and op2.
2558         // (Why? Also, presumably op2 is not a GT_NOP in this case?)
2559         if (op1->gtOper == GT_NOP)
2560         {
2561             GenTree* tmp;
2562
2563             tmp = op1;
2564             op1 = op2;
2565             op2 = tmp;
2566         }
2567
2568         if (!constOnly && ((op2 == base) || (!op2->IsCnsIntOrI())))
2569         {
2570             break;
2571         }
2572
2573         op1 = op1->gtEffectiveVal();
2574     }
2575
2576     *op1WB = op1;
2577     *op2WB = op2;
2578 }
2579
2580 #ifdef DEBUG
2581 /*****************************************************************************
2582  * This is a workaround. It is to help implement an assert in gtSetEvalOrder() that the values
2583  * gtWalkOp() leaves in op1 and op2 correspond with the values of adr, idx, mul, and cns
2584  * that are returned by genCreateAddrMode(). It's essentially impossible to determine
2585  * what gtWalkOp() *should* return for all possible trees. This simply loosens one assert
2586  * to handle the following case:
2587
2588          indir     int
2589                     const(h)  int    4 field
2590                  +         byref
2591                     lclVar    byref  V00 this               <-- op2
2592               comma     byref                           <-- adr (base)
2593                  indir     byte
2594                     lclVar    byref  V00 this
2595            +         byref
2596                  const     int    2                     <-- mul == 4
2597               <<        int                                 <-- op1
2598                  lclVar    int    V01 arg1              <-- idx
2599
2600  * Here, we are planning to generate the address mode [edx+4*eax], where eax = idx and edx = the GT_COMMA expression.
2601  * To check adr equivalence with op2, we need to walk down the GT_ADD tree just like gtWalkOp() does.
2602  */
2603 GenTree* Compiler::gtWalkOpEffectiveVal(GenTree* op)
2604 {
2605     for (;;)
2606     {
2607         op = op->gtEffectiveVal();
2608
2609         if ((op->gtOper != GT_ADD) || op->gtOverflow() || !op->gtOp.gtOp2->IsCnsIntOrI())
2610         {
2611             break;
2612         }
2613
2614         op = op->gtOp.gtOp1;
2615     }
2616
2617     return op;
2618 }
2619 #endif // DEBUG
2620
2621 /*****************************************************************************
2622  *
2623  *  Given a tree, set the gtCostEx and gtCostSz fields which
2624  *  are used to measure the relative costs of the codegen of the tree
2625  *
2626  */
2627
2628 void Compiler::gtPrepareCost(GenTree* tree)
2629 {
2630     gtSetEvalOrder(tree);
2631 }
2632
2633 bool Compiler::gtIsLikelyRegVar(GenTree* tree)
2634 {
2635     if (tree->gtOper != GT_LCL_VAR)
2636     {
2637         return false;
2638     }
2639
2640     assert(tree->gtLclVar.gtLclNum < lvaTableCnt);
2641     LclVarDsc* varDsc = lvaTable + tree->gtLclVar.gtLclNum;
2642
2643     if (varDsc->lvDoNotEnregister)
2644     {
2645         return false;
2646     }
2647
2648     // Be pessimistic if ref counts are not yet set up.
2649     //
2650     // Perhaps we should be optimistic though.
2651     // See notes in GitHub issue 18969.
2652     if (!lvaLocalVarRefCounted())
2653     {
2654         return false;
2655     }
2656
2657     if (varDsc->lvRefCntWtd() < (BB_UNITY_WEIGHT * 3))
2658     {
2659         return false;
2660     }
2661
2662 #ifdef _TARGET_X86_
2663     if (varTypeIsFloating(tree->TypeGet()))
2664         return false;
2665     if (varTypeIsLong(tree->TypeGet()))
2666         return false;
2667 #endif
2668
2669     return true;
2670 }
2671
2672 //------------------------------------------------------------------------
2673 // gtCanSwapOrder: Returns true iff the secondNode can be swapped with firstNode.
2674 //
2675 // Arguments:
2676 //    firstNode  - An operand of a tree that can have GTF_REVERSE_OPS set.
2677 //    secondNode - The other operand of the tree.
2678 //
2679 // Return Value:
2680 //    Returns a boolean indicating whether it is safe to reverse the execution
2681 //    order of the two trees, considering any exception, global effects, or
2682 //    ordering constraints.
2683 //
2684 bool Compiler::gtCanSwapOrder(GenTree* firstNode, GenTree* secondNode)
2685 {
2686     // Relative of order of global / side effects can't be swapped.
2687
2688     bool canSwap = true;
2689
2690     if (optValnumCSE_phase)
2691     {
2692         canSwap = optCSE_canSwap(firstNode, secondNode);
2693     }
2694
2695     // We cannot swap in the presence of special side effects such as GT_CATCH_ARG.
2696
2697     if (canSwap && (firstNode->gtFlags & GTF_ORDER_SIDEEFF))
2698     {
2699         canSwap = false;
2700     }
2701
2702     // When strict side effect order is disabled we allow GTF_REVERSE_OPS to be set
2703     // when one or both sides contains a GTF_CALL or GTF_EXCEPT.
2704     // Currently only the C and C++ languages allow non strict side effect order.
2705
2706     unsigned strictEffects = GTF_GLOB_EFFECT;
2707
2708     if (canSwap && (firstNode->gtFlags & strictEffects))
2709     {
2710         // op1 has side efects that can't be reordered.
2711         // Check for some special cases where we still may be able to swap.
2712
2713         if (secondNode->gtFlags & strictEffects)
2714         {
2715             // op2 has also has non reorderable side effects - can't swap.
2716             canSwap = false;
2717         }
2718         else
2719         {
2720             // No side effects in op2 - we can swap iff op1 has no way of modifying op2,
2721             // i.e. through byref assignments or calls or op2 is a constant.
2722
2723             if (firstNode->gtFlags & strictEffects & GTF_PERSISTENT_SIDE_EFFECTS)
2724             {
2725                 // We have to be conservative - can swap iff op2 is constant.
2726                 if (!secondNode->OperIsConst())
2727                 {
2728                     canSwap = false;
2729                 }
2730             }
2731         }
2732     }
2733     return canSwap;
2734 }
2735
2736 /*****************************************************************************
2737  *
2738  *  Given a tree, figure out the order in which its sub-operands should be
2739  *  evaluated. If the second operand of a binary operator is more expensive
2740  *  than the first operand, then try to swap the operand trees. Updates the
2741  *  GTF_REVERSE_OPS bit if necessary in this case.
2742  *
2743  *  Returns the Sethi 'complexity' estimate for this tree (the higher
2744  *  the number, the higher is the tree's resources requirement).
2745  *
2746  *  This function sets:
2747  *      1. gtCostEx to the execution complexity estimate
2748  *      2. gtCostSz to the code size estimate
2749  *      3. Sometimes sets GTF_ADDRMODE_NO_CSE on nodes in the tree.
2750  *      4. DEBUG-only: clears GTF_DEBUG_NODE_MORPHED.
2751  */
2752
2753 #ifdef _PREFAST_
2754 #pragma warning(push)
2755 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
2756 #endif
2757 unsigned Compiler::gtSetEvalOrder(GenTree* tree)
2758 {
2759     assert(tree);
2760     assert(tree->gtOper != GT_STMT);
2761
2762 #ifdef DEBUG
2763     /* Clear the GTF_DEBUG_NODE_MORPHED flag as well */
2764     tree->gtDebugFlags &= ~GTF_DEBUG_NODE_MORPHED;
2765 #endif
2766
2767     /* Is this a FP value? */
2768
2769     bool isflt = varTypeIsFloating(tree->TypeGet());
2770
2771     /* Figure out what kind of a node we have */
2772
2773     const genTreeOps oper = tree->OperGet();
2774     const unsigned   kind = tree->OperKind();
2775
2776     /* Assume no fixed registers will be trashed */
2777
2778     unsigned level;
2779     int      costEx;
2780     int      costSz;
2781
2782 #ifdef DEBUG
2783     costEx = -1;
2784     costSz = -1;
2785 #endif
2786
2787     /* Is this a constant or a leaf node? */
2788
2789     if (kind & (GTK_LEAF | GTK_CONST))
2790     {
2791         switch (oper)
2792         {
2793 #ifdef _TARGET_ARM_
2794             case GT_CNS_LNG:
2795                 costSz = 9;
2796                 costEx = 4;
2797                 goto COMMON_CNS;
2798
2799             case GT_CNS_STR:
2800                 // Uses movw/movt
2801                 costSz = 7;
2802                 costEx = 3;
2803                 goto COMMON_CNS;
2804
2805             case GT_CNS_INT:
2806             {
2807                 // If the constant is a handle then it will need to have a relocation
2808                 //  applied to it.
2809                 // Any constant that requires a reloc must use the movw/movt sequence
2810                 //
2811                 GenTreeIntConCommon* con = tree->AsIntConCommon();
2812
2813                 if (con->ImmedValNeedsReloc(this) ||
2814                     !codeGen->validImmForInstr(INS_mov, (target_ssize_t)tree->gtIntCon.gtIconVal))
2815                 {
2816                     // Uses movw/movt
2817                     costSz = 7;
2818                     costEx = 3;
2819                 }
2820                 else if (((unsigned)tree->gtIntCon.gtIconVal) <= 0x00ff)
2821                 {
2822                     // mov  Rd, <const8>
2823                     costSz = 1;
2824                     costEx = 1;
2825                 }
2826                 else
2827                 {
2828                     // Uses movw/mvn
2829                     costSz = 3;
2830                     costEx = 1;
2831                 }
2832                 goto COMMON_CNS;
2833             }
2834
2835 #elif defined _TARGET_XARCH_
2836
2837             case GT_CNS_LNG:
2838                 costSz = 10;
2839                 costEx = 3;
2840                 goto COMMON_CNS;
2841
2842             case GT_CNS_STR:
2843                 costSz = 4;
2844                 costEx = 1;
2845                 goto COMMON_CNS;
2846
2847             case GT_CNS_INT:
2848             {
2849                 // If the constant is a handle then it will need to have a relocation
2850                 //  applied to it.
2851                 //
2852                 GenTreeIntConCommon* con = tree->AsIntConCommon();
2853
2854                 bool iconNeedsReloc = con->ImmedValNeedsReloc(this);
2855
2856                 if (!iconNeedsReloc && con->FitsInI8())
2857                 {
2858                     costSz = 1;
2859                     costEx = 1;
2860                 }
2861 #if defined(_TARGET_AMD64_)
2862                 else if (iconNeedsReloc || !con->FitsInI32())
2863                 {
2864                     costSz = 10;
2865                     costEx = 3;
2866                 }
2867 #endif // _TARGET_AMD64_
2868                 else
2869                 {
2870                     costSz = 4;
2871                     costEx = 1;
2872                 }
2873                 goto COMMON_CNS;
2874             }
2875
2876 #elif defined(_TARGET_ARM64_)
2877             case GT_CNS_LNG:
2878             case GT_CNS_STR:
2879             case GT_CNS_INT:
2880                 // TODO-ARM64-NYI: Need cost estimates.
2881                 costSz = 1;
2882                 costEx = 1;
2883                 goto COMMON_CNS;
2884
2885 #else
2886             case GT_CNS_LNG:
2887             case GT_CNS_STR:
2888             case GT_CNS_INT:
2889 #error "Unknown _TARGET_"
2890 #endif
2891
2892             COMMON_CNS:
2893                 /*
2894                     Note that some code below depends on constants always getting
2895                     moved to be the second operand of a binary operator. This is
2896                     easily accomplished by giving constants a level of 0, which
2897                     we do on the next line. If you ever decide to change this, be
2898                     aware that unless you make other arrangements for integer
2899                     constants to be moved, stuff will break.
2900                  */
2901
2902                 level = 0;
2903                 break;
2904
2905             case GT_CNS_DBL:
2906                 level = 0;
2907                 /* We use fldz and fld1 to load 0.0 and 1.0, but all other  */
2908                 /* floating point constants are loaded using an indirection */
2909                 if ((*((__int64*)&(tree->gtDblCon.gtDconVal)) == 0) ||
2910                     (*((__int64*)&(tree->gtDblCon.gtDconVal)) == I64(0x3ff0000000000000)))
2911                 {
2912                     costEx = 1;
2913                     costSz = 1;
2914                 }
2915                 else
2916                 {
2917                     costEx = IND_COST_EX;
2918                     costSz = 4;
2919                 }
2920                 break;
2921
2922             case GT_LCL_VAR:
2923                 level = 1;
2924                 if (gtIsLikelyRegVar(tree))
2925                 {
2926                     costEx = 1;
2927                     costSz = 1;
2928                     /* Sign-extend and zero-extend are more expensive to load */
2929                     if (lvaTable[tree->gtLclVar.gtLclNum].lvNormalizeOnLoad())
2930                     {
2931                         costEx += 1;
2932                         costSz += 1;
2933                     }
2934                 }
2935                 else
2936                 {
2937                     costEx = IND_COST_EX;
2938                     costSz = 2;
2939                     /* Sign-extend and zero-extend are more expensive to load */
2940                     if (varTypeIsSmall(tree->TypeGet()))
2941                     {
2942                         costEx += 1;
2943                         costSz += 1;
2944                     }
2945                 }
2946 #if defined(_TARGET_AMD64_)
2947                 // increase costSz for floating point locals
2948                 if (isflt)
2949                 {
2950                     costSz += 1;
2951                     if (!gtIsLikelyRegVar(tree))
2952                     {
2953                         costSz += 1;
2954                     }
2955                 }
2956 #endif
2957                 break;
2958
2959             case GT_CLS_VAR:
2960 #ifdef _TARGET_ARM_
2961                 // We generate movw/movt/ldr
2962                 level  = 1;
2963                 costEx = 3 + IND_COST_EX; // 6
2964                 costSz = 4 + 4 + 2;       // 10
2965                 break;
2966 #endif
2967             case GT_LCL_FLD:
2968                 level  = 1;
2969                 costEx = IND_COST_EX;
2970                 costSz = 4;
2971                 if (varTypeIsSmall(tree->TypeGet()))
2972                 {
2973                     costEx += 1;
2974                     costSz += 1;
2975                 }
2976                 break;
2977
2978             case GT_PHI_ARG:
2979             case GT_ARGPLACE:
2980                 level  = 0;
2981                 costEx = 0;
2982                 costSz = 0;
2983                 break;
2984
2985             default:
2986                 level  = 1;
2987                 costEx = 1;
2988                 costSz = 1;
2989                 break;
2990         }
2991         goto DONE;
2992     }
2993
2994     /* Is it a 'simple' unary/binary operator? */
2995
2996     if (kind & GTK_SMPOP)
2997     {
2998         int      lvlb; // preference for op2
2999         unsigned lvl2; // scratch variable
3000
3001         GenTree* op1 = tree->gtOp.gtOp1;
3002         GenTree* op2 = tree->gtGetOp2IfPresent();
3003
3004         costEx = 0;
3005         costSz = 0;
3006
3007         if (tree->OperIsAddrMode())
3008         {
3009             if (op1 == nullptr)
3010             {
3011                 op1 = op2;
3012                 op2 = nullptr;
3013             }
3014         }
3015
3016         /* Check for a nilary operator */
3017
3018         if (op1 == nullptr)
3019         {
3020             assert(op2 == nullptr);
3021
3022             level = 0;
3023
3024             goto DONE;
3025         }
3026
3027         /* Is this a unary operator? */
3028
3029         if (op2 == nullptr)
3030         {
3031             /* Process the operand of the operator */
3032
3033             /* Most Unary ops have costEx of 1 */
3034             costEx = 1;
3035             costSz = 1;
3036
3037             level = gtSetEvalOrder(op1);
3038
3039             /* Special handling for some operators */
3040
3041             switch (oper)
3042             {
3043                 case GT_JTRUE:
3044                     costEx = 2;
3045                     costSz = 2;
3046                     break;
3047
3048                 case GT_SWITCH:
3049                     costEx = 10;
3050                     costSz = 5;
3051                     break;
3052
3053                 case GT_CAST:
3054 #if defined(_TARGET_ARM_)
3055                     costEx = 1;
3056                     costSz = 1;
3057                     if (isflt || varTypeIsFloating(op1->TypeGet()))
3058                     {
3059                         costEx = 3;
3060                         costSz = 4;
3061                     }
3062 #elif defined(_TARGET_ARM64_)
3063                     costEx = 1;
3064                     costSz = 2;
3065                     if (isflt || varTypeIsFloating(op1->TypeGet()))
3066                     {
3067                         costEx = 2;
3068                         costSz = 4;
3069                     }
3070 #elif defined(_TARGET_XARCH_)
3071                     costEx = 1;
3072                     costSz = 2;
3073
3074                     if (isflt || varTypeIsFloating(op1->TypeGet()))
3075                     {
3076                         /* cast involving floats always go through memory */
3077                         costEx = IND_COST_EX * 2;
3078                         costSz = 6;
3079                     }
3080 #else
3081 #error "Unknown _TARGET_"
3082 #endif
3083
3084                     /* Overflow casts are a lot more expensive */
3085                     if (tree->gtOverflow())
3086                     {
3087                         costEx += 6;
3088                         costSz += 6;
3089                     }
3090
3091                     break;
3092
3093                 case GT_LIST:
3094                 case GT_FIELD_LIST:
3095                 case GT_NOP:
3096                     costEx = 0;
3097                     costSz = 0;
3098                     break;
3099
3100                 case GT_INTRINSIC:
3101                     // GT_INTRINSIC intrinsics Sin, Cos, Sqrt, Abs ... have higher costs.
3102                     // TODO: tune these costs target specific as some of these are
3103                     // target intrinsics and would cost less to generate code.
3104                     switch (tree->gtIntrinsic.gtIntrinsicId)
3105                     {
3106                         default:
3107                             assert(!"missing case for gtIntrinsicId");
3108                             costEx = 12;
3109                             costSz = 12;
3110                             break;
3111
3112                         case CORINFO_INTRINSIC_Sin:
3113                         case CORINFO_INTRINSIC_Cos:
3114                         case CORINFO_INTRINSIC_Sqrt:
3115                         case CORINFO_INTRINSIC_Cbrt:
3116                         case CORINFO_INTRINSIC_Cosh:
3117                         case CORINFO_INTRINSIC_Sinh:
3118                         case CORINFO_INTRINSIC_Tan:
3119                         case CORINFO_INTRINSIC_Tanh:
3120                         case CORINFO_INTRINSIC_Asin:
3121                         case CORINFO_INTRINSIC_Asinh:
3122                         case CORINFO_INTRINSIC_Acos:
3123                         case CORINFO_INTRINSIC_Acosh:
3124                         case CORINFO_INTRINSIC_Atan:
3125                         case CORINFO_INTRINSIC_Atanh:
3126                         case CORINFO_INTRINSIC_Atan2:
3127                         case CORINFO_INTRINSIC_Log10:
3128                         case CORINFO_INTRINSIC_Pow:
3129                         case CORINFO_INTRINSIC_Exp:
3130                         case CORINFO_INTRINSIC_Ceiling:
3131                         case CORINFO_INTRINSIC_Floor:
3132                         case CORINFO_INTRINSIC_Object_GetType:
3133                             // Giving intrinsics a large fixed execution cost is because we'd like to CSE
3134                             // them, even if they are implemented by calls. This is different from modeling
3135                             // user calls since we never CSE user calls.
3136                             costEx = 36;
3137                             costSz = 4;
3138                             break;
3139
3140                         case CORINFO_INTRINSIC_Abs:
3141                             costEx = 5;
3142                             costSz = 15;
3143                             break;
3144
3145                         case CORINFO_INTRINSIC_Round:
3146                             costEx = 3;
3147                             costSz = 4;
3148                             break;
3149                     }
3150                     level++;
3151                     break;
3152
3153                 case GT_NOT:
3154                 case GT_NEG:
3155                     // We need to ensure that -x is evaluated before x or else
3156                     // we get burned while adjusting genFPstkLevel in x*-x where
3157                     // the rhs x is the last use of the enregistered x.
3158                     //
3159                     // Even in the integer case we want to prefer to
3160                     // evaluate the side without the GT_NEG node, all other things
3161                     // being equal.  Also a GT_NOT requires a scratch register
3162
3163                     level++;
3164                     break;
3165
3166                 case GT_ADDR:
3167
3168                     costEx = 0;
3169                     costSz = 1;
3170
3171                     // If we have a GT_ADDR of an GT_IND we can just copy the costs from indOp1
3172                     if (op1->OperGet() == GT_IND)
3173                     {
3174                         GenTree* indOp1 = op1->gtOp.gtOp1;
3175                         costEx          = indOp1->gtCostEx;
3176                         costSz          = indOp1->gtCostSz;
3177                     }
3178                     break;
3179
3180                 case GT_ARR_LENGTH:
3181                     level++;
3182
3183                     /* Array Len should be the same as an indirections, which have a costEx of IND_COST_EX */
3184                     costEx = IND_COST_EX - 1;
3185                     costSz = 2;
3186                     break;
3187
3188                 case GT_MKREFANY:
3189                 case GT_OBJ:
3190                     // We estimate the cost of a GT_OBJ or GT_MKREFANY to be two loads (GT_INDs)
3191                     costEx = 2 * IND_COST_EX;
3192                     costSz = 2 * 2;
3193                     break;
3194
3195                 case GT_BOX:
3196                     // We estimate the cost of a GT_BOX to be two stores (GT_INDs)
3197                     costEx = 2 * IND_COST_EX;
3198                     costSz = 2 * 2;
3199                     break;
3200
3201                 case GT_BLK:
3202                 case GT_IND:
3203
3204                     /* An indirection should always have a non-zero level.
3205                      * Only constant leaf nodes have level 0.
3206                      */
3207
3208                     if (level == 0)
3209                     {
3210                         level = 1;
3211                     }
3212
3213                     /* Indirections have a costEx of IND_COST_EX */
3214                     costEx = IND_COST_EX;
3215                     costSz = 2;
3216
3217                     /* If we have to sign-extend or zero-extend, bump the cost */
3218                     if (varTypeIsSmall(tree->TypeGet()))
3219                     {
3220                         costEx += 1;
3221                         costSz += 1;
3222                     }
3223
3224                     if (isflt)
3225                     {
3226                         if (tree->TypeGet() == TYP_DOUBLE)
3227                         {
3228                             costEx += 1;
3229                         }
3230 #ifdef _TARGET_ARM_
3231                         costSz += 2;
3232 #endif // _TARGET_ARM_
3233                     }
3234
3235                     // Can we form an addressing mode with this indirection?
3236                     // TODO-CQ: Consider changing this to op1->gtEffectiveVal() to take into account
3237                     // addressing modes hidden under a comma node.
3238
3239                     if (op1->gtOper == GT_ADD)
3240                     {
3241                         bool rev;
3242 #if SCALED_ADDR_MODES
3243                         unsigned mul;
3244 #endif // SCALED_ADDR_MODES
3245                         ssize_t  cns;
3246                         GenTree* base;
3247                         GenTree* idx;
3248
3249                         // See if we can form a complex addressing mode.
3250
3251                         GenTree* addr = op1->gtEffectiveVal();
3252
3253                         bool doAddrMode = true;
3254                         // See if we can form a complex addressing mode.
3255                         // Always use an addrMode for an array index indirection.
3256                         // TODO-1stClassStructs: Always do this, but first make sure it's
3257                         // done in Lowering as well.
3258                         if ((tree->gtFlags & GTF_IND_ARR_INDEX) == 0)
3259                         {
3260                             if (tree->TypeGet() == TYP_STRUCT)
3261                             {
3262                                 doAddrMode = false;
3263                             }
3264                             else if (varTypeIsStruct(tree))
3265                             {
3266                                 // This is a heuristic attempting to match prior behavior when indirections
3267                                 // under a struct assignment would not be considered for addressing modes.
3268                                 if (compCurStmt != nullptr)
3269                                 {
3270                                     GenTree* expr = compCurStmt->gtStmt.gtStmtExpr;
3271                                     if ((expr->OperGet() == GT_ASG) &&
3272                                         ((expr->gtGetOp1() == tree) || (expr->gtGetOp2() == tree)))
3273                                     {
3274                                         doAddrMode = false;
3275                                     }
3276                                 }
3277                             }
3278                         }
3279                         if ((doAddrMode) &&
3280                             codeGen->genCreateAddrMode(addr,  // address
3281                                                        false, // fold
3282                                                        &rev,  // reverse ops
3283                                                        &base, // base addr
3284                                                        &idx,  // index val
3285 #if SCALED_ADDR_MODES
3286                                                        &mul,  // scaling
3287 #endif                                                        // SCALED_ADDR_MODES
3288                                                        &cns)) // displacement
3289                         {
3290                             // We can form a complex addressing mode, so mark each of the interior
3291                             // nodes with GTF_ADDRMODE_NO_CSE and calculate a more accurate cost.
3292
3293                             addr->gtFlags |= GTF_ADDRMODE_NO_CSE;
3294 #ifdef _TARGET_XARCH_
3295                             // addrmodeCount is the count of items that we used to form
3296                             // an addressing mode.  The maximum value is 4 when we have
3297                             // all of these:   { base, idx, cns, mul }
3298                             //
3299                             unsigned addrmodeCount = 0;
3300                             if (base)
3301                             {
3302                                 costEx += base->gtCostEx;
3303                                 costSz += base->gtCostSz;
3304                                 addrmodeCount++;
3305                             }
3306
3307                             if (idx)
3308                             {
3309                                 costEx += idx->gtCostEx;
3310                                 costSz += idx->gtCostSz;
3311                                 addrmodeCount++;
3312                             }
3313
3314                             if (cns)
3315                             {
3316                                 if (((signed char)cns) == ((int)cns))
3317                                 {
3318                                     costSz += 1;
3319                                 }
3320                                 else
3321                                 {
3322                                     costSz += 4;
3323                                 }
3324                                 addrmodeCount++;
3325                             }
3326                             if (mul)
3327                             {
3328                                 addrmodeCount++;
3329                             }
3330                             // When we form a complex addressing mode we can reduced the costs
3331                             // associated with the interior GT_ADD and GT_LSH nodes:
3332                             //
3333                             //                      GT_ADD      -- reduce this interior GT_ADD by (-3,-3)
3334                             //                      /   \       --
3335                             //                  GT_ADD  'cns'   -- reduce this interior GT_ADD by (-2,-2)
3336                             //                  /   \           --
3337                             //               'base'  GT_LSL     -- reduce this interior GT_LSL by (-1,-1)
3338                             //                      /   \       --
3339                             //                   'idx'  'mul'
3340                             //
3341                             if (addrmodeCount > 1)
3342                             {
3343                                 // The number of interior GT_ADD and GT_LSL will always be one less than addrmodeCount
3344                                 //
3345                                 addrmodeCount--;
3346
3347                                 GenTree* tmp = addr;
3348                                 while (addrmodeCount > 0)
3349                                 {
3350                                     // decrement the gtCosts for the interior GT_ADD or GT_LSH node by the remaining
3351                                     // addrmodeCount
3352                                     tmp->SetCosts(tmp->gtCostEx - addrmodeCount, tmp->gtCostSz - addrmodeCount);
3353
3354                                     addrmodeCount--;
3355                                     if (addrmodeCount > 0)
3356                                     {
3357                                         GenTree* tmpOp1 = tmp->gtOp.gtOp1;
3358                                         GenTree* tmpOp2 = tmp->gtGetOp2();
3359                                         assert(tmpOp2 != nullptr);
3360
3361                                         if ((tmpOp1 != base) && (tmpOp1->OperGet() == GT_ADD))
3362                                         {
3363                                             tmp = tmpOp1;
3364                                         }
3365                                         else if (tmpOp2->OperGet() == GT_LSH)
3366                                         {
3367                                             tmp = tmpOp2;
3368                                         }
3369                                         else if (tmpOp1->OperGet() == GT_LSH)
3370                                         {
3371                                             tmp = tmpOp1;
3372                                         }
3373                                         else if (tmpOp2->OperGet() == GT_ADD)
3374                                         {
3375                                             tmp = tmpOp2;
3376                                         }
3377                                         else
3378                                         {
3379                                             // We can very rarely encounter a tree that has a GT_COMMA node
3380                                             // that is difficult to walk, so we just early out without decrementing.
3381                                             addrmodeCount = 0;
3382                                         }
3383                                     }
3384                                 }
3385                             }
3386 #elif defined _TARGET_ARM_
3387                             if (base)
3388                             {
3389                                 costEx += base->gtCostEx;
3390                                 costSz += base->gtCostSz;
3391                                 if ((base->gtOper == GT_LCL_VAR) && ((idx == NULL) || (cns == 0)))
3392                                 {
3393                                     costSz -= 1;
3394                                 }
3395                             }
3396
3397                             if (idx)
3398                             {
3399                                 costEx += idx->gtCostEx;
3400                                 costSz += idx->gtCostSz;
3401                                 if (mul > 0)
3402                                 {
3403                                     costSz += 2;
3404                                 }
3405                             }
3406
3407                             if (cns)
3408                             {
3409                                 if (cns >= 128) // small offsets fits into a 16-bit instruction
3410                                 {
3411                                     if (cns < 4096) // medium offsets require a 32-bit instruction
3412                                     {
3413                                         if (!isflt)
3414                                             costSz += 2;
3415                                     }
3416                                     else
3417                                     {
3418                                         costEx += 2; // Very large offsets require movw/movt instructions
3419                                         costSz += 8;
3420                                     }
3421                                 }
3422                             }
3423 #elif defined _TARGET_ARM64_
3424                             if (base)
3425                             {
3426                                 costEx += base->gtCostEx;
3427                                 costSz += base->gtCostSz;
3428                             }
3429
3430                             if (idx)
3431                             {
3432                                 costEx += idx->gtCostEx;
3433                                 costSz += idx->gtCostSz;
3434                             }
3435
3436                             if (cns != 0)
3437                             {
3438                                 if (cns >= (4096 * genTypeSize(tree->TypeGet())))
3439                                 {
3440                                     costEx += 1;
3441                                     costSz += 4;
3442                                 }
3443                             }
3444 #else
3445 #error "Unknown _TARGET_"
3446 #endif
3447
3448                             assert(addr->gtOper == GT_ADD);
3449                             assert(!addr->gtOverflow());
3450                             assert(op2 == nullptr);
3451                             assert(mul != 1);
3452
3453                             // If we have an addressing mode, we have one of:
3454                             //   [base             + cns]
3455                             //   [       idx * mul      ]  // mul >= 2, else we would use base instead of idx
3456                             //   [       idx * mul + cns]  // mul >= 2, else we would use base instead of idx
3457                             //   [base + idx * mul      ]  // mul can be 0, 2, 4, or 8
3458                             //   [base + idx * mul + cns]  // mul can be 0, 2, 4, or 8
3459                             // Note that mul == 0 is semantically equivalent to mul == 1.
3460                             // Note that cns can be zero.
3461                             CLANG_FORMAT_COMMENT_ANCHOR;
3462
3463 #if SCALED_ADDR_MODES
3464                             assert((base != nullptr) || (idx != nullptr && mul >= 2));
3465 #else
3466                             assert(base != NULL);
3467 #endif
3468
3469                             INDEBUG(GenTree* op1Save = addr);
3470
3471                             // Walk 'addr' identifying non-overflow ADDs that will be part of the address mode.
3472                             // Note that we will be modifying 'op1' and 'op2' so that eventually they should
3473                             // map to the base and index.
3474                             op1 = addr;
3475                             gtWalkOp(&op1, &op2, base, false);
3476
3477                             // op1 and op2 are now descendents of the root GT_ADD of the addressing mode.
3478                             assert(op1 != op1Save);
3479                             assert(op2 != nullptr);
3480
3481                             // Walk the operands again (the third operand is unused in this case).
3482                             // This time we will only consider adds with constant op2's, since
3483                             // we have already found either a non-ADD op1 or a non-constant op2.
3484                             gtWalkOp(&op1, &op2, nullptr, true);
3485
3486 #if defined(_TARGET_XARCH_)
3487                             // For XARCH we will fold GT_ADDs in the op2 position into the addressing mode, so we call
3488                             // gtWalkOp on both operands of the original GT_ADD.
3489                             // This is not done for ARMARCH. Though the stated reason is that we don't try to create a
3490                             // scaled index, in fact we actually do create them (even base + index*scale + offset).
3491
3492                             // At this point, 'op2' may itself be an ADD of a constant that should be folded
3493                             // into the addressing mode.
3494                             // Walk op2 looking for non-overflow GT_ADDs of constants.
3495                             gtWalkOp(&op2, &op1, nullptr, true);
3496 #endif // defined(_TARGET_XARCH_)
3497
3498                             // OK we are done walking the tree
3499                             // Now assert that op1 and op2 correspond with base and idx
3500                             // in one of the several acceptable ways.
3501
3502                             // Note that sometimes op1/op2 is equal to idx/base
3503                             // and other times op1/op2 is a GT_COMMA node with
3504                             // an effective value that is idx/base
3505
3506                             if (mul > 1)
3507                             {
3508                                 if ((op1 != base) && (op1->gtOper == GT_LSH))
3509                                 {
3510                                     op1->gtFlags |= GTF_ADDRMODE_NO_CSE;
3511                                     if (op1->gtOp.gtOp1->gtOper == GT_MUL)
3512                                     {
3513                                         op1->gtOp.gtOp1->gtFlags |= GTF_ADDRMODE_NO_CSE;
3514                                     }
3515                                     assert((base == nullptr) || (op2 == base) ||
3516                                            (op2->gtEffectiveVal() == base->gtEffectiveVal()) ||
3517                                            (gtWalkOpEffectiveVal(op2) == gtWalkOpEffectiveVal(base)));
3518                                 }
3519                                 else
3520                                 {
3521                                     assert(op2);
3522                                     assert(op2->gtOper == GT_LSH || op2->gtOper == GT_MUL);
3523                                     op2->gtFlags |= GTF_ADDRMODE_NO_CSE;
3524                                     // We may have eliminated multiple shifts and multiplies in the addressing mode,
3525                                     // so navigate down through them to get to "idx".
3526                                     GenTree* op2op1 = op2->gtOp.gtOp1;
3527                                     while ((op2op1->gtOper == GT_LSH || op2op1->gtOper == GT_MUL) && op2op1 != idx)
3528                                     {
3529                                         op2op1->gtFlags |= GTF_ADDRMODE_NO_CSE;
3530                                         op2op1 = op2op1->gtOp.gtOp1;
3531                                     }
3532                                     assert(op1->gtEffectiveVal() == base);
3533                                     assert(op2op1 == idx);
3534                                 }
3535                             }
3536                             else
3537                             {
3538                                 assert(mul == 0);
3539
3540                                 if ((op1 == idx) || (op1->gtEffectiveVal() == idx))
3541                                 {
3542                                     if (idx != nullptr)
3543                                     {
3544                                         if ((op1->gtOper == GT_MUL) || (op1->gtOper == GT_LSH))
3545                                         {
3546                                             if ((op1->gtOp.gtOp1->gtOper == GT_NOP) ||
3547                                                 (op1->gtOp.gtOp1->gtOper == GT_MUL &&
3548                                                  op1->gtOp.gtOp1->gtOp.gtOp1->gtOper == GT_NOP))
3549                                             {
3550                                                 op1->gtFlags |= GTF_ADDRMODE_NO_CSE;
3551                                                 if (op1->gtOp.gtOp1->gtOper == GT_MUL)
3552                                                 {
3553                                                     op1->gtOp.gtOp1->gtFlags |= GTF_ADDRMODE_NO_CSE;
3554                                                 }
3555                                             }
3556                                         }
3557                                     }
3558                                     assert((op2 == base) || (op2->gtEffectiveVal() == base));
3559                                 }
3560                                 else if ((op1 == base) || (op1->gtEffectiveVal() == base))
3561                                 {
3562                                     if (idx != nullptr)
3563                                     {
3564                                         assert(op2);
3565                                         if ((op2->gtOper == GT_MUL) || (op2->gtOper == GT_LSH))
3566                                         {
3567                                             if ((op2->gtOp.gtOp1->gtOper == GT_NOP) ||
3568                                                 (op2->gtOp.gtOp1->gtOper == GT_MUL &&
3569                                                  op2->gtOp.gtOp1->gtOp.gtOp1->gtOper == GT_NOP))
3570                                             {
3571                                                 op2->gtFlags |= GTF_ADDRMODE_NO_CSE;
3572                                                 if (op2->gtOp.gtOp1->gtOper == GT_MUL)
3573                                                 {
3574                                                     op2->gtOp.gtOp1->gtFlags |= GTF_ADDRMODE_NO_CSE;
3575                                                 }
3576                                             }
3577                                         }
3578                                         assert((op2 == idx) || (op2->gtEffectiveVal() == idx));
3579                                     }
3580                                 }
3581                                 else
3582                                 {
3583                                     // op1 isn't base or idx. Is this possible? Or should there be an assert?
3584                                 }
3585                             }
3586                             goto DONE;
3587
3588                         } // end  if  (genCreateAddrMode(...))
3589
3590                     } // end if  (op1->gtOper == GT_ADD)
3591                     else if (gtIsLikelyRegVar(op1))
3592                     {
3593                         /* Indirection of an enregister LCL_VAR, don't increase costEx/costSz */
3594                         goto DONE;
3595                     }
3596 #ifdef _TARGET_XARCH_
3597                     else if (op1->IsCnsIntOrI())
3598                     {
3599                         // Indirection of a CNS_INT, subtract 1 from costEx
3600                         // makes costEx 3 for x86 and 4 for amd64
3601                         //
3602                         costEx += (op1->gtCostEx - 1);
3603                         costSz += op1->gtCostSz;
3604                         goto DONE;
3605                     }
3606 #endif
3607                     break;
3608
3609                 default:
3610                     break;
3611             }
3612             costEx += op1->gtCostEx;
3613             costSz += op1->gtCostSz;
3614             goto DONE;
3615         }
3616
3617         /* Binary operator - check for certain special cases */
3618
3619         lvlb = 0;
3620
3621         /* Default Binary ops have a cost of 1,1 */
3622         costEx = 1;
3623         costSz = 1;
3624
3625 #ifdef _TARGET_ARM_
3626         if (isflt)
3627         {
3628             costSz += 2;
3629         }
3630 #endif
3631 #ifndef _TARGET_64BIT_
3632         if (varTypeIsLong(op1->TypeGet()))
3633         {
3634             /* Operations on longs are more expensive */
3635             costEx += 3;
3636             costSz += 3;
3637         }
3638 #endif
3639         switch (oper)
3640         {
3641             case GT_MOD:
3642             case GT_UMOD:
3643
3644                 /* Modulo by a power of 2 is easy */
3645
3646                 if (op2->IsCnsIntOrI())
3647                 {
3648                     size_t ival = op2->gtIntConCommon.IconValue();
3649
3650                     if (ival > 0 && ival == genFindLowestBit(ival))
3651                     {
3652                         break;
3653                     }
3654                 }
3655
3656                 __fallthrough;
3657
3658             case GT_DIV:
3659             case GT_UDIV:
3660
3661                 if (isflt)
3662                 {
3663                     /* fp division is very expensive to execute */
3664                     costEx = 36; // TYP_DOUBLE
3665                     costSz += 3;
3666                 }
3667                 else
3668                 {
3669                     /* integer division is also very expensive */
3670                     costEx = 20;
3671                     costSz += 2;
3672
3673                     // Encourage the first operand to be evaluated (into EAX/EDX) first */
3674                     lvlb -= 3;
3675                 }
3676                 break;
3677
3678             case GT_MUL:
3679
3680                 if (isflt)
3681                 {
3682                     /* FP multiplication instructions are more expensive */
3683                     costEx += 4;
3684                     costSz += 3;
3685                 }
3686                 else
3687                 {
3688                     /* Integer multiplication instructions are more expensive */
3689                     costEx += 3;
3690                     costSz += 2;
3691
3692                     if (tree->gtOverflow())
3693                     {
3694                         /* Overflow check are more expensive */
3695                         costEx += 3;
3696                         costSz += 3;
3697                     }
3698
3699 #ifdef _TARGET_X86_
3700                     if ((tree->gtType == TYP_LONG) || tree->gtOverflow())
3701                     {
3702                         /* We use imulEAX for TYP_LONG and overflow multiplications */
3703                         // Encourage the first operand to be evaluated (into EAX/EDX) first */
3704                         lvlb -= 4;
3705
3706                         /* The 64-bit imul instruction costs more */
3707                         costEx += 4;
3708                     }
3709 #endif //  _TARGET_X86_
3710                 }
3711                 break;
3712
3713             case GT_ADD:
3714             case GT_SUB:
3715                 if (isflt)
3716                 {
3717                     /* FP instructions are a bit more expensive */
3718                     costEx += 4;
3719                     costSz += 3;
3720                     break;
3721                 }
3722
3723                 /* Overflow check are more expensive */
3724                 if (tree->gtOverflow())
3725                 {
3726                     costEx += 3;
3727                     costSz += 3;
3728                 }
3729                 break;
3730
3731             case GT_COMMA:
3732
3733                 /* Comma tosses the result of the left operand */
3734                 gtSetEvalOrder(op1);
3735                 level = gtSetEvalOrder(op2);
3736
3737                 /* GT_COMMA cost is the sum of op1 and op2 costs */
3738                 costEx = (op1->gtCostEx + op2->gtCostEx);
3739                 costSz = (op1->gtCostSz + op2->gtCostSz);
3740
3741                 goto DONE;
3742
3743             case GT_COLON:
3744
3745                 level = gtSetEvalOrder(op1);
3746                 lvl2  = gtSetEvalOrder(op2);
3747
3748                 if (level < lvl2)
3749                 {
3750                     level = lvl2;
3751                 }
3752                 else if (level == lvl2)
3753                 {
3754                     level += 1;
3755                 }
3756
3757                 costEx = op1->gtCostEx + op2->gtCostEx;
3758                 costSz = op1->gtCostSz + op2->gtCostSz;
3759
3760                 goto DONE;
3761
3762             case GT_LIST:
3763             case GT_FIELD_LIST:
3764             {
3765                 const bool isListCallArgs = false;
3766                 const bool callArgsInRegs = false;
3767                 return gtSetListOrder(tree, isListCallArgs, callArgsInRegs);
3768             }
3769
3770             case GT_ASG:
3771                 /* Assignments need a bit of special handling */
3772                 /* Process the target */
3773                 level = gtSetEvalOrder(op1);
3774
3775                 if (gtIsLikelyRegVar(op1))
3776                 {
3777                     assert(lvlb == 0);
3778                     lvl2 = gtSetEvalOrder(op2);
3779
3780                     /* Assignment to an enregistered LCL_VAR */
3781                     costEx = op2->gtCostEx;
3782                     costSz = max(3, op2->gtCostSz); // 3 is an estimate for a reg-reg assignment
3783                     goto DONE_OP1_AFTER_COST;
3784                 }
3785                 goto DONE_OP1;
3786
3787             default:
3788                 break;
3789         }
3790
3791         /* Process the sub-operands */
3792
3793         level = gtSetEvalOrder(op1);
3794         if (lvlb < 0)
3795         {
3796             level -= lvlb; // lvlb is negative, so this increases level
3797             lvlb = 0;
3798         }
3799
3800     DONE_OP1:
3801         assert(lvlb >= 0);
3802         lvl2 = gtSetEvalOrder(op2) + lvlb;
3803
3804         costEx += (op1->gtCostEx + op2->gtCostEx);
3805         costSz += (op1->gtCostSz + op2->gtCostSz);
3806
3807     DONE_OP1_AFTER_COST:
3808
3809         bool bReverseInAssignment = false;
3810         if (oper == GT_ASG)
3811         {
3812             GenTree* op1Val = op1;
3813
3814             // Skip over the GT_IND/GT_ADDR tree (if one exists)
3815             //
3816             if ((op1->gtOper == GT_IND) && (op1->gtOp.gtOp1->gtOper == GT_ADDR))
3817             {
3818                 op1Val = op1->gtOp.gtOp1->gtOp.gtOp1;
3819             }
3820
3821             switch (op1Val->gtOper)
3822             {
3823                 case GT_IND:
3824                 case GT_BLK:
3825                 case GT_OBJ:
3826                 case GT_DYN_BLK:
3827
3828                     // In an indirection, the destination address is evaluated prior to the source.
3829                     // If we have any side effects on the target indirection,
3830                     // we have to evaluate op1 first.
3831                     // However, if the LHS is a lclVar address, SSA relies on using evaluation order for its
3832                     // renaming, and therefore the RHS must be evaluated first.
3833                     // If we have an assignment involving a lclVar address, the LHS may be marked as having
3834                     // side-effects.
3835                     // However the side-effects won't require that we evaluate the LHS address first:
3836                     // - The GTF_GLOB_REF might have been conservatively set on a FIELD of a local.
3837                     // - The local might be address-exposed, but that side-effect happens at the actual assignment (not
3838                     //   when its address is "evaluated") so it doesn't change the side effect to "evaluate" the address
3839                     //   after the RHS (note that in this case it won't be renamed by SSA anyway, but the reordering is
3840                     //   safe).
3841                     //
3842                     if (op1Val->AsIndir()->Addr()->IsLocalAddrExpr())
3843                     {
3844                         bReverseInAssignment = true;
3845                         tree->gtFlags |= GTF_REVERSE_OPS;
3846                         break;
3847                     }
3848                     if (op1Val->AsIndir()->Addr()->gtFlags & GTF_ALL_EFFECT)
3849                     {
3850                         break;
3851                     }
3852
3853                     // In case op2 assigns to a local var that is used in op1Val, we have to evaluate op1Val first.
3854                     if (op2->gtFlags & GTF_ASG)
3855                     {
3856                         break;
3857                     }
3858
3859                     // If op2 is simple then evaluate op1 first
3860
3861                     if (op2->OperKind() & GTK_LEAF)
3862                     {
3863                         break;
3864                     }
3865
3866                 // fall through and set GTF_REVERSE_OPS
3867
3868                 case GT_LCL_VAR:
3869                 case GT_LCL_FLD:
3870
3871                     // We evaluate op2 before op1
3872                     bReverseInAssignment = true;
3873                     tree->gtFlags |= GTF_REVERSE_OPS;
3874                     break;
3875
3876                 default:
3877                     break;
3878             }
3879         }
3880         else if (kind & GTK_RELOP)
3881         {
3882             /* Float compares remove both operands from the FP stack */
3883             /* Also FP comparison uses EAX for flags */
3884
3885             if (varTypeIsFloating(op1->TypeGet()))
3886             {
3887                 level++;
3888                 lvl2++;
3889             }
3890             if ((tree->gtFlags & GTF_RELOP_JMP_USED) == 0)
3891             {
3892                 /* Using a setcc instruction is more expensive */
3893                 costEx += 3;
3894             }
3895         }
3896
3897         /* Check for other interesting cases */
3898
3899         switch (oper)
3900         {
3901             case GT_LSH:
3902             case GT_RSH:
3903             case GT_RSZ:
3904             case GT_ROL:
3905             case GT_ROR:
3906                 /* Variable sized shifts are more expensive and use REG_SHIFT */
3907
3908                 if (!op2->IsCnsIntOrI())
3909                 {
3910                     costEx += 3;
3911 #ifndef _TARGET_64BIT_
3912                     // Variable sized LONG shifts require the use of a helper call
3913                     //
3914                     if (tree->gtType == TYP_LONG)
3915                     {
3916                         level += 5;
3917                         lvl2 += 5;
3918                         costEx += 3 * IND_COST_EX;
3919                         costSz += 4;
3920                     }
3921 #endif // !_TARGET_64BIT_
3922                 }
3923                 break;
3924
3925             case GT_INTRINSIC:
3926
3927                 switch (tree->gtIntrinsic.gtIntrinsicId)
3928                 {
3929                     case CORINFO_INTRINSIC_Atan2:
3930                     case CORINFO_INTRINSIC_Pow:
3931                         // These math intrinsics are actually implemented by user calls.
3932                         // Increase the Sethi 'complexity' by two to reflect the argument
3933                         // register requirement.
3934                         level += 2;
3935                         break;
3936                     default:
3937                         assert(!"Unknown binary GT_INTRINSIC operator");
3938                         break;
3939                 }
3940
3941                 break;
3942
3943             default:
3944                 break;
3945         }
3946
3947         /* We need to evalutate constants later as many places in codegen
3948            can't handle op1 being a constant. This is normally naturally
3949            enforced as constants have the least level of 0. However,
3950            sometimes we end up with a tree like "cns1 < nop(cns2)". In
3951            such cases, both sides have a level of 0. So encourage constants
3952            to be evaluated last in such cases */
3953
3954         if ((level == 0) && (level == lvl2) && (op1->OperKind() & GTK_CONST) &&
3955             (tree->OperIsCommutative() || tree->OperIsCompare()))
3956         {
3957             lvl2++;
3958         }
3959
3960         /* We try to swap operands if the second one is more expensive */
3961         bool     tryToSwap;
3962         GenTree* opA;
3963         GenTree* opB;
3964
3965         if (tree->gtFlags & GTF_REVERSE_OPS)
3966         {
3967             opA = op2;
3968             opB = op1;
3969         }
3970         else
3971         {
3972             opA = op1;
3973             opB = op2;
3974         }
3975
3976         if (fgOrder == FGOrderLinear)
3977         {
3978             // Don't swap anything if we're in linear order; we're really just interested in the costs.
3979             tryToSwap = false;
3980         }
3981         else if (bReverseInAssignment)
3982         {
3983             // Assignments are special, we want the reverseops flags
3984             // so if possible it was set above.
3985             tryToSwap = false;
3986         }
3987         else if ((oper == GT_INTRINSIC) && IsIntrinsicImplementedByUserCall(tree->AsIntrinsic()->gtIntrinsicId))
3988         {
3989             // We do not swap operand execution order for intrinsics that are implemented by user calls
3990             // because of trickiness around ensuring the execution order does not change during rationalization.
3991             tryToSwap = false;
3992         }
3993         else
3994         {
3995             if (tree->gtFlags & GTF_REVERSE_OPS)
3996             {
3997                 tryToSwap = (level > lvl2);
3998             }
3999             else
4000             {
4001                 tryToSwap = (level < lvl2);
4002             }
4003
4004             // Try to force extra swapping when in the stress mode:
4005             if (compStressCompile(STRESS_REVERSE_FLAG, 60) && ((tree->gtFlags & GTF_REVERSE_OPS) == 0) &&
4006                 ((op2->OperKind() & GTK_CONST) == 0))
4007             {
4008                 tryToSwap = true;
4009             }
4010         }
4011
4012         if (tryToSwap)
4013         {
4014             bool canSwap = gtCanSwapOrder(opA, opB);
4015
4016             if (canSwap)
4017             {
4018                 /* Can we swap the order by commuting the operands? */
4019
4020                 switch (oper)
4021                 {
4022                     case GT_EQ:
4023                     case GT_NE:
4024                     case GT_LT:
4025                     case GT_LE:
4026                     case GT_GE:
4027                     case GT_GT:
4028                         if (GenTree::SwapRelop(oper) != oper)
4029                         {
4030                             tree->SetOper(GenTree::SwapRelop(oper), GenTree::PRESERVE_VN);
4031                         }
4032
4033                         __fallthrough;
4034
4035                     case GT_ADD:
4036                     case GT_MUL:
4037
4038                     case GT_OR:
4039                     case GT_XOR:
4040                     case GT_AND:
4041
4042                         /* Swap the operands */
4043
4044                         tree->gtOp.gtOp1 = op2;
4045                         tree->gtOp.gtOp2 = op1;
4046                         break;
4047
4048                     case GT_QMARK:
4049                     case GT_COLON:
4050                     case GT_MKREFANY:
4051                         break;
4052
4053                     case GT_LIST:
4054                     case GT_FIELD_LIST:
4055                         break;
4056
4057                     default:
4058
4059                         /* Mark the operand's evaluation order to be swapped */
4060                         if (tree->gtFlags & GTF_REVERSE_OPS)
4061                         {
4062                             tree->gtFlags &= ~GTF_REVERSE_OPS;
4063                         }
4064                         else
4065                         {
4066                             tree->gtFlags |= GTF_REVERSE_OPS;
4067                         }
4068
4069                         break;
4070                 }
4071             }
4072         }
4073
4074         /* Swap the level counts */
4075         if (tree->gtFlags & GTF_REVERSE_OPS)
4076         {
4077             unsigned tmpl;
4078
4079             tmpl  = level;
4080             level = lvl2;
4081             lvl2  = tmpl;
4082         }
4083
4084         /* Compute the sethi number for this binary operator */
4085
4086         if (level < 1)
4087         {
4088             level = lvl2;
4089         }
4090         else if (level == lvl2)
4091         {
4092             level += 1;
4093         }
4094
4095         goto DONE;
4096     }
4097
4098     /* See what kind of a special operator we have here */
4099
4100     switch (oper)
4101     {
4102         unsigned lvl2; // Scratch variable
4103
4104         case GT_CALL:
4105
4106             assert(tree->gtFlags & GTF_CALL);
4107
4108             level  = 0;
4109             costEx = 5;
4110             costSz = 2;
4111
4112             /* Evaluate the 'this' argument, if present */
4113
4114             if (tree->gtCall.gtCallObjp)
4115             {
4116                 GenTree* thisVal = tree->gtCall.gtCallObjp;
4117
4118                 lvl2 = gtSetEvalOrder(thisVal);
4119                 if (level < lvl2)
4120                 {
4121                     level = lvl2;
4122                 }
4123                 costEx += thisVal->gtCostEx;
4124                 costSz += thisVal->gtCostSz + 1;
4125             }
4126
4127             /* Evaluate the arguments, right to left */
4128
4129             if (tree->gtCall.gtCallArgs)
4130             {
4131                 const bool isListCallArgs = true;
4132                 const bool callArgsInRegs = false;
4133                 lvl2                      = gtSetListOrder(tree->gtCall.gtCallArgs, isListCallArgs, callArgsInRegs);
4134                 if (level < lvl2)
4135                 {
4136                     level = lvl2;
4137                 }
4138                 costEx += tree->gtCall.gtCallArgs->gtCostEx;
4139                 costSz += tree->gtCall.gtCallArgs->gtCostSz;
4140             }
4141
4142             /* Evaluate the temp register arguments list
4143              * This is a "hidden" list and its only purpose is to
4144              * extend the life of temps until we make the call */
4145
4146             if (tree->gtCall.gtCallLateArgs)
4147             {
4148                 const bool isListCallArgs = true;
4149                 const bool callArgsInRegs = true;
4150                 lvl2                      = gtSetListOrder(tree->gtCall.gtCallLateArgs, isListCallArgs, callArgsInRegs);
4151                 if (level < lvl2)
4152                 {
4153                     level = lvl2;
4154                 }
4155                 costEx += tree->gtCall.gtCallLateArgs->gtCostEx;
4156                 costSz += tree->gtCall.gtCallLateArgs->gtCostSz;
4157             }
4158
4159             if (tree->gtCall.gtCallType == CT_INDIRECT)
4160             {
4161                 // pinvoke-calli cookie is a constant, or constant indirection
4162                 assert(tree->gtCall.gtCallCookie == nullptr || tree->gtCall.gtCallCookie->gtOper == GT_CNS_INT ||
4163                        tree->gtCall.gtCallCookie->gtOper == GT_IND);
4164
4165                 GenTree* indirect = tree->gtCall.gtCallAddr;
4166
4167                 lvl2 = gtSetEvalOrder(indirect);
4168                 if (level < lvl2)
4169                 {
4170                     level = lvl2;
4171                 }
4172                 costEx += indirect->gtCostEx + IND_COST_EX;
4173                 costSz += indirect->gtCostSz;
4174             }
4175             else
4176             {
4177 #ifdef _TARGET_ARM_
4178                 if (tree->gtCall.IsVirtualStub())
4179                 {
4180                     // We generate movw/movt/ldr
4181                     costEx += (1 + IND_COST_EX);
4182                     costSz += 8;
4183                     if (tree->gtCall.gtCallMoreFlags & GTF_CALL_M_VIRTSTUB_REL_INDIRECT)
4184                     {
4185                         // Must use R12 for the ldr target -- REG_JUMP_THUNK_PARAM
4186                         costSz += 2;
4187                     }
4188                 }
4189                 else if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
4190                 {
4191                     costEx += 2;
4192                     costSz += 6;
4193                 }
4194                 costSz += 2;
4195 #endif
4196 #ifdef _TARGET_XARCH_
4197                 costSz += 3;
4198 #endif
4199             }
4200
4201             level += 1;
4202
4203             /* Virtual calls are a bit more expensive */
4204             if (tree->gtCall.IsVirtual())
4205             {
4206                 costEx += 2 * IND_COST_EX;
4207                 costSz += 2;
4208             }
4209
4210             level += 5;
4211             costEx += 3 * IND_COST_EX;
4212             break;
4213
4214         case GT_ARR_ELEM:
4215
4216             level  = gtSetEvalOrder(tree->gtArrElem.gtArrObj);
4217             costEx = tree->gtArrElem.gtArrObj->gtCostEx;
4218             costSz = tree->gtArrElem.gtArrObj->gtCostSz;
4219
4220             unsigned dim;
4221             for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
4222             {
4223                 lvl2 = gtSetEvalOrder(tree->gtArrElem.gtArrInds[dim]);
4224                 if (level < lvl2)
4225                 {
4226                     level = lvl2;
4227                 }
4228                 costEx += tree->gtArrElem.gtArrInds[dim]->gtCostEx;
4229                 costSz += tree->gtArrElem.gtArrInds[dim]->gtCostSz;
4230             }
4231
4232             level += tree->gtArrElem.gtArrRank;
4233             costEx += 2 + (tree->gtArrElem.gtArrRank * (IND_COST_EX + 1));
4234             costSz += 2 + (tree->gtArrElem.gtArrRank * 2);
4235             break;
4236
4237         case GT_ARR_OFFSET:
4238             level  = gtSetEvalOrder(tree->gtArrOffs.gtOffset);
4239             costEx = tree->gtArrOffs.gtOffset->gtCostEx;
4240             costSz = tree->gtArrOffs.gtOffset->gtCostSz;
4241             lvl2   = gtSetEvalOrder(tree->gtArrOffs.gtIndex);
4242             level  = max(level, lvl2);
4243             costEx += tree->gtArrOffs.gtIndex->gtCostEx;
4244             costSz += tree->gtArrOffs.gtIndex->gtCostSz;
4245             lvl2  = gtSetEvalOrder(tree->gtArrOffs.gtArrObj);
4246             level = max(level, lvl2);
4247             costEx += tree->gtArrOffs.gtArrObj->gtCostEx;
4248             costSz += tree->gtArrOffs.gtArrObj->gtCostSz;
4249             break;
4250
4251         case GT_CMPXCHG:
4252
4253             level  = gtSetEvalOrder(tree->gtCmpXchg.gtOpLocation);
4254             costSz = tree->gtCmpXchg.gtOpLocation->gtCostSz;
4255
4256             lvl2 = gtSetEvalOrder(tree->gtCmpXchg.gtOpValue);
4257             if (level < lvl2)
4258             {
4259                 level = lvl2;
4260             }
4261             costSz += tree->gtCmpXchg.gtOpValue->gtCostSz;
4262
4263             lvl2 = gtSetEvalOrder(tree->gtCmpXchg.gtOpComparand);
4264             if (level < lvl2)
4265             {
4266                 level = lvl2;
4267             }
4268             costSz += tree->gtCmpXchg.gtOpComparand->gtCostSz;
4269
4270             costEx = MAX_COST; // Seriously, what could be more expensive than lock cmpxchg?
4271             costSz += 5;       // size of lock cmpxchg [reg+C], reg
4272             break;
4273
4274         case GT_ARR_BOUNDS_CHECK:
4275 #ifdef FEATURE_SIMD
4276         case GT_SIMD_CHK:
4277 #endif // FEATURE_SIMD
4278 #ifdef FEATURE_HW_INTRINSICS
4279         case GT_HW_INTRINSIC_CHK:
4280 #endif // FEATURE_HW_INTRINSICS
4281
4282             costEx = 4; // cmp reg,reg and jae throw (not taken)
4283             costSz = 7; // jump to cold section
4284
4285             level = gtSetEvalOrder(tree->gtBoundsChk.gtIndex);
4286             costEx += tree->gtBoundsChk.gtIndex->gtCostEx;
4287             costSz += tree->gtBoundsChk.gtIndex->gtCostSz;
4288
4289             lvl2 = gtSetEvalOrder(tree->gtBoundsChk.gtArrLen);
4290             if (level < lvl2)
4291             {
4292                 level = lvl2;
4293             }
4294             costEx += tree->gtBoundsChk.gtArrLen->gtCostEx;
4295             costSz += tree->gtBoundsChk.gtArrLen->gtCostSz;
4296
4297             break;
4298
4299         case GT_STORE_DYN_BLK:
4300         case GT_DYN_BLK:
4301         {
4302             costEx = 0;
4303             costSz = 0;
4304             level  = 0;
4305             if (oper == GT_STORE_DYN_BLK)
4306             {
4307                 lvl2  = gtSetEvalOrder(tree->gtDynBlk.Data());
4308                 level = max(level, lvl2);
4309                 costEx += tree->gtDynBlk.Data()->gtCostEx;
4310                 costSz += tree->gtDynBlk.Data()->gtCostSz;
4311             }
4312             lvl2               = gtSetEvalOrder(tree->gtDynBlk.Addr());
4313             level              = max(level, lvl2);
4314             costEx             = tree->gtDynBlk.Addr()->gtCostEx;
4315             costSz             = tree->gtDynBlk.Addr()->gtCostSz;
4316             unsigned sizeLevel = gtSetEvalOrder(tree->gtDynBlk.gtDynamicSize);
4317
4318             // Determine whether the size node should be evaluated first.
4319             // We would like to do this if the sizeLevel is larger than the current level,
4320             // but we have to ensure that we obey ordering constraints.
4321             if (tree->AsDynBlk()->gtEvalSizeFirst != (level < sizeLevel))
4322             {
4323                 bool canChange = true;
4324
4325                 GenTree* sizeNode = tree->AsDynBlk()->gtDynamicSize;
4326                 GenTree* dst      = tree->AsDynBlk()->Addr();
4327                 GenTree* src      = tree->AsDynBlk()->Data();
4328
4329                 if (tree->AsDynBlk()->gtEvalSizeFirst)
4330                 {
4331                     canChange = gtCanSwapOrder(sizeNode, dst);
4332                     if (canChange && (src != nullptr))
4333                     {
4334                         canChange = gtCanSwapOrder(sizeNode, src);
4335                     }
4336                 }
4337                 else
4338                 {
4339                     canChange = gtCanSwapOrder(dst, sizeNode);
4340                     if (canChange && (src != nullptr))
4341                     {
4342                         gtCanSwapOrder(src, sizeNode);
4343                     }
4344                 }
4345                 if (canChange)
4346                 {
4347                     tree->AsDynBlk()->gtEvalSizeFirst = (level < sizeLevel);
4348                 }
4349             }
4350             level = max(level, sizeLevel);
4351             costEx += tree->gtDynBlk.gtDynamicSize->gtCostEx;
4352             costSz += tree->gtDynBlk.gtDynamicSize->gtCostSz;
4353         }
4354         break;
4355
4356         case GT_INDEX_ADDR:
4357             costEx = 6; // cmp reg,reg; jae throw; mov reg, [addrmode]  (not taken)
4358             costSz = 9; // jump to cold section
4359
4360             level = gtSetEvalOrder(tree->AsIndexAddr()->Index());
4361             costEx += tree->AsIndexAddr()->Index()->gtCostEx;
4362             costSz += tree->AsIndexAddr()->Index()->gtCostSz;
4363
4364             lvl2 = gtSetEvalOrder(tree->AsIndexAddr()->Arr());
4365             if (level < lvl2)
4366             {
4367                 level = lvl2;
4368             }
4369             costEx += tree->AsIndexAddr()->Arr()->gtCostEx;
4370             costSz += tree->AsIndexAddr()->Arr()->gtCostSz;
4371             break;
4372
4373         default:
4374 #ifdef DEBUG
4375             if (verbose)
4376             {
4377                 printf("unexpected operator in this tree:\n");
4378                 gtDispTree(tree);
4379             }
4380 #endif
4381             NO_WAY("unexpected operator");
4382     }
4383
4384 DONE:
4385
4386 #ifdef FEATURE_HW_INTRINSICS
4387     if ((oper == GT_HWIntrinsic) && (tree->gtGetOp1() == nullptr))
4388     {
4389         // We can have nullary HWIntrinsic nodes, and we must have non-zero cost.
4390         costEx = 1;
4391         costSz = 1;
4392     }
4393 #endif // FEATURE_HW_INTRINSICS
4394
4395     // Some path through this function must have set the costs.
4396     assert(costEx != -1);
4397     assert(costSz != -1);
4398
4399     tree->SetCosts(costEx, costSz);
4400
4401     return level;
4402 }
4403 #ifdef _PREFAST_
4404 #pragma warning(pop)
4405 #endif
4406
4407 /*****************************************************************************
4408  *
4409  *  If the given tree is an integer constant that can be used
4410  *  in a scaled index address mode as a multiplier (e.g. "[4*index]"), then return
4411  *  the scale factor: 2, 4, or 8. Otherwise, return 0. Note that we never return 1,
4412  *  to match the behavior of GetScaleIndexShf().
4413  */
4414
4415 unsigned GenTree::GetScaleIndexMul()
4416 {
4417     if (IsCnsIntOrI() && jitIsScaleIndexMul(gtIntConCommon.IconValue()) && gtIntConCommon.IconValue() != 1)
4418     {
4419         return (unsigned)gtIntConCommon.IconValue();
4420     }
4421
4422     return 0;
4423 }
4424
4425 /*****************************************************************************
4426  *
4427  *  If the given tree is the right-hand side of a left shift (that is,
4428  *  'y' in the tree 'x' << 'y'), and it is an integer constant that can be used
4429  *  in a scaled index address mode as a multiplier (e.g. "[4*index]"), then return
4430  *  the scale factor: 2, 4, or 8. Otherwise, return 0.
4431  */
4432
4433 unsigned GenTree::GetScaleIndexShf()
4434 {
4435     if (IsCnsIntOrI() && jitIsScaleIndexShift(gtIntConCommon.IconValue()))
4436     {
4437         return (unsigned)(1 << gtIntConCommon.IconValue());
4438     }
4439
4440     return 0;
4441 }
4442
4443 /*****************************************************************************
4444  *
4445  *  If the given tree is a scaled index (i.e. "op * 4" or "op << 2"), returns
4446  *  the multiplier: 2, 4, or 8; otherwise returns 0. Note that "1" is never
4447  *  returned.
4448  */
4449
4450 unsigned GenTree::GetScaledIndex()
4451 {
4452     // with (!opts.OptEnabled(CLFLG_CONSTANTFOLD) we can have
4453     //   CNS_INT * CNS_INT
4454     //
4455     if (gtOp.gtOp1->IsCnsIntOrI())
4456     {
4457         return 0;
4458     }
4459
4460     switch (gtOper)
4461     {
4462         case GT_MUL:
4463             return gtOp.gtOp2->GetScaleIndexMul();
4464
4465         case GT_LSH:
4466             return gtOp.gtOp2->GetScaleIndexShf();
4467
4468         default:
4469             assert(!"GenTree::GetScaledIndex() called with illegal gtOper");
4470             break;
4471     }
4472
4473     return 0;
4474 }
4475
4476 /*****************************************************************************
4477  *
4478  *  Returns true if "addr" is a GT_ADD node, at least one of whose arguments is an integer (<= 32 bit)
4479  *  constant.  If it returns true, it sets "*offset" to (one of the) constant value(s), and
4480  *  "*addr" to the other argument.
4481  */
4482
4483 bool GenTree::IsAddWithI32Const(GenTree** addr, int* offset)
4484 {
4485     if (OperGet() == GT_ADD)
4486     {
4487         if (gtOp.gtOp1->IsIntCnsFitsInI32())
4488         {
4489             *offset = (int)gtOp.gtOp1->gtIntCon.gtIconVal;
4490             *addr   = gtOp.gtOp2;
4491             return true;
4492         }
4493         else if (gtOp.gtOp2->IsIntCnsFitsInI32())
4494         {
4495             *offset = (int)gtOp.gtOp2->gtIntCon.gtIconVal;
4496             *addr   = gtOp.gtOp1;
4497             return true;
4498         }
4499     }
4500     // Otherwise...
4501     return false;
4502 }
4503
4504 //------------------------------------------------------------------------
4505 // gtGetChildPointer: If 'parent' is the parent of this node, return the pointer
4506 //    to the child node so that it can be modified; otherwise, return nullptr.
4507 //
4508 // Arguments:
4509 //    parent - The possible parent of this node
4510 //
4511 // Return Value:
4512 //    If "child" is a child of "parent", returns a pointer to the child node in the parent
4513 //    (i.e. a pointer to a GenTree pointer).
4514 //    Otherwise, returns nullptr.
4515 //
4516 // Assumptions:
4517 //    'parent' must be non-null
4518 //
4519 // Notes:
4520 //    When FEATURE_MULTIREG_ARGS is defined we can get here with GT_OBJ tree.
4521 //    This happens when we have a struct that is passed in multiple registers.
4522 //
4523 //    Also note that when UNIX_AMD64_ABI is defined the GT_LDOBJ
4524 //    later gets converted to a GT_FIELD_LIST with two GT_LCL_FLDs in Lower/LowerXArch.
4525 //
4526
4527 GenTree** GenTree::gtGetChildPointer(GenTree* parent) const
4528
4529 {
4530     switch (parent->OperGet())
4531     {
4532         default:
4533             if (!parent->OperIsSimple())
4534             {
4535                 return nullptr;
4536             }
4537             if (this == parent->gtOp.gtOp1)
4538             {
4539                 return &(parent->gtOp.gtOp1);
4540             }
4541             if (this == parent->gtOp.gtOp2)
4542             {
4543                 return &(parent->gtOp.gtOp2);
4544             }
4545             break;
4546
4547         case GT_CMPXCHG:
4548             if (this == parent->gtCmpXchg.gtOpLocation)
4549             {
4550                 return &(parent->gtCmpXchg.gtOpLocation);
4551             }
4552             if (this == parent->gtCmpXchg.gtOpValue)
4553             {
4554                 return &(parent->gtCmpXchg.gtOpValue);
4555             }
4556             if (this == parent->gtCmpXchg.gtOpComparand)
4557             {
4558                 return &(parent->gtCmpXchg.gtOpComparand);
4559             }
4560             break;
4561
4562         case GT_ARR_BOUNDS_CHECK:
4563 #ifdef FEATURE_SIMD
4564         case GT_SIMD_CHK:
4565 #endif // FEATURE_SIMD
4566 #ifdef FEATURE_HW_INTRINSICS
4567         case GT_HW_INTRINSIC_CHK:
4568 #endif // FEATURE_HW_INTRINSICS
4569             if (this == parent->gtBoundsChk.gtIndex)
4570             {
4571                 return &(parent->gtBoundsChk.gtIndex);
4572             }
4573             if (this == parent->gtBoundsChk.gtArrLen)
4574             {
4575                 return &(parent->gtBoundsChk.gtArrLen);
4576             }
4577             if (this == parent->gtBoundsChk.gtIndRngFailBB)
4578             {
4579                 return &(parent->gtBoundsChk.gtIndRngFailBB);
4580             }
4581             break;
4582
4583         case GT_ARR_ELEM:
4584             if (this == parent->gtArrElem.gtArrObj)
4585             {
4586                 return &(parent->gtArrElem.gtArrObj);
4587             }
4588             for (int i = 0; i < GT_ARR_MAX_RANK; i++)
4589             {
4590                 if (this == parent->gtArrElem.gtArrInds[i])
4591                 {
4592                     return &(parent->gtArrElem.gtArrInds[i]);
4593                 }
4594             }
4595             break;
4596
4597         case GT_ARR_OFFSET:
4598             if (this == parent->gtArrOffs.gtOffset)
4599             {
4600                 return &(parent->gtArrOffs.gtOffset);
4601             }
4602             if (this == parent->gtArrOffs.gtIndex)
4603             {
4604                 return &(parent->gtArrOffs.gtIndex);
4605             }
4606             if (this == parent->gtArrOffs.gtArrObj)
4607             {
4608                 return &(parent->gtArrOffs.gtArrObj);
4609             }
4610             break;
4611
4612         case GT_STORE_DYN_BLK:
4613         case GT_DYN_BLK:
4614             if (this == parent->gtDynBlk.gtOp1)
4615             {
4616                 return &(parent->gtDynBlk.gtOp1);
4617             }
4618             if (this == parent->gtDynBlk.gtOp2)
4619             {
4620                 return &(parent->gtDynBlk.gtOp2);
4621             }
4622             if (this == parent->gtDynBlk.gtDynamicSize)
4623             {
4624                 return &(parent->gtDynBlk.gtDynamicSize);
4625             }
4626             break;
4627
4628         case GT_FIELD:
4629             if (this == parent->AsField()->gtFldObj)
4630             {
4631                 return &(parent->AsField()->gtFldObj);
4632             }
4633             break;
4634
4635         case GT_RET_EXPR:
4636             if (this == parent->gtRetExpr.gtInlineCandidate)
4637             {
4638                 return &(parent->gtRetExpr.gtInlineCandidate);
4639             }
4640             break;
4641
4642         case GT_CALL:
4643         {
4644             GenTreeCall* call = parent->AsCall();
4645
4646             if (this == call->gtCallObjp)
4647             {
4648                 return &(call->gtCallObjp);
4649             }
4650             if (this == call->gtCallArgs)
4651             {
4652                 return reinterpret_cast<GenTree**>(&(call->gtCallArgs));
4653             }
4654             if (this == call->gtCallLateArgs)
4655             {
4656                 return reinterpret_cast<GenTree**>(&(call->gtCallLateArgs));
4657             }
4658             if (this == call->gtControlExpr)
4659             {
4660                 return &(call->gtControlExpr);
4661             }
4662             if (call->gtCallType == CT_INDIRECT)
4663             {
4664                 if (this == call->gtCallCookie)
4665                 {
4666                     return &(call->gtCallCookie);
4667                 }
4668                 if (this == call->gtCallAddr)
4669                 {
4670                     return &(call->gtCallAddr);
4671                 }
4672             }
4673         }
4674         break;
4675
4676         case GT_STMT:
4677             noway_assert(!"Illegal node for gtGetChildPointer()");
4678             unreached();
4679     }
4680
4681     return nullptr;
4682 }
4683
4684 bool GenTree::TryGetUse(GenTree* def, GenTree*** use)
4685 {
4686     assert(def != nullptr);
4687     assert(use != nullptr);
4688
4689     switch (OperGet())
4690     {
4691         // Leaf nodes
4692         case GT_LCL_VAR:
4693         case GT_LCL_FLD:
4694         case GT_LCL_VAR_ADDR:
4695         case GT_LCL_FLD_ADDR:
4696         case GT_CATCH_ARG:
4697         case GT_LABEL:
4698         case GT_FTN_ADDR:
4699         case GT_RET_EXPR:
4700         case GT_CNS_INT:
4701         case GT_CNS_LNG:
4702         case GT_CNS_DBL:
4703         case GT_CNS_STR:
4704         case GT_MEMORYBARRIER:
4705         case GT_JMP:
4706         case GT_JCC:
4707         case GT_SETCC:
4708         case GT_NO_OP:
4709         case GT_START_NONGC:
4710         case GT_PROF_HOOK:
4711 #if !FEATURE_EH_FUNCLETS
4712         case GT_END_LFIN:
4713 #endif // !FEATURE_EH_FUNCLETS
4714         case GT_PHI_ARG:
4715         case GT_JMPTABLE:
4716         case GT_CLS_VAR:
4717         case GT_CLS_VAR_ADDR:
4718         case GT_ARGPLACE:
4719         case GT_PHYSREG:
4720         case GT_EMITNOP:
4721         case GT_PINVOKE_PROLOG:
4722         case GT_PINVOKE_EPILOG:
4723         case GT_IL_OFFSET:
4724             return false;
4725
4726         // Standard unary operators
4727         case GT_STORE_LCL_VAR:
4728         case GT_STORE_LCL_FLD:
4729         case GT_NOT:
4730         case GT_NEG:
4731         case GT_COPY:
4732         case GT_RELOAD:
4733         case GT_ARR_LENGTH:
4734         case GT_CAST:
4735         case GT_BITCAST:
4736         case GT_CKFINITE:
4737         case GT_LCLHEAP:
4738         case GT_ADDR:
4739         case GT_IND:
4740         case GT_OBJ:
4741         case GT_BLK:
4742         case GT_BOX:
4743         case GT_ALLOCOBJ:
4744         case GT_RUNTIMELOOKUP:
4745         case GT_INIT_VAL:
4746         case GT_JTRUE:
4747         case GT_SWITCH:
4748         case GT_NULLCHECK:
4749         case GT_PUTARG_REG:
4750         case GT_PUTARG_STK:
4751         case GT_RETURNTRAP:
4752         case GT_NOP:
4753         case GT_RETURN:
4754         case GT_RETFILT:
4755         case GT_BSWAP:
4756         case GT_BSWAP16:
4757             if (def == this->AsUnOp()->gtOp1)
4758             {
4759                 *use = &this->AsUnOp()->gtOp1;
4760                 return true;
4761             }
4762             return false;
4763
4764         // Variadic nodes
4765         case GT_PHI:
4766             assert(this->AsUnOp()->gtOp1 != nullptr);
4767             return this->AsUnOp()->gtOp1->TryGetUseList(def, use);
4768
4769         case GT_FIELD_LIST:
4770             return TryGetUseList(def, use);
4771
4772 #if FEATURE_ARG_SPLIT
4773         case GT_PUTARG_SPLIT:
4774             if (this->AsUnOp()->gtOp1->gtOper == GT_FIELD_LIST)
4775             {
4776                 return this->AsUnOp()->gtOp1->TryGetUseList(def, use);
4777             }
4778             if (def == this->AsUnOp()->gtOp1)
4779             {
4780                 *use = &this->AsUnOp()->gtOp1;
4781                 return true;
4782             }
4783             return false;
4784 #endif // FEATURE_ARG_SPLIT
4785
4786 #ifdef FEATURE_SIMD
4787         case GT_SIMD:
4788             if (this->AsSIMD()->gtSIMDIntrinsicID == SIMDIntrinsicInitN)
4789             {
4790                 assert(this->AsSIMD()->gtOp1 != nullptr);
4791                 return this->AsSIMD()->gtOp1->TryGetUseList(def, use);
4792             }
4793
4794             return TryGetUseBinOp(def, use);
4795 #endif // FEATURE_SIMD
4796
4797 #ifdef FEATURE_HW_INTRINSICS
4798         case GT_HWIntrinsic:
4799             if ((this->AsHWIntrinsic()->gtOp1 != nullptr) && this->AsHWIntrinsic()->gtOp1->OperIsList())
4800             {
4801                 return this->AsHWIntrinsic()->gtOp1->TryGetUseList(def, use);
4802             }
4803
4804             return TryGetUseBinOp(def, use);
4805 #endif // FEATURE_HW_INTRINSICS
4806
4807         // Special nodes
4808         case GT_CMPXCHG:
4809         {
4810             GenTreeCmpXchg* const cmpXchg = this->AsCmpXchg();
4811             if (def == cmpXchg->gtOpLocation)
4812             {
4813                 *use = &cmpXchg->gtOpLocation;
4814                 return true;
4815             }
4816             if (def == cmpXchg->gtOpValue)
4817             {
4818                 *use = &cmpXchg->gtOpValue;
4819                 return true;
4820             }
4821             if (def == cmpXchg->gtOpComparand)
4822             {
4823                 *use = &cmpXchg->gtOpComparand;
4824                 return true;
4825             }
4826             return false;
4827         }
4828
4829         case GT_ARR_BOUNDS_CHECK:
4830 #ifdef FEATURE_SIMD
4831         case GT_SIMD_CHK:
4832 #endif // FEATURE_SIMD
4833 #ifdef FEATURE_HW_INTRINSICS
4834         case GT_HW_INTRINSIC_CHK:
4835 #endif // FEATURE_HW_INTRINSICS
4836         {
4837             GenTreeBoundsChk* const boundsChk = this->AsBoundsChk();
4838             if (def == boundsChk->gtIndex)
4839             {
4840                 *use = &boundsChk->gtIndex;
4841                 return true;
4842             }
4843             if (def == boundsChk->gtArrLen)
4844             {
4845                 *use = &boundsChk->gtArrLen;
4846                 return true;
4847             }
4848             return false;
4849         }
4850
4851         case GT_FIELD:
4852             if (def == this->AsField()->gtFldObj)
4853             {
4854                 *use = &this->AsField()->gtFldObj;
4855                 return true;
4856             }
4857             return false;
4858
4859         case GT_STMT:
4860             if (def == this->AsStmt()->gtStmtExpr)
4861             {
4862                 *use = &this->AsStmt()->gtStmtExpr;
4863                 return true;
4864             }
4865             return false;
4866
4867         case GT_ARR_ELEM:
4868         {
4869             GenTreeArrElem* const arrElem = this->AsArrElem();
4870             if (def == arrElem->gtArrObj)
4871             {
4872                 *use = &arrElem->gtArrObj;
4873                 return true;
4874             }
4875             for (unsigned i = 0; i < arrElem->gtArrRank; i++)
4876             {
4877                 if (def == arrElem->gtArrInds[i])
4878                 {
4879                     *use = &arrElem->gtArrInds[i];
4880                     return true;
4881                 }
4882             }
4883             return false;
4884         }
4885
4886         case GT_ARR_OFFSET:
4887         {
4888             GenTreeArrOffs* const arrOffs = this->AsArrOffs();
4889             if (def == arrOffs->gtOffset)
4890             {
4891                 *use = &arrOffs->gtOffset;
4892                 return true;
4893             }
4894             if (def == arrOffs->gtIndex)
4895             {
4896                 *use = &arrOffs->gtIndex;
4897                 return true;
4898             }
4899             if (def == arrOffs->gtArrObj)
4900             {
4901                 *use = &arrOffs->gtArrObj;
4902                 return true;
4903             }
4904             return false;
4905         }
4906
4907         case GT_DYN_BLK:
4908         {
4909             GenTreeDynBlk* const dynBlock = this->AsDynBlk();
4910             if (def == dynBlock->gtOp1)
4911             {
4912                 *use = &dynBlock->gtOp1;
4913                 return true;
4914             }
4915             if (def == dynBlock->gtDynamicSize)
4916             {
4917                 *use = &dynBlock->gtDynamicSize;
4918                 return true;
4919             }
4920             return false;
4921         }
4922
4923         case GT_STORE_DYN_BLK:
4924         {
4925             GenTreeDynBlk* const dynBlock = this->AsDynBlk();
4926             if (def == dynBlock->gtOp1)
4927             {
4928                 *use = &dynBlock->gtOp1;
4929                 return true;
4930             }
4931             if (def == dynBlock->gtOp2)
4932             {
4933                 *use = &dynBlock->gtOp2;
4934                 return true;
4935             }
4936             if (def == dynBlock->gtDynamicSize)
4937             {
4938                 *use = &dynBlock->gtDynamicSize;
4939                 return true;
4940             }
4941             return false;
4942         }
4943
4944         case GT_CALL:
4945         {
4946             GenTreeCall* const call = this->AsCall();
4947             if (def == call->gtCallObjp)
4948             {
4949                 *use = &call->gtCallObjp;
4950                 return true;
4951             }
4952             if (def == call->gtControlExpr)
4953             {
4954                 *use = &call->gtControlExpr;
4955                 return true;
4956             }
4957             if (call->gtCallType == CT_INDIRECT)
4958             {
4959                 if (def == call->gtCallCookie)
4960                 {
4961                     *use = &call->gtCallCookie;
4962                     return true;
4963                 }
4964                 if (def == call->gtCallAddr)
4965                 {
4966                     *use = &call->gtCallAddr;
4967                     return true;
4968                 }
4969             }
4970             if ((call->gtCallArgs != nullptr) && call->gtCallArgs->TryGetUseList(def, use))
4971             {
4972                 return true;
4973             }
4974
4975             return (call->gtCallLateArgs != nullptr) && call->gtCallLateArgs->TryGetUseList(def, use);
4976         }
4977
4978         // Binary nodes
4979         default:
4980             assert(this->OperIsBinary());
4981             return TryGetUseBinOp(def, use);
4982     }
4983 }
4984
4985 bool GenTree::TryGetUseList(GenTree* def, GenTree*** use)
4986 {
4987     assert(def != nullptr);
4988     assert(use != nullptr);
4989
4990     for (GenTreeArgList* node = this->AsArgList(); node != nullptr; node = node->Rest())
4991     {
4992         if (def == node->gtOp1)
4993         {
4994             *use = &node->gtOp1;
4995             return true;
4996         }
4997     }
4998     return false;
4999 }
5000
5001 bool GenTree::TryGetUseBinOp(GenTree* def, GenTree*** use)
5002 {
5003     assert(def != nullptr);
5004     assert(use != nullptr);
5005     assert(this->OperIsBinary());
5006
5007     GenTreeOp* const binOp = this->AsOp();
5008     if (def == binOp->gtOp1)
5009     {
5010         *use = &binOp->gtOp1;
5011         return true;
5012     }
5013     if (def == binOp->gtOp2)
5014     {
5015         *use = &binOp->gtOp2;
5016         return true;
5017     }
5018     return false;
5019 }
5020
5021 //------------------------------------------------------------------------
5022 // GenTree::ReplaceOperand:
5023 //    Replace a given operand to this node with a new operand. If the
5024 //    current node is a call node, this will also udpate the call
5025 //    argument table if necessary.
5026 //
5027 // Arguments:
5028 //    useEdge - the use edge that points to the operand to be replaced.
5029 //    replacement - the replacement node.
5030 //
5031 void GenTree::ReplaceOperand(GenTree** useEdge, GenTree* replacement)
5032 {
5033     assert(useEdge != nullptr);
5034     assert(replacement != nullptr);
5035     assert(TryGetUse(*useEdge, &useEdge));
5036
5037     if (OperGet() == GT_CALL)
5038     {
5039         AsCall()->ReplaceCallOperand(useEdge, replacement);
5040     }
5041     else
5042     {
5043         *useEdge = replacement;
5044     }
5045 }
5046
5047 //------------------------------------------------------------------------
5048 // gtGetParent: Get the parent of this node, and optionally capture the
5049 //    pointer to the child so that it can be modified.
5050 //
5051 // Arguments:
5052
5053 //    parentChildPointer - A pointer to a GenTree** (yes, that's three
5054 //                         levels, i.e. GenTree ***), which if non-null,
5055 //                         will be set to point to the field in the parent
5056 //                         that points to this node.
5057 //
5058 //    Return value       - The parent of this node.
5059 //
5060 //    Notes:
5061 //
5062 //    This requires that the execution order must be defined (i.e. gtSetEvalOrder() has been called).
5063 //    To enable the child to be replaced, it accepts an argument, parentChildPointer that, if non-null,
5064 //    will be set to point to the child pointer in the parent that points to this node.
5065
5066 GenTree* GenTree::gtGetParent(GenTree*** parentChildPtrPtr) const
5067 {
5068     // Find the parent node; it must be after this node in the execution order.
5069     GenTree** parentChildPtr = nullptr;
5070     GenTree*  parent;
5071     for (parent = gtNext; parent != nullptr; parent = parent->gtNext)
5072     {
5073         parentChildPtr = gtGetChildPointer(parent);
5074         if (parentChildPtr != nullptr)
5075         {
5076             break;
5077         }
5078     }
5079     if (parentChildPtrPtr != nullptr)
5080     {
5081         *parentChildPtrPtr = parentChildPtr;
5082     }
5083     return parent;
5084 }
5085
5086 //------------------------------------------------------------------------------
5087 // OperRequiresAsgFlag : Check whether the operation requires GTF_ASG flag regardless
5088 //                       of the children's flags.
5089 //
5090
5091 bool GenTree::OperRequiresAsgFlag()
5092 {
5093     if (OperIs(GT_ASG) || OperIs(GT_XADD, GT_XCHG, GT_LOCKADD, GT_CMPXCHG, GT_MEMORYBARRIER))
5094     {
5095         return true;
5096     }
5097 #ifdef FEATURE_HW_INTRINSICS
5098     if (gtOper == GT_HWIntrinsic)
5099     {
5100         GenTreeHWIntrinsic* hwIntrinsicNode = this->AsHWIntrinsic();
5101         if (hwIntrinsicNode->OperIsMemoryStore())
5102         {
5103             // A MemoryStore operation is an assignment
5104             return true;
5105         }
5106     }
5107 #endif // FEATURE_HW_INTRINSICS
5108     return false;
5109 }
5110
5111 //------------------------------------------------------------------------------
5112 // OperRequiresCallFlag : Check whether the operation requires GTF_CALL flag regardless
5113 //                        of the children's flags.
5114 //
5115
5116 bool GenTree::OperRequiresCallFlag(Compiler* comp)
5117 {
5118     switch (gtOper)
5119     {
5120         case GT_CALL:
5121             return true;
5122
5123         case GT_INTRINSIC:
5124             return comp->IsIntrinsicImplementedByUserCall(this->AsIntrinsic()->gtIntrinsicId);
5125
5126 #if FEATURE_FIXED_OUT_ARGS && !defined(_TARGET_64BIT_)
5127         case GT_LSH:
5128         case GT_RSH:
5129         case GT_RSZ:
5130
5131             // Variable shifts of a long end up being helper calls, so mark the tree as such in morph.
5132             // This is potentially too conservative, since they'll get treated as having side effects.
5133             // It is important to mark them as calls so if they are part of an argument list,
5134             // they will get sorted and processed properly (for example, it is important to handle
5135             // all nested calls before putting struct arguments in the argument registers). We
5136             // could mark the trees just before argument processing, but it would require a full
5137             // tree walk of the argument tree, so we just do it when morphing, instead, even though we'll
5138             // mark non-argument trees (that will still get converted to calls, anyway).
5139             return (this->TypeGet() == TYP_LONG) && (gtGetOp2()->OperGet() != GT_CNS_INT);
5140 #endif // FEATURE_FIXED_OUT_ARGS && !_TARGET_64BIT_
5141
5142         default:
5143             return false;
5144     }
5145 }
5146
5147 //------------------------------------------------------------------------------
5148 // OperIsImplicitIndir : Check whether the operation contains an implicit
5149 //                       indirection.
5150 // Arguments:
5151 //    this      -  a GenTree node
5152 //
5153 // Return Value:
5154 //    True if the given node contains an implicit indirection
5155 //
5156 // Note that for the GT_HWIntrinsic node we have to examine the
5157 // details of the node to determine its result.
5158 //
5159
5160 bool GenTree::OperIsImplicitIndir() const
5161 {
5162     switch (gtOper)
5163     {
5164         case GT_LOCKADD:
5165         case GT_XADD:
5166         case GT_XCHG:
5167         case GT_CMPXCHG:
5168         case GT_BLK:
5169         case GT_OBJ:
5170         case GT_DYN_BLK:
5171         case GT_STORE_BLK:
5172         case GT_STORE_OBJ:
5173         case GT_STORE_DYN_BLK:
5174         case GT_BOX:
5175         case GT_ARR_INDEX:
5176         case GT_ARR_ELEM:
5177         case GT_ARR_OFFSET:
5178             return true;
5179 #ifdef FEATURE_HW_INTRINSICS
5180         case GT_HWIntrinsic:
5181         {
5182             GenTreeHWIntrinsic* hwIntrinsicNode = (const_cast<GenTree*>(this))->AsHWIntrinsic();
5183             return hwIntrinsicNode->OperIsMemoryLoadOrStore();
5184         }
5185 #endif // FEATURE_HW_INTRINSICS
5186         default:
5187             return false;
5188     }
5189 }
5190
5191 //------------------------------------------------------------------------------
5192 // OperMayThrow : Check whether the operation may throw.
5193 //
5194 //
5195 // Arguments:
5196 //    comp      -  Compiler instance
5197 //
5198 // Return Value:
5199 //    True if the given operator may cause an exception
5200
5201 bool GenTree::OperMayThrow(Compiler* comp)
5202 {
5203     GenTree* op;
5204
5205     switch (gtOper)
5206     {
5207         case GT_MOD:
5208         case GT_DIV:
5209         case GT_UMOD:
5210         case GT_UDIV:
5211
5212             /* Division with a non-zero, non-minus-one constant does not throw an exception */
5213
5214             op = gtOp.gtOp2;
5215
5216             if (varTypeIsFloating(op->TypeGet()))
5217             {
5218                 return false; // Floating point division does not throw.
5219             }
5220
5221             // For integers only division by 0 or by -1 can throw
5222             if (op->IsIntegralConst() && !op->IsIntegralConst(0) && !op->IsIntegralConst(-1))
5223             {
5224                 return false;
5225             }
5226             return true;
5227
5228         case GT_INTRINSIC:
5229             // If this is an intrinsic that represents the object.GetType(), it can throw an NullReferenceException.
5230             // Report it as may throw.
5231             // Note: Some of the rest of the existing intrinsics could potentially throw an exception (for example
5232             //       the array and string element access ones). They are handled differently than the GetType intrinsic
5233             //       and are not marked with GTF_EXCEPT. If these are revisited at some point to be marked as
5234             //       GTF_EXCEPT,
5235             //       the code below might need to be specialized to handle them properly.
5236             if ((this->gtFlags & GTF_EXCEPT) != 0)
5237             {
5238                 return true;
5239             }
5240
5241             break;
5242
5243         case GT_CALL:
5244
5245             CorInfoHelpFunc helper;
5246             helper = comp->eeGetHelperNum(this->AsCall()->gtCallMethHnd);
5247             return ((helper == CORINFO_HELP_UNDEF) || !comp->s_helperCallProperties.NoThrow(helper));
5248
5249         case GT_IND:
5250         case GT_BLK:
5251         case GT_OBJ:
5252         case GT_DYN_BLK:
5253         case GT_STORE_BLK:
5254         case GT_NULLCHECK:
5255             return (((this->gtFlags & GTF_IND_NONFAULTING) == 0) && comp->fgAddrCouldBeNull(this->AsIndir()->Addr()));
5256
5257         case GT_ARR_LENGTH:
5258             return (((this->gtFlags & GTF_IND_NONFAULTING) == 0) &&
5259                     comp->fgAddrCouldBeNull(this->AsArrLen()->ArrRef()));
5260
5261         case GT_ARR_ELEM:
5262             return comp->fgAddrCouldBeNull(this->gtArrElem.gtArrObj);
5263
5264         case GT_ARR_BOUNDS_CHECK:
5265         case GT_ARR_INDEX:
5266         case GT_ARR_OFFSET:
5267         case GT_LCLHEAP:
5268         case GT_CKFINITE:
5269 #ifdef FEATURE_SIMD
5270         case GT_SIMD_CHK:
5271 #endif // FEATURE_SIMD
5272 #ifdef FEATURE_HW_INTRINSICS
5273         case GT_HW_INTRINSIC_CHK:
5274 #endif // FEATURE_HW_INTRINSICS
5275         case GT_INDEX_ADDR:
5276             return true;
5277
5278 #ifdef FEATURE_HW_INTRINSICS
5279         case GT_HWIntrinsic:
5280         {
5281             GenTreeHWIntrinsic* hwIntrinsicNode = this->AsHWIntrinsic();
5282             assert(hwIntrinsicNode != nullptr);
5283             if (hwIntrinsicNode->OperIsMemoryLoadOrStore())
5284             {
5285                 // This operation contains an implicit indirection
5286                 //   it could throw a null reference exception.
5287                 //
5288                 return true;
5289             }
5290         }
5291 #endif // FEATURE_HW_INTRINSICS
5292
5293         default:
5294             break;
5295     }
5296
5297     /* Overflow arithmetic operations also throw exceptions */
5298
5299     if (gtOverflowEx())
5300     {
5301         return true;
5302     }
5303
5304     return false;
5305 }
5306
5307 #if DEBUGGABLE_GENTREE
5308 // static
5309 GenTree::VtablePtr GenTree::s_vtablesForOpers[] = {nullptr};
5310 GenTree::VtablePtr GenTree::s_vtableForOp       = nullptr;
5311
5312 GenTree::VtablePtr GenTree::GetVtableForOper(genTreeOps oper)
5313 {
5314     noway_assert(oper < GT_COUNT);
5315
5316     // First, check a cache.
5317
5318     if (s_vtablesForOpers[oper] != nullptr)
5319     {
5320         return s_vtablesForOpers[oper];
5321     }
5322
5323     // Otherwise, look up the correct vtable entry. Note that we want the most derived GenTree subtype
5324     // for an oper. E.g., GT_LCL_VAR is defined in GTSTRUCT_3 as GenTreeLclVar and in GTSTRUCT_N as
5325     // GenTreeLclVarCommon. We want the GenTreeLclVar vtable, since nothing should actually be
5326     // instantiated as a GenTreeLclVarCommon.
5327
5328     VtablePtr res = nullptr;
5329     switch (oper)
5330     {
5331
5332 // clang-format off
5333
5334 #define GTSTRUCT_0(nm, tag)                             /*handle explicitly*/
5335 #define GTSTRUCT_1(nm, tag)                             \
5336         case tag:                                       \
5337         {                                               \
5338             GenTree##nm gt;                             \
5339             res = *reinterpret_cast<VtablePtr*>(&gt);   \
5340         }                                               \
5341         break;
5342 #define GTSTRUCT_2(nm, tag, tag2)                       \
5343         case tag:                                       \
5344         case tag2:                                      \
5345         {                                               \
5346             GenTree##nm gt;                             \
5347             res = *reinterpret_cast<VtablePtr*>(&gt);   \
5348         }                                               \
5349         break;
5350 #define GTSTRUCT_3(nm, tag, tag2, tag3)                 \
5351         case tag:                                       \
5352         case tag2:                                      \
5353         case tag3:                                      \
5354         {                                               \
5355             GenTree##nm gt;                             \
5356             res = *reinterpret_cast<VtablePtr*>(&gt);   \
5357         }                                               \
5358         break;
5359 #define GTSTRUCT_4(nm, tag, tag2, tag3, tag4)           \
5360         case tag:                                       \
5361         case tag2:                                      \
5362         case tag3:                                      \
5363         case tag4:                                      \
5364         {                                               \
5365             GenTree##nm gt;                             \
5366             res = *reinterpret_cast<VtablePtr*>(&gt);   \
5367         }                                               \
5368         break;
5369 #define GTSTRUCT_N(nm, ...)                             /*handle explicitly*/
5370 #define GTSTRUCT_2_SPECIAL(nm, tag, tag2)               /*handle explicitly*/
5371 #define GTSTRUCT_3_SPECIAL(nm, tag, tag2, tag3)         /*handle explicitly*/
5372 #include "gtstructs.h"
5373
5374         // clang-format on
5375
5376         // Handle the special cases.
5377         // The following opers are in GTSTRUCT_N but no other place (namely, no subtypes).
5378
5379         case GT_STORE_BLK:
5380         case GT_BLK:
5381         {
5382             GenTreeBlk gt;
5383             res = *reinterpret_cast<VtablePtr*>(&gt);
5384         }
5385         break;
5386
5387         case GT_IND:
5388         case GT_NULLCHECK:
5389         {
5390             GenTreeIndir gt;
5391             res = *reinterpret_cast<VtablePtr*>(&gt);
5392         }
5393         break;
5394
5395         // Handle GT_LIST (but not GT_FIELD_LIST, which is also in a GTSTRUCT_1).
5396
5397         case GT_LIST:
5398         {
5399             GenTreeArgList gt;
5400             res = *reinterpret_cast<VtablePtr*>(&gt);
5401         }
5402         break;
5403
5404         // We don't need to handle GTSTRUCT_N for LclVarCommon, since all those allowed opers are specified
5405         // in their proper subtype. Similarly for GenTreeIndir.
5406
5407         default:
5408         {
5409             // Should be unary or binary op.
5410             if (s_vtableForOp == nullptr)
5411             {
5412                 unsigned opKind = OperKind(oper);
5413                 assert(!IsExOp(opKind));
5414                 assert(OperIsSimple(oper) || OperIsLeaf(oper));
5415                 // Need to provide non-null operands.
5416                 GenTreeIntCon dummyOp(TYP_INT, 0);
5417                 GenTreeOp     gt(oper, TYP_INT, &dummyOp, ((opKind & GTK_UNOP) ? nullptr : &dummyOp));
5418                 s_vtableForOp = *reinterpret_cast<VtablePtr*>(&gt);
5419             }
5420             res = s_vtableForOp;
5421             break;
5422         }
5423     }
5424     s_vtablesForOpers[oper] = res;
5425     return res;
5426 }
5427
5428 void GenTree::SetVtableForOper(genTreeOps oper)
5429 {
5430     *reinterpret_cast<VtablePtr*>(this) = GetVtableForOper(oper);
5431 }
5432 #endif // DEBUGGABLE_GENTREE
5433
5434 GenTree* Compiler::gtNewOperNode(genTreeOps oper, var_types type, GenTree* op1, GenTree* op2)
5435 {
5436     assert(op1 != nullptr);
5437     assert(op2 != nullptr);
5438
5439     // We should not be allocating nodes that extend GenTreeOp with this;
5440     // should call the appropriate constructor for the extended type.
5441     assert(!GenTree::IsExOp(GenTree::OperKind(oper)));
5442
5443     GenTree* node = new (this, oper) GenTreeOp(oper, type, op1, op2);
5444
5445     return node;
5446 }
5447
5448 GenTree* Compiler::gtNewQmarkNode(var_types type, GenTree* cond, GenTree* colon)
5449 {
5450     compQmarkUsed = true;
5451     cond->gtFlags |= GTF_RELOP_QMARK;
5452     GenTree* result = new (this, GT_QMARK) GenTreeQmark(type, cond, colon, this);
5453 #ifdef DEBUG
5454     if (compQmarkRationalized)
5455     {
5456         fgCheckQmarkAllowedForm(result);
5457     }
5458 #endif
5459     return result;
5460 }
5461
5462 GenTreeQmark::GenTreeQmark(var_types type, GenTree* cond, GenTree* colonOp, Compiler* comp)
5463     : GenTreeOp(GT_QMARK, type, cond, colonOp)
5464 {
5465     // These must follow a specific form.
5466     assert(cond != nullptr && cond->TypeGet() == TYP_INT);
5467     assert(colonOp != nullptr && colonOp->OperGet() == GT_COLON);
5468 }
5469
5470 GenTreeIntCon* Compiler::gtNewIconNode(ssize_t value, var_types type)
5471 {
5472     return new (this, GT_CNS_INT) GenTreeIntCon(type, value);
5473 }
5474
5475 // return a new node representing the value in a physical register
5476 GenTree* Compiler::gtNewPhysRegNode(regNumber reg, var_types type)
5477 {
5478     assert(genIsValidIntReg(reg) || (reg == REG_SPBASE));
5479     GenTree* result = new (this, GT_PHYSREG) GenTreePhysReg(reg, type);
5480     return result;
5481 }
5482
5483 GenTree* Compiler::gtNewJmpTableNode()
5484 {
5485     GenTree* node                     = new (this, GT_JMPTABLE) GenTreeJumpTable(TYP_INT);
5486     node->gtJumpTable.gtJumpTableAddr = 0;
5487     return node;
5488 }
5489
5490 /*****************************************************************************
5491  *
5492  *  Converts an annotated token into an icon flags (so that we will later be
5493  *  able to tell the type of the handle that will be embedded in the icon
5494  *  node)
5495  */
5496
5497 unsigned Compiler::gtTokenToIconFlags(unsigned token)
5498 {
5499     unsigned flags = 0;
5500
5501     switch (TypeFromToken(token))
5502     {
5503         case mdtTypeRef:
5504         case mdtTypeDef:
5505         case mdtTypeSpec:
5506             flags = GTF_ICON_CLASS_HDL;
5507             break;
5508
5509         case mdtMethodDef:
5510             flags = GTF_ICON_METHOD_HDL;
5511             break;
5512
5513         case mdtFieldDef:
5514             flags = GTF_ICON_FIELD_HDL;
5515             break;
5516
5517         default:
5518             flags = GTF_ICON_TOKEN_HDL;
5519             break;
5520     }
5521
5522     return flags;
5523 }
5524
5525 //-----------------------------------------------------------------------------------------
5526 // gtNewIndOfIconHandleNode: Creates an indirection GenTree node of a constant handle
5527 //
5528 // Arguments:
5529 //    indType     - The type returned by the indirection node
5530 //    addr        - The constant address to read from
5531 //    iconFlags   - The GTF_ICON flag value that specifies the kind of handle that we have
5532 //    isInvariant - The indNode should also be marked as invariant
5533 //
5534 // Return Value:
5535 //    Returns a GT_IND node representing value at the address provided by 'value'
5536 //
5537 // Notes:
5538 //    The GT_IND node is marked as non-faulting
5539 //    If the indType is GT_REF we also mark the indNode as GTF_GLOB_REF
5540 //
5541
5542 GenTree* Compiler::gtNewIndOfIconHandleNode(var_types indType, size_t addr, unsigned iconFlags, bool isInvariant)
5543 {
5544     GenTree* addrNode = gtNewIconHandleNode(addr, iconFlags);
5545     GenTree* indNode  = gtNewOperNode(GT_IND, indType, addrNode);
5546
5547     // This indirection won't cause an exception.
5548     //
5549     indNode->gtFlags |= GTF_IND_NONFAULTING;
5550
5551     // String Literal handles are indirections that return a TYP_REF.
5552     // They are pointers into the GC heap and they are not invariant
5553     // as the address is a reportable GC-root and as such it can be
5554     // modified during a GC collection
5555     //
5556     if (indType == TYP_REF)
5557     {
5558         // This indirection points into the gloabal heap
5559         indNode->gtFlags |= GTF_GLOB_REF;
5560     }
5561     if (isInvariant)
5562     {
5563         // This indirection also is invariant.
5564         indNode->gtFlags |= GTF_IND_INVARIANT;
5565     }
5566     return indNode;
5567 }
5568
5569 /*****************************************************************************
5570  *
5571  *  Allocates a integer constant entry that represents a HANDLE to something.
5572  *  It may not be allowed to embed HANDLEs directly into the JITed code (for eg,
5573  *  as arguments to JIT helpers). Get a corresponding value that can be embedded.
5574  *  If the handle needs to be accessed via an indirection, pValue points to it.
5575  */
5576
5577 GenTree* Compiler::gtNewIconEmbHndNode(void* value, void* pValue, unsigned iconFlags, void* compileTimeHandle)
5578 {
5579     GenTree* iconNode;
5580     GenTree* handleNode;
5581
5582     if (value != nullptr)
5583     {
5584         // When 'value' is non-null, pValue is required to be null
5585         assert(pValue == nullptr);
5586
5587         // use 'value' to construct an integer constant node
5588         iconNode = gtNewIconHandleNode((size_t)value, iconFlags);
5589
5590         // 'value' is the handle
5591         handleNode = iconNode;
5592     }
5593     else
5594     {
5595         // When 'value' is null, pValue is required to be non-null
5596         assert(pValue != nullptr);
5597
5598         // use 'pValue' to construct an integer constant node
5599         iconNode = gtNewIconHandleNode((size_t)pValue, iconFlags);
5600
5601         // 'pValue' is an address of a location that contains the handle
5602
5603         // construct the indirection of 'pValue'
5604         handleNode = gtNewOperNode(GT_IND, TYP_I_IMPL, iconNode);
5605
5606         // This indirection won't cause an exception.
5607         handleNode->gtFlags |= GTF_IND_NONFAULTING;
5608 #if 0
5609         // It should also be invariant, but marking it as such leads to bad diffs.
5610
5611         // This indirection also is invariant.
5612         handleNode->gtFlags |= GTF_IND_INVARIANT;
5613 #endif
5614     }
5615
5616     iconNode->gtIntCon.gtCompileTimeHandle = (size_t)compileTimeHandle;
5617
5618     return handleNode;
5619 }
5620
5621 /*****************************************************************************/
5622 GenTree* Compiler::gtNewStringLiteralNode(InfoAccessType iat, void* pValue)
5623 {
5624     GenTree* tree = nullptr;
5625
5626     switch (iat)
5627     {
5628         case IAT_VALUE: // constructStringLiteral in CoreRT case can return IAT_VALUE
5629             tree         = gtNewIconEmbHndNode(pValue, nullptr, GTF_ICON_STR_HDL, nullptr);
5630             tree->gtType = TYP_REF;
5631             tree         = gtNewOperNode(GT_NOP, TYP_REF, tree); // prevents constant folding
5632             break;
5633
5634         case IAT_PVALUE: // The value needs to be accessed via an indirection
5635             // Create an indirection
5636             tree = gtNewIndOfIconHandleNode(TYP_REF, (size_t)pValue, GTF_ICON_STR_HDL, false);
5637             break;
5638
5639         case IAT_PPVALUE: // The value needs to be accessed via a double indirection
5640             // Create the first indirection
5641             tree = gtNewIndOfIconHandleNode(TYP_I_IMPL, (size_t)pValue, GTF_ICON_PSTR_HDL, true);
5642
5643             // Create the second indirection
5644             tree = gtNewOperNode(GT_IND, TYP_REF, tree);
5645             // This indirection won't cause an exception.
5646             tree->gtFlags |= GTF_IND_NONFAULTING;
5647             // This indirection points into the gloabal heap (it is String Object)
5648             tree->gtFlags |= GTF_GLOB_REF;
5649             break;
5650
5651         default:
5652             noway_assert(!"Unexpected InfoAccessType");
5653     }
5654
5655     return tree;
5656 }
5657
5658 /*****************************************************************************/
5659
5660 GenTree* Compiler::gtNewLconNode(__int64 value)
5661 {
5662 #ifdef _TARGET_64BIT_
5663     GenTree* node = new (this, GT_CNS_INT) GenTreeIntCon(TYP_LONG, value);
5664 #else
5665     GenTree* node = new (this, GT_CNS_LNG) GenTreeLngCon(value);
5666 #endif
5667
5668     return node;
5669 }
5670
5671 GenTree* Compiler::gtNewDconNode(double value)
5672 {
5673     GenTree* node = new (this, GT_CNS_DBL) GenTreeDblCon(value);
5674
5675     return node;
5676 }
5677
5678 GenTree* Compiler::gtNewSconNode(int CPX, CORINFO_MODULE_HANDLE scpHandle)
5679 {
5680
5681 #if SMALL_TREE_NODES
5682
5683     /* 'GT_CNS_STR' nodes later get transformed into 'GT_CALL' */
5684
5685     assert(GenTree::s_gtNodeSizes[GT_CALL] > GenTree::s_gtNodeSizes[GT_CNS_STR]);
5686
5687     GenTree* node = new (this, GT_CALL) GenTreeStrCon(CPX, scpHandle DEBUGARG(/*largeNode*/ true));
5688 #else
5689     GenTree* node = new (this, GT_CNS_STR) GenTreeStrCon(CPX, scpHandle DEBUGARG(/*largeNode*/ true));
5690 #endif
5691
5692     return node;
5693 }
5694
5695 GenTree* Compiler::gtNewZeroConNode(var_types type)
5696 {
5697     GenTree* zero;
5698     switch (type)
5699     {
5700         case TYP_INT:
5701             zero = gtNewIconNode(0);
5702             break;
5703
5704         case TYP_BYREF:
5705             __fallthrough;
5706
5707         case TYP_REF:
5708             zero         = gtNewIconNode(0);
5709             zero->gtType = type;
5710             break;
5711
5712         case TYP_LONG:
5713             zero = gtNewLconNode(0);
5714             break;
5715
5716         case TYP_FLOAT:
5717             zero         = gtNewDconNode(0.0);
5718             zero->gtType = type;
5719             break;
5720
5721         case TYP_DOUBLE:
5722             zero = gtNewDconNode(0.0);
5723             break;
5724
5725         default:
5726             noway_assert(!"Bad type in gtNewZeroConNode");
5727             zero = nullptr;
5728             break;
5729     }
5730     return zero;
5731 }
5732
5733 GenTree* Compiler::gtNewOneConNode(var_types type)
5734 {
5735     GenTree* one;
5736     switch (type)
5737     {
5738         case TYP_INT:
5739         case TYP_UINT:
5740             one = gtNewIconNode(1);
5741             break;
5742
5743         case TYP_LONG:
5744         case TYP_ULONG:
5745             one = gtNewLconNode(1);
5746             break;
5747
5748         case TYP_FLOAT:
5749         case TYP_DOUBLE:
5750             one         = gtNewDconNode(1.0);
5751             one->gtType = type;
5752             break;
5753
5754         default:
5755             noway_assert(!"Bad type in gtNewOneConNode");
5756             one = nullptr;
5757             break;
5758     }
5759     return one;
5760 }
5761
5762 #ifdef FEATURE_SIMD
5763 //---------------------------------------------------------------------
5764 // gtNewSIMDVectorZero: create a GT_SIMD node for Vector<T>.Zero
5765 //
5766 // Arguments:
5767 //    simdType  -  simd vector type
5768 //    baseType  -  element type of vector
5769 //    size      -  size of vector in bytes
5770 GenTree* Compiler::gtNewSIMDVectorZero(var_types simdType, var_types baseType, unsigned size)
5771 {
5772     baseType         = genActualType(baseType);
5773     GenTree* initVal = gtNewZeroConNode(baseType);
5774     initVal->gtType  = baseType;
5775     return gtNewSIMDNode(simdType, initVal, nullptr, SIMDIntrinsicInit, baseType, size);
5776 }
5777
5778 //---------------------------------------------------------------------
5779 // gtNewSIMDVectorOne: create a GT_SIMD node for Vector<T>.One
5780 //
5781 // Arguments:
5782 //    simdType  -  simd vector type
5783 //    baseType  -  element type of vector
5784 //    size      -  size of vector in bytes
5785 GenTree* Compiler::gtNewSIMDVectorOne(var_types simdType, var_types baseType, unsigned size)
5786 {
5787     GenTree* initVal;
5788     if (varTypeIsSmallInt(baseType))
5789     {
5790         unsigned baseSize = genTypeSize(baseType);
5791         int      val;
5792         if (baseSize == 1)
5793         {
5794             val = 0x01010101;
5795         }
5796         else
5797         {
5798             val = 0x00010001;
5799         }
5800         initVal = gtNewIconNode(val);
5801     }
5802     else
5803     {
5804         initVal = gtNewOneConNode(baseType);
5805     }
5806
5807     baseType        = genActualType(baseType);
5808     initVal->gtType = baseType;
5809     return gtNewSIMDNode(simdType, initVal, nullptr, SIMDIntrinsicInit, baseType, size);
5810 }
5811 #endif // FEATURE_SIMD
5812
5813 GenTreeCall* Compiler::gtNewIndCallNode(GenTree* addr, var_types type, GenTreeArgList* args, IL_OFFSETX ilOffset)
5814 {
5815     return gtNewCallNode(CT_INDIRECT, (CORINFO_METHOD_HANDLE)addr, type, args, ilOffset);
5816 }
5817
5818 GenTreeCall* Compiler::gtNewCallNode(
5819     gtCallTypes callType, CORINFO_METHOD_HANDLE callHnd, var_types type, GenTreeArgList* args, IL_OFFSETX ilOffset)
5820 {
5821     GenTreeCall* node = new (this, GT_CALL) GenTreeCall(genActualType(type));
5822
5823     node->gtFlags |= (GTF_CALL | GTF_GLOB_REF);
5824     if (args)
5825     {
5826         node->gtFlags |= (args->gtFlags & GTF_ALL_EFFECT);
5827     }
5828     node->gtCallType      = callType;
5829     node->gtCallMethHnd   = callHnd;
5830     node->gtCallArgs      = args;
5831     node->gtCallObjp      = nullptr;
5832     node->fgArgInfo       = nullptr;
5833     node->callSig         = nullptr;
5834     node->gtRetClsHnd     = nullptr;
5835     node->gtControlExpr   = nullptr;
5836     node->gtCallMoreFlags = 0;
5837
5838     if (callType == CT_INDIRECT)
5839     {
5840         node->gtCallCookie = nullptr;
5841     }
5842     else
5843     {
5844         node->gtInlineCandidateInfo = nullptr;
5845     }
5846     node->gtCallLateArgs = nullptr;
5847     node->gtReturnType   = type;
5848
5849 #ifdef FEATURE_READYTORUN_COMPILER
5850     node->gtEntryPoint.addr       = nullptr;
5851     node->gtEntryPoint.accessType = IAT_VALUE;
5852 #endif
5853
5854 #if defined(DEBUG) || defined(INLINE_DATA)
5855     // These get updated after call node is built.
5856     node->gtInlineObservation = InlineObservation::CALLEE_UNUSED_INITIAL;
5857     node->gtRawILOffset       = BAD_IL_OFFSET;
5858 #endif
5859
5860     // Spec: Managed Retval sequence points needs to be generated while generating debug info for debuggable code.
5861     //
5862     // Implementation note: if not generating MRV info genCallSite2ILOffsetMap will be NULL and
5863     // codegen will pass BAD_IL_OFFSET as IL offset of a call node to emitter, which will cause emitter
5864     // not to emit IP mapping entry.
5865     if (opts.compDbgCode && opts.compDbgInfo)
5866     {
5867         // Managed Retval - IL offset of the call.  This offset is used to emit a
5868         // CALL_INSTRUCTION type sequence point while emitting corresponding native call.
5869         //
5870         // TODO-Cleanup:
5871         // a) (Opt) We need not store this offset if the method doesn't return a
5872         // value.  Rather it can be made BAD_IL_OFFSET to prevent a sequence
5873         // point being emitted.
5874         //
5875         // b) (Opt) Add new sequence points only if requested by debugger through
5876         // a new boundary type - ICorDebugInfo::BoundaryTypes
5877         if (genCallSite2ILOffsetMap == nullptr)
5878         {
5879             genCallSite2ILOffsetMap = new (getAllocator()) CallSiteILOffsetTable(getAllocator());
5880         }
5881
5882         // Make sure that there are no duplicate entries for a given call node
5883         assert(!genCallSite2ILOffsetMap->Lookup(node));
5884         genCallSite2ILOffsetMap->Set(node, ilOffset);
5885     }
5886
5887     // Initialize gtOtherRegs
5888     node->ClearOtherRegs();
5889
5890     // Initialize spill flags of gtOtherRegs
5891     node->ClearOtherRegFlags();
5892
5893 #if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
5894     // Initialize the multi-reg long return info if necessary
5895     if (varTypeIsLong(node))
5896     {
5897         // The return type will remain as the incoming long type
5898         node->gtReturnType = node->gtType;
5899
5900         // Initialize Return type descriptor of call node
5901         ReturnTypeDesc* retTypeDesc = node->GetReturnTypeDesc();
5902         retTypeDesc->InitializeLongReturnType(this);
5903
5904         // must be a long returned in two registers
5905         assert(retTypeDesc->GetReturnRegCount() == 2);
5906     }
5907 #endif // defined(_TARGET_X86_) || defined(_TARGET_ARM_)
5908
5909     return node;
5910 }
5911
5912 GenTree* Compiler::gtNewLclvNode(unsigned lnum, var_types type, IL_OFFSETX ILoffs)
5913 {
5914     // We need to ensure that all struct values are normalized.
5915     // It might be nice to assert this in general, but we have assignments of int to long.
5916     if (varTypeIsStruct(type))
5917     {
5918         // Make an exception for implicit by-ref parameters during global morph, since
5919         // their lvType has been updated to byref but their appearances have not yet all
5920         // been rewritten and so may have struct type still.
5921         assert(type == lvaTable[lnum].lvType ||
5922                (lvaIsImplicitByRefLocal(lnum) && fgGlobalMorph && (lvaTable[lnum].lvType == TYP_BYREF)));
5923     }
5924     GenTree* node = new (this, GT_LCL_VAR) GenTreeLclVar(type, lnum, ILoffs);
5925
5926     /* Cannot have this assert because the inliner uses this function
5927      * to add temporaries */
5928
5929     // assert(lnum < lvaCount);
5930
5931     return node;
5932 }
5933
5934 GenTree* Compiler::gtNewLclLNode(unsigned lnum, var_types type, IL_OFFSETX ILoffs)
5935 {
5936     // We need to ensure that all struct values are normalized.
5937     // It might be nice to assert this in general, but we have assignments of int to long.
5938     if (varTypeIsStruct(type))
5939     {
5940         // Make an exception for implicit by-ref parameters during global morph, since
5941         // their lvType has been updated to byref but their appearances have not yet all
5942         // been rewritten and so may have struct type still.
5943         assert(type == lvaTable[lnum].lvType ||
5944                (lvaIsImplicitByRefLocal(lnum) && fgGlobalMorph && (lvaTable[lnum].lvType == TYP_BYREF)));
5945     }
5946 #if SMALL_TREE_NODES
5947     /* This local variable node may later get transformed into a large node */
5948
5949     // assert(GenTree::s_gtNodeSizes[GT_CALL] > GenTree::s_gtNodeSizes[GT_LCL_VAR]);
5950
5951     GenTree* node = new (this, GT_CALL) GenTreeLclVar(type, lnum, ILoffs DEBUGARG(/*largeNode*/ true));
5952 #else
5953     GenTree* node = new (this, GT_LCL_VAR) GenTreeLclVar(type, lnum, ILoffs DEBUGARG(/*largeNode*/ true));
5954 #endif
5955
5956     return node;
5957 }
5958
5959 GenTreeLclFld* Compiler::gtNewLclFldNode(unsigned lnum, var_types type, unsigned offset)
5960 {
5961     GenTreeLclFld* node = new (this, GT_LCL_FLD) GenTreeLclFld(type, lnum, offset);
5962
5963     /* Cannot have this assert because the inliner uses this function
5964      * to add temporaries */
5965
5966     // assert(lnum < lvaCount);
5967
5968     node->gtFieldSeq = FieldSeqStore::NotAField();
5969     return node;
5970 }
5971
5972 GenTree* Compiler::gtNewInlineCandidateReturnExpr(GenTree* inlineCandidate, var_types type)
5973
5974 {
5975     assert(GenTree::s_gtNodeSizes[GT_RET_EXPR] == TREE_NODE_SZ_LARGE);
5976
5977     GenTree* node = new (this, GT_RET_EXPR) GenTreeRetExpr(type);
5978
5979     node->gtRetExpr.gtInlineCandidate = inlineCandidate;
5980
5981     if (varTypeIsStruct(inlineCandidate) && !inlineCandidate->OperIsBlkOp())
5982     {
5983         node->gtRetExpr.gtRetClsHnd = gtGetStructHandle(inlineCandidate);
5984     }
5985
5986     // GT_RET_EXPR node eventually might be bashed back to GT_CALL (when inlining is aborted for example).
5987     // Therefore it should carry the GTF_CALL flag so that all the rules about spilling can apply to it as well.
5988     // For example, impImportLeave or CEE_POP need to spill GT_RET_EXPR before empty the evaluation stack.
5989     node->gtFlags |= GTF_CALL;
5990
5991     return node;
5992 }
5993
5994 GenTreeArgList* Compiler::gtNewListNode(GenTree* op1, GenTreeArgList* op2)
5995 {
5996     assert((op1 != nullptr) && (op1->OperGet() != GT_LIST));
5997
5998     return new (this, GT_LIST) GenTreeArgList(op1, op2);
5999 }
6000
6001 /*****************************************************************************
6002  *
6003  *  Create a list out of one value.
6004  */
6005
6006 GenTreeArgList* Compiler::gtNewArgList(GenTree* arg)
6007 {
6008     return new (this, GT_LIST) GenTreeArgList(arg);
6009 }
6010
6011 /*****************************************************************************
6012  *
6013  *  Create a list out of the two values.
6014  */
6015
6016 GenTreeArgList* Compiler::gtNewArgList(GenTree* arg1, GenTree* arg2)
6017 {
6018     return new (this, GT_LIST) GenTreeArgList(arg1, gtNewArgList(arg2));
6019 }
6020
6021 /*****************************************************************************
6022  *
6023  *  Create a list out of the three values.
6024  */
6025
6026 GenTreeArgList* Compiler::gtNewArgList(GenTree* arg1, GenTree* arg2, GenTree* arg3)
6027 {
6028     return new (this, GT_LIST) GenTreeArgList(arg1, gtNewArgList(arg2, arg3));
6029 }
6030
6031 /*****************************************************************************
6032  *
6033  *  Create a list out of the three values.
6034  */
6035
6036 GenTreeArgList* Compiler::gtNewArgList(GenTree* arg1, GenTree* arg2, GenTree* arg3, GenTree* arg4)
6037 {
6038     return new (this, GT_LIST) GenTreeArgList(arg1, gtNewArgList(arg2, arg3, arg4));
6039 }
6040
6041 /*****************************************************************************
6042  *
6043  *  Given a GT_CALL node, access the fgArgInfo and find the entry
6044  *  that has the matching argNum and return the fgArgTableEntryPtr
6045  */
6046
6047 fgArgTabEntry* Compiler::gtArgEntryByArgNum(GenTreeCall* call, unsigned argNum)
6048 {
6049     fgArgInfo* argInfo = call->fgArgInfo;
6050     noway_assert(argInfo != nullptr);
6051     return argInfo->GetArgEntry(argNum);
6052 }
6053
6054 /*****************************************************************************
6055  *
6056  *  Given a GT_CALL node, access the fgArgInfo and find the entry
6057  *  that has the matching node and return the fgArgTableEntryPtr
6058  */
6059
6060 fgArgTabEntry* Compiler::gtArgEntryByNode(GenTreeCall* call, GenTree* node)
6061 {
6062     fgArgInfo* argInfo = call->fgArgInfo;
6063     noway_assert(argInfo != nullptr);
6064
6065     unsigned        argCount       = argInfo->ArgCount();
6066     fgArgTabEntry** argTable       = argInfo->ArgTable();
6067     fgArgTabEntry*  curArgTabEntry = nullptr;
6068
6069     for (unsigned i = 0; i < argCount; i++)
6070     {
6071         curArgTabEntry = argTable[i];
6072
6073         if (curArgTabEntry->node == node)
6074         {
6075             return curArgTabEntry;
6076         }
6077         else if (curArgTabEntry->parent != nullptr)
6078         {
6079             assert(curArgTabEntry->parent->OperIsList());
6080             if (curArgTabEntry->parent->Current() == node)
6081             {
6082                 return curArgTabEntry;
6083             }
6084         }
6085         else // (curArgTabEntry->parent == NULL)
6086         {
6087             if (call->gtCallObjp == node)
6088             {
6089                 return curArgTabEntry;
6090             }
6091         }
6092     }
6093     noway_assert(!"gtArgEntryByNode: node not found");
6094     return nullptr;
6095 }
6096
6097 /*****************************************************************************
6098  *
6099  *  Find and return the entry with the given "lateArgInx".  Requires that one is found
6100  *  (asserts this).
6101  */
6102 fgArgTabEntry* Compiler::gtArgEntryByLateArgIndex(GenTreeCall* call, unsigned lateArgInx)
6103 {
6104     fgArgInfo* argInfo = call->fgArgInfo;
6105     noway_assert(argInfo != nullptr);
6106     assert(lateArgInx != UINT_MAX);
6107
6108     unsigned        argCount       = argInfo->ArgCount();
6109     fgArgTabEntry** argTable       = argInfo->ArgTable();
6110     fgArgTabEntry*  curArgTabEntry = nullptr;
6111
6112     for (unsigned i = 0; i < argCount; i++)
6113     {
6114         curArgTabEntry = argTable[i];
6115         if (curArgTabEntry->isLateArg() && curArgTabEntry->lateArgInx == lateArgInx)
6116         {
6117             return curArgTabEntry;
6118         }
6119     }
6120     noway_assert(!"gtArgEntryByNode: node not found");
6121     return nullptr;
6122 }
6123
6124 //------------------------------------------------------------------------
6125 // gtArgNodeByLateArgInx: Given a call instruction, find the argument with the given
6126 //                        late arg index (i.e. the given position in the gtCallLateArgs list).
6127 // Arguments:
6128 //    call - the call node
6129 //    lateArgInx - the index into the late args list
6130 //
6131 // Return value:
6132 //    The late argument node.
6133 //
6134 GenTree* Compiler::gtArgNodeByLateArgInx(GenTreeCall* call, unsigned lateArgInx)
6135 {
6136     GenTree* argx     = nullptr;
6137     unsigned regIndex = 0;
6138
6139     for (GenTreeArgList *list = call->gtCall.gtCallLateArgs; list != nullptr; regIndex++, list = list->Rest())
6140     {
6141         argx = list->Current();
6142         assert(!argx->IsArgPlaceHolderNode()); // No placeholder nodes are in gtCallLateArgs;
6143         if (regIndex == lateArgInx)
6144         {
6145             break;
6146         }
6147     }
6148     noway_assert(argx != nullptr);
6149     return argx;
6150 }
6151
6152 /*****************************************************************************
6153  *
6154  *  Given an fgArgTabEntry*, return true if it is the 'this' pointer argument.
6155  */
6156 bool Compiler::gtArgIsThisPtr(fgArgTabEntry* argEntry)
6157 {
6158     return (argEntry->parent == nullptr);
6159 }
6160
6161 /*****************************************************************************
6162  *
6163  *  Create a node that will assign 'src' to 'dst'.
6164  */
6165
6166 GenTree* Compiler::gtNewAssignNode(GenTree* dst, GenTree* src)
6167 {
6168     /* Mark the target as being assigned */
6169
6170     if ((dst->gtOper == GT_LCL_VAR) || (dst->OperGet() == GT_LCL_FLD))
6171     {
6172         dst->gtFlags |= GTF_VAR_DEF;
6173         if (dst->IsPartialLclFld(this))
6174         {
6175             // We treat these partial writes as combined uses and defs.
6176             dst->gtFlags |= GTF_VAR_USEASG;
6177         }
6178     }
6179     dst->gtFlags |= GTF_DONT_CSE;
6180
6181     /* Create the assignment node */
6182
6183     GenTree* asg = gtNewOperNode(GT_ASG, dst->TypeGet(), dst, src);
6184
6185     /* Mark the expression as containing an assignment */
6186
6187     asg->gtFlags |= GTF_ASG;
6188
6189     return asg;
6190 }
6191
6192 //------------------------------------------------------------------------
6193 // gtNewObjNode: Creates a new Obj node.
6194 //
6195 // Arguments:
6196 //    structHnd - The class handle of the struct type.
6197 //    addr      - The address of the struct.
6198 //
6199 // Return Value:
6200 //    Returns a node representing the struct value at the given address.
6201 //
6202 // Assumptions:
6203 //    Any entry and exit conditions, such as required preconditions of
6204 //    data structures, memory to be freed by caller, etc.
6205 //
6206 // Notes:
6207 //    It will currently return a GT_OBJ node for any struct type, but may
6208 //    return a GT_IND or a non-indirection for a scalar type.
6209 //    The node will not yet have its GC info initialized. This is because
6210 //    we may not need this info if this is an r-value.
6211
6212 GenTree* Compiler::gtNewObjNode(CORINFO_CLASS_HANDLE structHnd, GenTree* addr)
6213 {
6214     var_types nodeType = impNormStructType(structHnd);
6215     assert(varTypeIsStruct(nodeType));
6216     unsigned size = info.compCompHnd->getClassSize(structHnd);
6217
6218     // It would be convenient to set the GC info at this time, but we don't actually require
6219     // it unless this is going to be a destination.
6220     if (!varTypeIsStruct(nodeType))
6221     {
6222         if ((addr->gtOper == GT_ADDR) && (addr->gtGetOp1()->TypeGet() == nodeType))
6223         {
6224             return addr->gtGetOp1();
6225         }
6226         else
6227         {
6228             return gtNewOperNode(GT_IND, nodeType, addr);
6229         }
6230     }
6231     GenTreeBlk* newBlkOrObjNode = new (this, GT_OBJ) GenTreeObj(nodeType, addr, structHnd, size);
6232
6233     // An Obj is not a global reference, if it is known to be a local struct.
6234     if ((addr->gtFlags & GTF_GLOB_REF) == 0)
6235     {
6236         GenTreeLclVarCommon* lclNode = addr->IsLocalAddrExpr();
6237         if (lclNode != nullptr)
6238         {
6239             newBlkOrObjNode->gtFlags |= GTF_IND_NONFAULTING;
6240             if (!lvaIsImplicitByRefLocal(lclNode->gtLclNum))
6241             {
6242                 newBlkOrObjNode->gtFlags &= ~GTF_GLOB_REF;
6243             }
6244         }
6245     }
6246     return newBlkOrObjNode;
6247 }
6248
6249 //------------------------------------------------------------------------
6250 // gtSetObjGcInfo: Set the GC info on an object node
6251 //
6252 // Arguments:
6253 //    objNode - The object node of interest
6254
6255 void Compiler::gtSetObjGcInfo(GenTreeObj* objNode)
6256 {
6257     CORINFO_CLASS_HANDLE structHnd  = objNode->gtClass;
6258     var_types            nodeType   = objNode->TypeGet();
6259     unsigned             size       = objNode->gtBlkSize;
6260     unsigned             slots      = 0;
6261     unsigned             gcPtrCount = 0;
6262     BYTE*                gcPtrs     = nullptr;
6263
6264     assert(varTypeIsStruct(nodeType));
6265     assert(size == info.compCompHnd->getClassSize(structHnd));
6266     assert(nodeType == impNormStructType(structHnd));
6267
6268     if (nodeType == TYP_STRUCT)
6269     {
6270         if (size >= TARGET_POINTER_SIZE)
6271         {
6272             // Get the GC fields info
6273             var_types simdBaseType; // Dummy argument
6274             slots    = roundUp(size, TARGET_POINTER_SIZE) / TARGET_POINTER_SIZE;
6275             gcPtrs   = new (this, CMK_ASTNode) BYTE[slots];
6276             nodeType = impNormStructType(structHnd, gcPtrs, &gcPtrCount, &simdBaseType);
6277         }
6278     }
6279     objNode->SetGCInfo(gcPtrs, gcPtrCount, slots);
6280     assert(objNode->gtType == nodeType);
6281 }
6282
6283 //------------------------------------------------------------------------
6284 // gtNewStructVal: Return a node that represents a struct value
6285 //
6286 // Arguments:
6287 //    structHnd - The class for the struct
6288 //    addr      - The address of the struct
6289 //
6290 // Return Value:
6291 //    A block, object or local node that represents the struct value pointed to by 'addr'.
6292
6293 GenTree* Compiler::gtNewStructVal(CORINFO_CLASS_HANDLE structHnd, GenTree* addr)
6294 {
6295     if (addr->gtOper == GT_ADDR)
6296     {
6297         GenTree* val = addr->gtGetOp1();
6298         if (val->OperGet() == GT_LCL_VAR)
6299         {
6300             unsigned   lclNum = addr->gtGetOp1()->AsLclVarCommon()->gtLclNum;
6301             LclVarDsc* varDsc = &(lvaTable[lclNum]);
6302             if (varTypeIsStruct(varDsc) && (varDsc->lvVerTypeInfo.GetClassHandle() == structHnd) &&
6303                 !lvaIsImplicitByRefLocal(lclNum))
6304             {
6305                 return addr->gtGetOp1();
6306             }
6307         }
6308     }
6309     return gtNewObjNode(structHnd, addr);
6310 }
6311
6312 //------------------------------------------------------------------------
6313 // gtNewBlockVal: Return a node that represents a possibly untyped block value
6314 //
6315 // Arguments:
6316 //    addr      - The address of the block
6317 //    size      - The size of the block
6318 //
6319 // Return Value:
6320 //    A block, object or local node that represents the block value pointed to by 'addr'.
6321
6322 GenTree* Compiler::gtNewBlockVal(GenTree* addr, unsigned size)
6323 {
6324     // By default we treat this as an opaque struct type with known size.
6325     var_types blkType = TYP_STRUCT;
6326     if ((addr->gtOper == GT_ADDR) && (addr->gtGetOp1()->OperGet() == GT_LCL_VAR))
6327     {
6328         GenTree* val = addr->gtGetOp1();
6329 #if FEATURE_SIMD
6330         if (varTypeIsSIMD(val))
6331         {
6332             if (genTypeSize(val->TypeGet()) == size)
6333             {
6334                 blkType = val->TypeGet();
6335                 return addr->gtGetOp1();
6336             }
6337         }
6338         else
6339 #endif // FEATURE_SIMD
6340             if (val->TypeGet() == TYP_STRUCT)
6341         {
6342             GenTreeLclVarCommon* lcl    = addr->gtGetOp1()->AsLclVarCommon();
6343             LclVarDsc*           varDsc = &(lvaTable[lcl->gtLclNum]);
6344             if ((varDsc->TypeGet() == TYP_STRUCT) && (varDsc->lvExactSize == size))
6345             {
6346                 return addr->gtGetOp1();
6347             }
6348         }
6349     }
6350     return new (this, GT_BLK) GenTreeBlk(GT_BLK, blkType, addr, size);
6351 }
6352
6353 // Creates a new assignment node for a CpObj.
6354 // Parameters (exactly the same as MSIL CpObj):
6355 //
6356 //  dstAddr    - The target to copy the struct to
6357 //  srcAddr    - The source to copy the struct from
6358 //  structHnd  - A class token that represents the type of object being copied. May be null
6359 //               if FEATURE_SIMD is enabled and the source has a SIMD type.
6360 //  isVolatile - Is this marked as volatile memory?
6361
6362 GenTree* Compiler::gtNewCpObjNode(GenTree* dstAddr, GenTree* srcAddr, CORINFO_CLASS_HANDLE structHnd, bool isVolatile)
6363 {
6364     GenTree* lhs = gtNewStructVal(structHnd, dstAddr);
6365     GenTree* src = nullptr;
6366     unsigned size;
6367
6368     if (lhs->OperIsBlk())
6369     {
6370         size = lhs->AsBlk()->gtBlkSize;
6371         if (lhs->OperGet() == GT_OBJ)
6372         {
6373             gtSetObjGcInfo(lhs->AsObj());
6374         }
6375     }
6376     else
6377     {
6378         size = genTypeSize(lhs->gtType);
6379     }
6380
6381     if (srcAddr->OperGet() == GT_ADDR)
6382     {
6383         src = srcAddr->gtOp.gtOp1;
6384     }
6385     else
6386     {
6387         src = gtNewOperNode(GT_IND, lhs->TypeGet(), srcAddr);
6388     }
6389
6390     GenTree* result = gtNewBlkOpNode(lhs, src, size, isVolatile, true);
6391     return result;
6392 }
6393
6394 //------------------------------------------------------------------------
6395 // FixupInitBlkValue: Fixup the init value for an initBlk operation
6396 //
6397 // Arguments:
6398 //    asgType - The type of assignment that the initBlk is being transformed into
6399 //
6400 // Return Value:
6401 //    Modifies the constant value on this node to be the appropriate "fill"
6402 //    value for the initblk.
6403 //
6404 // Notes:
6405 //    The initBlk MSIL instruction takes a byte value, which must be
6406 //    extended to the size of the assignment when an initBlk is transformed
6407 //    to an assignment of a primitive type.
6408 //    This performs the appropriate extension.
6409
6410 void GenTreeIntCon::FixupInitBlkValue(var_types asgType)
6411 {
6412     assert(varTypeIsIntegralOrI(asgType));
6413     unsigned size = genTypeSize(asgType);
6414     if (size > 1)
6415     {
6416         size_t cns = gtIconVal;
6417         cns        = cns & 0xFF;
6418         cns |= cns << 8;
6419         if (size >= 4)
6420         {
6421             cns |= cns << 16;
6422 #ifdef _TARGET_64BIT_
6423             if (size == 8)
6424             {
6425                 cns |= cns << 32;
6426             }
6427 #endif // _TARGET_64BIT_
6428
6429             // Make the type match for evaluation types.
6430             gtType = asgType;
6431
6432             // if we are initializing a GC type the value being assigned must be zero (null).
6433             assert(!varTypeIsGC(asgType) || (cns == 0));
6434         }
6435
6436         gtIconVal = cns;
6437     }
6438 }
6439
6440 //
6441 //------------------------------------------------------------------------
6442 // gtBlockOpInit: Initializes a BlkOp GenTree
6443 //
6444 // Arguments:
6445 //    result     - an assignment node that is to be initialized.
6446 //    dst        - the target (destination) we want to either initialize or copy to.
6447 //    src        - the init value for InitBlk or the source struct for CpBlk/CpObj.
6448 //    isVolatile - specifies whether this node is a volatile memory operation.
6449 //
6450 // Assumptions:
6451 //    'result' is an assignment that is newly constructed.
6452 //    If 'dst' is TYP_STRUCT, then it must be a block node or lclVar.
6453 //
6454 // Notes:
6455 //    This procedure centralizes all the logic to both enforce proper structure and
6456 //    to properly construct any InitBlk/CpBlk node.
6457
6458 void Compiler::gtBlockOpInit(GenTree* result, GenTree* dst, GenTree* srcOrFillVal, bool isVolatile)
6459 {
6460     if (!result->OperIsBlkOp())
6461     {
6462         assert(dst->TypeGet() != TYP_STRUCT);
6463         return;
6464     }
6465 #ifdef DEBUG
6466     // If the copy involves GC pointers, the caller must have already set
6467     // the node additional members (gtGcPtrs, gtGcPtrCount, gtSlots) on the dst.
6468     if ((dst->gtOper == GT_OBJ) && dst->AsBlk()->HasGCPtr())
6469     {
6470         GenTreeObj* objNode = dst->AsObj();
6471         assert(objNode->gtGcPtrs != nullptr);
6472         assert(!IsUninitialized(objNode->gtGcPtrs));
6473         assert(!IsUninitialized(objNode->gtGcPtrCount));
6474         assert(!IsUninitialized(objNode->gtSlots) && objNode->gtSlots > 0);
6475
6476         for (unsigned i = 0; i < objNode->gtGcPtrCount; ++i)
6477         {
6478             CorInfoGCType t = (CorInfoGCType)objNode->gtGcPtrs[i];
6479             switch (t)
6480             {
6481                 case TYPE_GC_NONE:
6482                 case TYPE_GC_REF:
6483                 case TYPE_GC_BYREF:
6484                 case TYPE_GC_OTHER:
6485                     break;
6486                 default:
6487                     unreached();
6488             }
6489         }
6490     }
6491 #endif // DEBUG
6492
6493     /* In the case of CpBlk, we want to avoid generating
6494     * nodes where the source and destination are the same
6495     * because of two reasons, first, is useless, second
6496     * it introduces issues in liveness and also copying
6497     * memory from an overlapping memory location is
6498     * undefined both as per the ECMA standard and also
6499     * the memcpy semantics specify that.
6500     *
6501     * NOTE: In this case we'll only detect the case for addr of a local
6502     * and a local itself, any other complex expressions won't be
6503     * caught.
6504     *
6505     * TODO-Cleanup: though having this logic is goodness (i.e. avoids self-assignment
6506     * of struct vars very early), it was added because fgInterBlockLocalVarLiveness()
6507     * isn't handling self-assignment of struct variables correctly.  This issue may not
6508     * surface if struct promotion is ON (which is the case on x86/arm).  But still the
6509     * fundamental issue exists that needs to be addressed.
6510     */
6511     if (result->OperIsCopyBlkOp())
6512     {
6513         GenTree* currSrc = srcOrFillVal;
6514         GenTree* currDst = dst;
6515
6516         if (currSrc->OperIsBlk() && (currSrc->AsBlk()->Addr()->OperGet() == GT_ADDR))
6517         {
6518             currSrc = currSrc->AsBlk()->Addr()->gtGetOp1();
6519         }
6520         if (currDst->OperIsBlk() && (currDst->AsBlk()->Addr()->OperGet() == GT_ADDR))
6521         {
6522             currDst = currDst->AsBlk()->Addr()->gtGetOp1();
6523         }
6524
6525         if (currSrc->OperGet() == GT_LCL_VAR && currDst->OperGet() == GT_LCL_VAR &&
6526             currSrc->gtLclVarCommon.gtLclNum == currDst->gtLclVarCommon.gtLclNum)
6527         {
6528             // Make this a NOP
6529             // TODO-Cleanup: probably doesn't matter, but could do this earlier and avoid creating a GT_ASG
6530             result->gtBashToNOP();
6531             return;
6532         }
6533     }
6534
6535     // Propagate all effect flags from children
6536     result->gtFlags |= dst->gtFlags & GTF_ALL_EFFECT;
6537     result->gtFlags |= result->gtOp.gtOp2->gtFlags & GTF_ALL_EFFECT;
6538
6539     result->gtFlags |= (dst->gtFlags & GTF_EXCEPT) | (srcOrFillVal->gtFlags & GTF_EXCEPT);
6540
6541     if (isVolatile)
6542     {
6543         result->gtFlags |= GTF_BLK_VOLATILE;
6544     }
6545
6546 #ifdef FEATURE_SIMD
6547     if (result->OperIsCopyBlkOp() && varTypeIsSIMD(srcOrFillVal))
6548     {
6549         // If the source is a GT_SIMD node of SIMD type, then the dst lclvar struct
6550         // should be labeled as simd intrinsic related struct.
6551         // This is done so that the morpher can transform any field accesses into
6552         // intrinsics, thus avoiding conflicting access methods (fields vs. whole-register).
6553
6554         GenTree* src = srcOrFillVal;
6555         if (src->OperIsIndir() && (src->AsIndir()->Addr()->OperGet() == GT_ADDR))
6556         {
6557             src = src->AsIndir()->Addr()->gtGetOp1();
6558         }
6559 #ifdef FEATURE_HW_INTRINSICS
6560         if ((src->OperGet() == GT_SIMD) || (src->OperGet() == GT_HWIntrinsic))
6561 #else
6562         if (src->OperGet() == GT_SIMD)
6563 #endif // FEATURE_HW_INTRINSICS
6564         {
6565             if (dst->OperIsBlk() && (dst->AsIndir()->Addr()->OperGet() == GT_ADDR))
6566             {
6567                 dst = dst->AsIndir()->Addr()->gtGetOp1();
6568             }
6569
6570             if (dst->OperIsLocal() && varTypeIsStruct(dst))
6571             {
6572                 setLclRelatedToSIMDIntrinsic(dst);
6573             }
6574         }
6575     }
6576 #endif // FEATURE_SIMD
6577 }
6578
6579 //------------------------------------------------------------------------
6580 // gtNewBlkOpNode: Creates a GenTree for a block (struct) assignment.
6581 //
6582 // Arguments:
6583 //    dst           - Destination or target to copy to / initialize the buffer.
6584 //    srcOrFillVall - the size of the buffer to copy/initialize or zero, in the case of CpObj.
6585 //    size          - The size of the buffer or a class token (in the case of CpObj).
6586 //    isVolatile    - Whether this is a volatile memory operation or not.
6587 //    isCopyBlock   - True if this is a block copy (rather than a block init).
6588 //
6589 // Return Value:
6590 //    Returns the newly constructed and initialized block operation.
6591 //
6592 // Notes:
6593 //    If size is zero, the dst must be a GT_OBJ with the class handle.
6594 //    'dst' must be a block node or lclVar.
6595 //
6596 GenTree* Compiler::gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, unsigned size, bool isVolatile, bool isCopyBlock)
6597 {
6598     assert(dst->OperIsBlk() || dst->OperIsLocal());
6599     if (isCopyBlock)
6600     {
6601         srcOrFillVal->gtFlags |= GTF_DONT_CSE;
6602         if (srcOrFillVal->OperIsIndir() && (srcOrFillVal->gtGetOp1()->gtOper == GT_ADDR))
6603         {
6604             srcOrFillVal = srcOrFillVal->gtGetOp1()->gtGetOp1();
6605         }
6606     }
6607     else
6608     {
6609         // InitBlk
6610         assert(varTypeIsIntegral(srcOrFillVal));
6611         if (varTypeIsStruct(dst))
6612         {
6613             if (!srcOrFillVal->IsIntegralConst(0))
6614             {
6615                 srcOrFillVal = gtNewOperNode(GT_INIT_VAL, TYP_INT, srcOrFillVal);
6616             }
6617         }
6618     }
6619
6620     GenTree* result = gtNewAssignNode(dst, srcOrFillVal);
6621     gtBlockOpInit(result, dst, srcOrFillVal, isVolatile);
6622     return result;
6623 }
6624
6625 //------------------------------------------------------------------------
6626 // gtNewPutArgReg: Creates a new PutArgReg node.
6627 //
6628 // Arguments:
6629 //    type   - The actual type of the argument
6630 //    arg    - The argument node
6631 //    argReg - The register that the argument will be passed in
6632 //
6633 // Return Value:
6634 //    Returns the newly created PutArgReg node.
6635 //
6636 // Notes:
6637 //    The node is generated as GenTreeMultiRegOp on RyuJIT/armel, GenTreeOp on all the other archs.
6638 //
6639 GenTree* Compiler::gtNewPutArgReg(var_types type, GenTree* arg, regNumber argReg)
6640 {
6641     assert(arg != nullptr);
6642
6643     GenTree* node = nullptr;
6644 #if defined(_TARGET_ARM_)
6645     // A PUTARG_REG could be a MultiRegOp on arm since we could move a double register to two int registers.
6646     node = new (this, GT_PUTARG_REG) GenTreeMultiRegOp(GT_PUTARG_REG, type, arg, nullptr);
6647     if (type == TYP_LONG)
6648     {
6649         node->AsMultiRegOp()->gtOtherReg = REG_NEXT(argReg);
6650     }
6651 #else
6652     node          = gtNewOperNode(GT_PUTARG_REG, type, arg);
6653 #endif
6654     node->gtRegNum = argReg;
6655
6656     return node;
6657 }
6658
6659 //------------------------------------------------------------------------
6660 // gtNewBitCastNode: Creates a new BitCast node.
6661 //
6662 // Arguments:
6663 //    type   - The actual type of the argument
6664 //    arg    - The argument node
6665 //    argReg - The register that the argument will be passed in
6666 //
6667 // Return Value:
6668 //    Returns the newly created BitCast node.
6669 //
6670 // Notes:
6671 //    The node is generated as GenTreeMultiRegOp on RyuJIT/arm, as GenTreeOp on all the other archs.
6672 //
6673 GenTree* Compiler::gtNewBitCastNode(var_types type, GenTree* arg)
6674 {
6675     assert(arg != nullptr);
6676
6677     GenTree* node = nullptr;
6678 #if defined(_TARGET_ARM_)
6679     // A BITCAST could be a MultiRegOp on arm since we could move a double register to two int registers.
6680     node = new (this, GT_BITCAST) GenTreeMultiRegOp(GT_BITCAST, type, arg, nullptr);
6681 #else
6682     node          = gtNewOperNode(GT_BITCAST, type, arg);
6683 #endif
6684
6685     return node;
6686 }
6687
6688 //------------------------------------------------------------------------
6689 // gtNewAllocObjNode: Helper to create an object allocation node.
6690 //
6691 // Arguments:
6692 //    pResolvedToken   - Resolved token for the object being allocated
6693 //    useParent     -    true iff the token represents a child of the object's class
6694 //
6695 // Return Value:
6696 //    Returns GT_ALLOCOBJ node that will be later morphed into an
6697 //    allocation helper call or local variable allocation on the stack.
6698
6699 GenTreeAllocObj* Compiler::gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, BOOL useParent)
6700 {
6701     const BOOL      mustRestoreHandle     = TRUE;
6702     BOOL* const     pRuntimeLookup        = nullptr;
6703     bool            usingReadyToRunHelper = false;
6704     CorInfoHelpFunc helper                = CORINFO_HELP_UNDEF;
6705     GenTree*        opHandle = impTokenToHandle(pResolvedToken, pRuntimeLookup, mustRestoreHandle, useParent);
6706
6707 #ifdef FEATURE_READYTORUN_COMPILER
6708     CORINFO_CONST_LOOKUP lookup;
6709
6710     if (opts.IsReadyToRun())
6711     {
6712         helper                                        = CORINFO_HELP_READYTORUN_NEW;
6713         CORINFO_LOOKUP_KIND* const pGenericLookupKind = nullptr;
6714         usingReadyToRunHelper =
6715             info.compCompHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, helper, &lookup);
6716     }
6717 #endif
6718
6719     if (!usingReadyToRunHelper)
6720     {
6721         if (opHandle == nullptr)
6722         {
6723             // We must be backing out of an inline.
6724             assert(compDonotInline());
6725             return nullptr;
6726         }
6727
6728         helper = info.compCompHnd->getNewHelper(pResolvedToken, info.compMethodHnd);
6729     }
6730
6731     // TODO: ReadyToRun: When generic dictionary lookups are necessary, replace the lookup call
6732     // and the newfast call with a single call to a dynamic R2R cell that will:
6733     //      1) Load the context
6734     //      2) Perform the generic dictionary lookup and caching, and generate the appropriate stub
6735     //      3) Allocate and return the new object for boxing
6736     // Reason: performance (today, we'll always use the slow helper for the R2R generics case)
6737
6738     GenTreeAllocObj* allocObj = gtNewAllocObjNode(helper, pResolvedToken->hClass, TYP_REF, opHandle);
6739
6740 #ifdef FEATURE_READYTORUN_COMPILER
6741     if (usingReadyToRunHelper)
6742     {
6743         allocObj->gtEntryPoint = lookup;
6744     }
6745 #endif
6746
6747     return allocObj;
6748 }
6749
6750 /*****************************************************************************
6751  *
6752  *  Clones the given tree value and returns a copy of the given tree.
6753  *  If 'complexOK' is false, the cloning is only done provided the tree
6754  *     is not too complex (whatever that may mean);
6755  *  If 'complexOK' is true, we try slightly harder to clone the tree.
6756  *  In either case, NULL is returned if the tree cannot be cloned
6757  *
6758  *  Note that there is the function gtCloneExpr() which does a more
6759  *  complete job if you can't handle this function failing.
6760  */
6761
6762 GenTree* Compiler::gtClone(GenTree* tree, bool complexOK)
6763 {
6764     GenTree* copy;
6765
6766     switch (tree->gtOper)
6767     {
6768         case GT_CNS_INT:
6769
6770 #if defined(LATE_DISASM)
6771             if (tree->IsIconHandle())
6772             {
6773                 copy = gtNewIconHandleNode(tree->gtIntCon.gtIconVal, tree->gtFlags, tree->gtIntCon.gtFieldSeq);
6774                 copy->gtIntCon.gtCompileTimeHandle = tree->gtIntCon.gtCompileTimeHandle;
6775                 copy->gtType                       = tree->gtType;
6776             }
6777             else
6778 #endif
6779             {
6780                 copy = new (this, GT_CNS_INT)
6781                     GenTreeIntCon(tree->gtType, tree->gtIntCon.gtIconVal, tree->gtIntCon.gtFieldSeq);
6782                 copy->gtIntCon.gtCompileTimeHandle = tree->gtIntCon.gtCompileTimeHandle;
6783             }
6784             break;
6785
6786         case GT_CNS_LNG:
6787             copy = gtNewLconNode(tree->gtLngCon.gtLconVal);
6788             break;
6789
6790         case GT_LCL_VAR:
6791             // Remember that the LclVar node has been cloned. The flag will be set
6792             // on 'copy' as well.
6793             tree->gtFlags |= GTF_VAR_CLONED;
6794             copy = gtNewLclvNode(tree->gtLclVarCommon.gtLclNum, tree->gtType, tree->gtLclVar.gtLclILoffs);
6795             break;
6796
6797         case GT_LCL_FLD:
6798         case GT_LCL_FLD_ADDR:
6799             // Remember that the LclVar node has been cloned. The flag will be set
6800             // on 'copy' as well.
6801             tree->gtFlags |= GTF_VAR_CLONED;
6802             copy = new (this, tree->gtOper)
6803                 GenTreeLclFld(tree->gtOper, tree->TypeGet(), tree->gtLclFld.gtLclNum, tree->gtLclFld.gtLclOffs);
6804             copy->gtLclFld.gtFieldSeq = tree->gtLclFld.gtFieldSeq;
6805             break;
6806
6807         case GT_CLS_VAR:
6808             copy = new (this, GT_CLS_VAR)
6809                 GenTreeClsVar(tree->gtType, tree->gtClsVar.gtClsVarHnd, tree->gtClsVar.gtFieldSeq);
6810             break;
6811
6812         default:
6813             if (!complexOK)
6814             {
6815                 return nullptr;
6816             }
6817
6818             if (tree->gtOper == GT_FIELD)
6819             {
6820                 GenTree* objp;
6821
6822                 // copied from line 9850
6823
6824                 objp = nullptr;
6825                 if (tree->gtField.gtFldObj)
6826                 {
6827                     objp = gtClone(tree->gtField.gtFldObj, false);
6828                     if (!objp)
6829                     {
6830                         return objp;
6831                     }
6832                 }
6833
6834                 copy = gtNewFieldRef(tree->TypeGet(), tree->gtField.gtFldHnd, objp, tree->gtField.gtFldOffset);
6835                 copy->gtField.gtFldMayOverlap = tree->gtField.gtFldMayOverlap;
6836 #ifdef FEATURE_READYTORUN_COMPILER
6837                 copy->gtField.gtFieldLookup = tree->gtField.gtFieldLookup;
6838 #endif
6839             }
6840             else if (tree->OperIs(GT_ADD, GT_SUB))
6841             {
6842                 GenTree* op1 = tree->gtOp.gtOp1;
6843                 GenTree* op2 = tree->gtOp.gtOp2;
6844
6845                 if (op1->OperIsLeaf() && op2->OperIsLeaf())
6846                 {
6847                     op1 = gtClone(op1);
6848                     if (op1 == nullptr)
6849                     {
6850                         return nullptr;
6851                     }
6852                     op2 = gtClone(op2);
6853                     if (op2 == nullptr)
6854                     {
6855                         return nullptr;
6856                     }
6857
6858                     copy = gtNewOperNode(tree->OperGet(), tree->TypeGet(), op1, op2);
6859                 }
6860                 else
6861                 {
6862                     return nullptr;
6863                 }
6864             }
6865             else if (tree->gtOper == GT_ADDR)
6866             {
6867                 GenTree* op1 = gtClone(tree->gtOp.gtOp1);
6868                 if (op1 == nullptr)
6869                 {
6870                     return nullptr;
6871                 }
6872                 copy = gtNewOperNode(GT_ADDR, tree->TypeGet(), op1);
6873             }
6874             else
6875             {
6876                 return nullptr;
6877             }
6878
6879             break;
6880     }
6881
6882     copy->gtFlags |= tree->gtFlags & ~GTF_NODE_MASK;
6883 #if defined(DEBUG)
6884     copy->gtDebugFlags |= tree->gtDebugFlags & ~GTF_DEBUG_NODE_MASK;
6885 #endif // defined(DEBUG)
6886
6887     return copy;
6888 }
6889
6890 //------------------------------------------------------------------------
6891 // gtCloneExpr: Create a copy of `tree`, adding flags `addFlags`, mapping
6892 //              local `varNum` to int constant `varVal` if it appears at
6893 //              the root, and mapping uses of local `deepVarNum` to constant
6894 //              `deepVarVal` if they occur beyond the root.
6895 //
6896 // Arguments:
6897 //    tree - GenTree to create a copy of
6898 //    addFlags - GTF_* flags to add to the copied tree nodes
6899 //    varNum - lclNum to replace at the root, or ~0 for no root replacement
6900 //    varVal - If replacing at root, replace local `varNum` with IntCns `varVal`
6901 //    deepVarNum - lclNum to replace uses of beyond the root, or ~0 for no replacement
6902 //    deepVarVal - If replacing beyond root, replace `deepVarNum` with IntCns `deepVarVal`
6903 //
6904 // Return Value:
6905 //    A copy of the given tree with the replacements and added flags specified.
6906 //
6907 // Notes:
6908 //    Top-level callers should generally call the overload that doesn't have
6909 //    the explicit `deepVarNum` and `deepVarVal` parameters; those are used in
6910 //    recursive invocations to avoid replacing defs.
6911
6912 GenTree* Compiler::gtCloneExpr(
6913     GenTree* tree, unsigned addFlags, unsigned varNum, int varVal, unsigned deepVarNum, int deepVarVal)
6914 {
6915     if (tree == nullptr)
6916     {
6917         return nullptr;
6918     }
6919
6920     /* Figure out what kind of a node we have */
6921
6922     genTreeOps oper = tree->OperGet();
6923     unsigned   kind = tree->OperKind();
6924     GenTree*   copy;
6925
6926     /* Is this a constant or leaf node? */
6927
6928     if (kind & (GTK_CONST | GTK_LEAF))
6929     {
6930         switch (oper)
6931         {
6932             case GT_CNS_INT:
6933
6934 #if defined(LATE_DISASM)
6935                 if (tree->IsIconHandle())
6936                 {
6937                     copy = gtNewIconHandleNode(tree->gtIntCon.gtIconVal, tree->gtFlags, tree->gtIntCon.gtFieldSeq);
6938                     copy->gtIntCon.gtCompileTimeHandle = tree->gtIntCon.gtCompileTimeHandle;
6939                     copy->gtType                       = tree->gtType;
6940                 }
6941                 else
6942 #endif
6943                 {
6944                     copy                               = gtNewIconNode(tree->gtIntCon.gtIconVal, tree->gtType);
6945                     copy->gtIntCon.gtCompileTimeHandle = tree->gtIntCon.gtCompileTimeHandle;
6946                     copy->gtIntCon.gtFieldSeq          = tree->gtIntCon.gtFieldSeq;
6947                 }
6948                 goto DONE;
6949
6950             case GT_CNS_LNG:
6951                 copy = gtNewLconNode(tree->gtLngCon.gtLconVal);
6952                 goto DONE;
6953
6954             case GT_CNS_DBL:
6955                 copy         = gtNewDconNode(tree->gtDblCon.gtDconVal);
6956                 copy->gtType = tree->gtType; // keep the same type
6957                 goto DONE;
6958
6959             case GT_CNS_STR:
6960                 copy = gtNewSconNode(tree->gtStrCon.gtSconCPX, tree->gtStrCon.gtScpHnd);
6961                 goto DONE;
6962
6963             case GT_LCL_VAR:
6964
6965                 if (tree->gtLclVarCommon.gtLclNum == varNum)
6966                 {
6967                     copy = gtNewIconNode(varVal, tree->gtType);
6968                     if (tree->gtFlags & GTF_VAR_ARR_INDEX)
6969                     {
6970                         copy->LabelIndex(this);
6971                     }
6972                 }
6973                 else
6974                 {
6975                     // Remember that the LclVar node has been cloned. The flag will
6976                     // be set on 'copy' as well.
6977                     tree->gtFlags |= GTF_VAR_CLONED;
6978                     copy = gtNewLclvNode(tree->gtLclVar.gtLclNum, tree->gtType, tree->gtLclVar.gtLclILoffs);
6979                     copy->AsLclVarCommon()->SetSsaNum(tree->AsLclVarCommon()->GetSsaNum());
6980                 }
6981                 copy->gtFlags = tree->gtFlags;
6982                 goto DONE;
6983
6984             case GT_LCL_FLD:
6985                 if (tree->gtLclFld.gtLclNum == varNum)
6986                 {
6987                     IMPL_LIMITATION("replacing GT_LCL_FLD with a constant");
6988                 }
6989                 else
6990                 {
6991                     // Remember that the LclVar node has been cloned. The flag will
6992                     // be set on 'copy' as well.
6993                     tree->gtFlags |= GTF_VAR_CLONED;
6994                     copy = new (this, GT_LCL_FLD)
6995                         GenTreeLclFld(tree->TypeGet(), tree->gtLclFld.gtLclNum, tree->gtLclFld.gtLclOffs);
6996                     copy->gtLclFld.gtFieldSeq = tree->gtLclFld.gtFieldSeq;
6997                     copy->gtFlags             = tree->gtFlags;
6998                 }
6999                 goto DONE;
7000
7001             case GT_CLS_VAR:
7002                 copy = new (this, GT_CLS_VAR)
7003                     GenTreeClsVar(tree->TypeGet(), tree->gtClsVar.gtClsVarHnd, tree->gtClsVar.gtFieldSeq);
7004                 goto DONE;
7005
7006             case GT_RET_EXPR:
7007                 // GT_RET_EXPR is unique node, that contains a link to a gtInlineCandidate node,
7008                 // that is part of another statement. We cannot clone both here and cannot
7009                 // create another GT_RET_EXPR that points to the same gtInlineCandidate.
7010                 NO_WAY("Cloning of GT_RET_EXPR node not supported");
7011                 goto DONE;
7012
7013             case GT_MEMORYBARRIER:
7014                 copy = new (this, GT_MEMORYBARRIER) GenTree(GT_MEMORYBARRIER, TYP_VOID);
7015                 goto DONE;
7016
7017             case GT_ARGPLACE:
7018                 copy = gtNewArgPlaceHolderNode(tree->gtType, tree->gtArgPlace.gtArgPlaceClsHnd);
7019                 goto DONE;
7020
7021             case GT_FTN_ADDR:
7022                 copy = new (this, oper) GenTreeFptrVal(tree->gtType, tree->gtFptrVal.gtFptrMethod);
7023
7024 #ifdef FEATURE_READYTORUN_COMPILER
7025                 copy->gtFptrVal.gtEntryPoint = tree->gtFptrVal.gtEntryPoint;
7026 #endif
7027                 goto DONE;
7028
7029             case GT_CATCH_ARG:
7030             case GT_NO_OP:
7031                 copy = new (this, oper) GenTree(oper, tree->gtType);
7032                 goto DONE;
7033
7034 #if !FEATURE_EH_FUNCLETS
7035             case GT_END_LFIN:
7036 #endif // !FEATURE_EH_FUNCLETS
7037             case GT_JMP:
7038                 copy = new (this, oper) GenTreeVal(oper, tree->gtType, tree->gtVal.gtVal1);
7039                 goto DONE;
7040
7041             case GT_LABEL:
7042                 copy = new (this, oper) GenTreeLabel(tree->gtLabel.gtLabBB);
7043                 goto DONE;
7044
7045             default:
7046                 NO_WAY("Cloning of node not supported");
7047                 goto DONE;
7048         }
7049     }
7050
7051     /* Is it a 'simple' unary/binary operator? */
7052
7053     if (kind & GTK_SMPOP)
7054     {
7055         /* If necessary, make sure we allocate a "fat" tree node */
7056         CLANG_FORMAT_COMMENT_ANCHOR;
7057
7058 #if SMALL_TREE_NODES
7059         switch (oper)
7060         {
7061             /* These nodes sometimes get bashed to "fat" ones */
7062
7063             case GT_MUL:
7064             case GT_DIV:
7065             case GT_MOD:
7066
7067             case GT_UDIV:
7068             case GT_UMOD:
7069
7070                 //  In the implementation of gtNewLargeOperNode you have
7071                 //  to give an oper that will create a small node,
7072                 //  otherwise it asserts.
7073                 //
7074                 if (GenTree::s_gtNodeSizes[oper] == TREE_NODE_SZ_SMALL)
7075                 {
7076                     copy = gtNewLargeOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1,
7077                                               tree->OperIsBinary() ? tree->gtOp.gtOp2 : nullptr);
7078                 }
7079                 else // Always a large tree
7080                 {
7081                     if (tree->OperIsBinary())
7082                     {
7083                         copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2);
7084                     }
7085                     else
7086                     {
7087                         copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1);
7088                     }
7089                 }
7090                 break;
7091
7092             case GT_CAST:
7093                 copy =
7094                     new (this, LargeOpOpcode()) GenTreeCast(tree->TypeGet(), tree->gtCast.CastOp(), tree->IsUnsigned(),
7095                                                             tree->gtCast.gtCastType DEBUGARG(/*largeNode*/ TRUE));
7096                 break;
7097
7098             // The nodes below this are not bashed, so they can be allocated at their individual sizes.
7099
7100             case GT_LIST:
7101                 assert((tree->gtOp.gtOp2 == nullptr) || tree->gtOp.gtOp2->OperIsList());
7102                 copy             = new (this, GT_LIST) GenTreeArgList(tree->gtOp.gtOp1);
7103                 copy->gtOp.gtOp2 = tree->gtOp.gtOp2;
7104                 break;
7105
7106             case GT_FIELD_LIST:
7107                 copy = new (this, GT_FIELD_LIST) GenTreeFieldList(tree->gtOp.gtOp1, tree->AsFieldList()->gtFieldOffset,
7108                                                                   tree->AsFieldList()->gtFieldType, nullptr);
7109                 copy->gtOp.gtOp2 = tree->gtOp.gtOp2;
7110                 copy->gtFlags    = (copy->gtFlags & ~GTF_FIELD_LIST_HEAD) | (tree->gtFlags & GTF_FIELD_LIST_HEAD);
7111                 break;
7112
7113             case GT_INDEX:
7114             {
7115                 GenTreeIndex* asInd = tree->AsIndex();
7116                 copy                = new (this, GT_INDEX)
7117                     GenTreeIndex(asInd->TypeGet(), asInd->Arr(), asInd->Index(), asInd->gtIndElemSize);
7118                 copy->AsIndex()->gtStructElemClass = asInd->gtStructElemClass;
7119             }
7120             break;
7121
7122             case GT_INDEX_ADDR:
7123             {
7124                 GenTreeIndexAddr* asIndAddr = tree->AsIndexAddr();
7125
7126                 copy = new (this, GT_INDEX_ADDR)
7127                     GenTreeIndexAddr(asIndAddr->Arr(), asIndAddr->Index(), asIndAddr->gtElemType,
7128                                      asIndAddr->gtStructElemClass, asIndAddr->gtElemSize, asIndAddr->gtLenOffset,
7129                                      asIndAddr->gtElemOffset);
7130                 copy->AsIndexAddr()->gtIndRngFailBB = asIndAddr->gtIndRngFailBB;
7131             }
7132             break;
7133
7134             case GT_ALLOCOBJ:
7135             {
7136                 GenTreeAllocObj* asAllocObj = tree->AsAllocObj();
7137                 copy = new (this, GT_ALLOCOBJ) GenTreeAllocObj(tree->TypeGet(), asAllocObj->gtNewHelper,
7138                                                                asAllocObj->gtAllocObjClsHnd, asAllocObj->gtOp1);
7139             }
7140             break;
7141
7142             case GT_RUNTIMELOOKUP:
7143             {
7144                 GenTreeRuntimeLookup* asRuntimeLookup = tree->AsRuntimeLookup();
7145
7146                 copy = new (this, GT_RUNTIMELOOKUP)
7147                     GenTreeRuntimeLookup(asRuntimeLookup->gtHnd, asRuntimeLookup->gtHndType, asRuntimeLookup->gtOp1);
7148             }
7149             break;
7150
7151             case GT_ARR_LENGTH:
7152                 copy = gtNewArrLen(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtArrLen.ArrLenOffset());
7153                 break;
7154
7155             case GT_ARR_INDEX:
7156                 copy = new (this, GT_ARR_INDEX)
7157                     GenTreeArrIndex(tree->TypeGet(),
7158                                     gtCloneExpr(tree->gtArrIndex.ArrObj(), addFlags, deepVarNum, deepVarVal),
7159                                     gtCloneExpr(tree->gtArrIndex.IndexExpr(), addFlags, deepVarNum, deepVarVal),
7160                                     tree->gtArrIndex.gtCurrDim, tree->gtArrIndex.gtArrRank,
7161                                     tree->gtArrIndex.gtArrElemType);
7162                 break;
7163
7164             case GT_QMARK:
7165                 copy = new (this, GT_QMARK) GenTreeQmark(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2, this);
7166                 break;
7167
7168             case GT_OBJ:
7169                 copy = new (this, GT_OBJ)
7170                     GenTreeObj(tree->TypeGet(), tree->gtOp.gtOp1, tree->AsObj()->gtClass, tree->gtBlk.gtBlkSize);
7171                 copy->AsObj()->CopyGCInfo(tree->AsObj());
7172                 copy->gtBlk.gtBlkOpGcUnsafe = tree->gtBlk.gtBlkOpGcUnsafe;
7173                 break;
7174
7175             case GT_BLK:
7176                 copy = new (this, GT_BLK) GenTreeBlk(GT_BLK, tree->TypeGet(), tree->gtOp.gtOp1, tree->gtBlk.gtBlkSize);
7177                 copy->gtBlk.gtBlkOpGcUnsafe = tree->gtBlk.gtBlkOpGcUnsafe;
7178                 break;
7179
7180             case GT_DYN_BLK:
7181                 copy = new (this, GT_DYN_BLK) GenTreeDynBlk(tree->gtOp.gtOp1, tree->gtDynBlk.gtDynamicSize);
7182                 copy->gtBlk.gtBlkOpGcUnsafe = tree->gtBlk.gtBlkOpGcUnsafe;
7183                 break;
7184
7185             case GT_BOX:
7186                 copy = new (this, GT_BOX)
7187                     GenTreeBox(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtBox.gtAsgStmtWhenInlinedBoxValue,
7188                                tree->gtBox.gtCopyStmtWhenInlinedBoxValue);
7189                 break;
7190
7191             case GT_INTRINSIC:
7192                 copy = new (this, GT_INTRINSIC)
7193                     GenTreeIntrinsic(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2,
7194                                      tree->gtIntrinsic.gtIntrinsicId, tree->gtIntrinsic.gtMethodHandle);
7195 #ifdef FEATURE_READYTORUN_COMPILER
7196                 copy->gtIntrinsic.gtEntryPoint = tree->gtIntrinsic.gtEntryPoint;
7197 #endif
7198                 break;
7199
7200             case GT_LEA:
7201             {
7202                 GenTreeAddrMode* addrModeOp = tree->AsAddrMode();
7203                 copy                        = new (this, GT_LEA)
7204                     GenTreeAddrMode(addrModeOp->TypeGet(), addrModeOp->Base(), addrModeOp->Index(), addrModeOp->gtScale,
7205                                     static_cast<unsigned>(addrModeOp->Offset()));
7206             }
7207             break;
7208
7209             case GT_COPY:
7210             case GT_RELOAD:
7211             {
7212                 copy = new (this, oper) GenTreeCopyOrReload(oper, tree->TypeGet(), tree->gtGetOp1());
7213             }
7214             break;
7215
7216 #ifdef FEATURE_SIMD
7217             case GT_SIMD:
7218             {
7219                 GenTreeSIMD* simdOp = tree->AsSIMD();
7220                 copy                = gtNewSIMDNode(simdOp->TypeGet(), simdOp->gtGetOp1(), simdOp->gtGetOp2IfPresent(),
7221                                      simdOp->gtSIMDIntrinsicID, simdOp->gtSIMDBaseType, simdOp->gtSIMDSize);
7222             }
7223             break;
7224 #endif
7225
7226 #ifdef FEATURE_HW_INTRINSICS
7227             case GT_HWIntrinsic:
7228             {
7229                 GenTreeHWIntrinsic* hwintrinsicOp = tree->AsHWIntrinsic();
7230                 copy                              = new (this, GT_HWIntrinsic)
7231                     GenTreeHWIntrinsic(hwintrinsicOp->TypeGet(), hwintrinsicOp->gtGetOp1(),
7232                                        hwintrinsicOp->gtGetOp2IfPresent(), hwintrinsicOp->gtHWIntrinsicId,
7233                                        hwintrinsicOp->gtSIMDBaseType, hwintrinsicOp->gtSIMDSize);
7234                 copy->AsHWIntrinsic()->gtIndexBaseType = hwintrinsicOp->gtIndexBaseType;
7235             }
7236             break;
7237 #endif
7238
7239             default:
7240                 assert(!GenTree::IsExOp(tree->OperKind()) && tree->OperIsSimple());
7241                 // We're in the SimpleOp case, so it's always unary or binary.
7242                 if (GenTree::OperIsUnary(tree->OperGet()))
7243                 {
7244                     copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1, /*doSimplifications*/ false);
7245                 }
7246                 else
7247                 {
7248                     assert(GenTree::OperIsBinary(tree->OperGet()));
7249                     copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2);
7250                 }
7251                 break;
7252         }
7253 #else
7254         // We're in the SimpleOp case, so it's always unary or binary.
7255         copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2);
7256 #endif
7257
7258         // Some flags are conceptually part of the gtOper, and should be copied immediately.
7259         if (tree->gtOverflowEx())
7260         {
7261             copy->gtFlags |= GTF_OVERFLOW;
7262         }
7263
7264         if (tree->gtOp.gtOp1)
7265         {
7266             if (tree->gtOper == GT_ASG)
7267             {
7268                 // Don't replace varNum if it appears as the LHS of an assign.
7269                 copy->gtOp.gtOp1 = gtCloneExpr(tree->gtOp.gtOp1, addFlags, -1, 0, deepVarNum, deepVarVal);
7270             }
7271             else
7272             {
7273                 copy->gtOp.gtOp1 = gtCloneExpr(tree->gtOp.gtOp1, addFlags, deepVarNum, deepVarVal);
7274             }
7275         }
7276
7277         if (tree->gtGetOp2IfPresent())
7278         {
7279             copy->gtOp.gtOp2 = gtCloneExpr(tree->gtOp.gtOp2, addFlags, deepVarNum, deepVarVal);
7280         }
7281
7282         /* Flags */
7283         addFlags |= tree->gtFlags;
7284
7285         // Copy any node annotations, if necessary.
7286         switch (tree->gtOper)
7287         {
7288             case GT_STOREIND:
7289             case GT_IND:
7290             case GT_OBJ:
7291             case GT_STORE_OBJ:
7292             {
7293                 ArrayInfo arrInfo;
7294                 if (!tree->AsIndir()->gtOp1->OperIs(GT_INDEX_ADDR) && TryGetArrayInfo(tree->AsIndir(), &arrInfo))
7295                 {
7296                     GetArrayInfoMap()->Set(copy, arrInfo);
7297                 }
7298             }
7299             break;
7300
7301             default:
7302                 break;
7303         }
7304
7305 #ifdef DEBUG
7306         /* GTF_NODE_MASK should not be propagated from 'tree' to 'copy' */
7307         addFlags &= ~GTF_NODE_MASK;
7308 #endif
7309
7310         // Effects flags propagate upwards.
7311         if (copy->gtOp.gtOp1 != nullptr)
7312         {
7313             copy->gtFlags |= (copy->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT);
7314         }
7315         if (copy->gtGetOp2IfPresent() != nullptr)
7316         {
7317             copy->gtFlags |= (copy->gtGetOp2()->gtFlags & GTF_ALL_EFFECT);
7318         }
7319
7320         goto DONE;
7321     }
7322
7323     /* See what kind of a special operator we have here */
7324
7325     switch (oper)
7326     {
7327         case GT_STMT:
7328             copy = gtCloneExpr(tree->gtStmt.gtStmtExpr, addFlags, deepVarNum, deepVarVal);
7329             copy = gtNewStmt(copy, tree->gtStmt.gtStmtILoffsx);
7330             goto DONE;
7331
7332         case GT_CALL:
7333
7334             // We can't safely clone calls that have GT_RET_EXPRs via gtCloneExpr.
7335             // You must use gtCloneCandidateCall for these calls (and then do appropriate other fixup)
7336             if (tree->gtCall.IsInlineCandidate() || tree->gtCall.IsGuardedDevirtualizationCandidate())
7337             {
7338                 NO_WAY("Cloning of calls with associated GT_RET_EXPR nodes is not supported");
7339             }
7340
7341             copy = gtCloneExprCallHelper(tree->AsCall(), addFlags, deepVarNum, deepVarVal);
7342             break;
7343
7344         case GT_FIELD:
7345
7346             copy = gtNewFieldRef(tree->TypeGet(), tree->gtField.gtFldHnd, nullptr, tree->gtField.gtFldOffset);
7347
7348             copy->gtField.gtFldObj = tree->gtField.gtFldObj
7349                                          ? gtCloneExpr(tree->gtField.gtFldObj, addFlags, deepVarNum, deepVarVal)
7350                                          : nullptr;
7351             copy->gtField.gtFldMayOverlap = tree->gtField.gtFldMayOverlap;
7352 #ifdef FEATURE_READYTORUN_COMPILER
7353             copy->gtField.gtFieldLookup = tree->gtField.gtFieldLookup;
7354 #endif
7355
7356             break;
7357
7358         case GT_ARR_ELEM:
7359         {
7360             GenTree* inds[GT_ARR_MAX_RANK];
7361             for (unsigned dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
7362             {
7363                 inds[dim] = gtCloneExpr(tree->gtArrElem.gtArrInds[dim], addFlags, deepVarNum, deepVarVal);
7364             }
7365             copy = new (this, GT_ARR_ELEM)
7366                 GenTreeArrElem(tree->TypeGet(), gtCloneExpr(tree->gtArrElem.gtArrObj, addFlags, deepVarNum, deepVarVal),
7367                                tree->gtArrElem.gtArrRank, tree->gtArrElem.gtArrElemSize, tree->gtArrElem.gtArrElemType,
7368                                &inds[0]);
7369         }
7370         break;
7371
7372         case GT_ARR_OFFSET:
7373         {
7374             copy = new (this, GT_ARR_OFFSET)
7375                 GenTreeArrOffs(tree->TypeGet(), gtCloneExpr(tree->gtArrOffs.gtOffset, addFlags, deepVarNum, deepVarVal),
7376                                gtCloneExpr(tree->gtArrOffs.gtIndex, addFlags, deepVarNum, deepVarVal),
7377                                gtCloneExpr(tree->gtArrOffs.gtArrObj, addFlags, deepVarNum, deepVarVal),
7378                                tree->gtArrOffs.gtCurrDim, tree->gtArrOffs.gtArrRank, tree->gtArrOffs.gtArrElemType);
7379         }
7380         break;
7381
7382         case GT_CMPXCHG:
7383             copy = new (this, GT_CMPXCHG)
7384                 GenTreeCmpXchg(tree->TypeGet(),
7385                                gtCloneExpr(tree->gtCmpXchg.gtOpLocation, addFlags, deepVarNum, deepVarVal),
7386                                gtCloneExpr(tree->gtCmpXchg.gtOpValue, addFlags, deepVarNum, deepVarVal),
7387                                gtCloneExpr(tree->gtCmpXchg.gtOpComparand, addFlags, deepVarNum, deepVarVal));
7388             break;
7389
7390         case GT_ARR_BOUNDS_CHECK:
7391 #ifdef FEATURE_SIMD
7392         case GT_SIMD_CHK:
7393 #endif // FEATURE_SIMD
7394 #ifdef FEATURE_HW_INTRINSICS
7395         case GT_HW_INTRINSIC_CHK:
7396 #endif // FEATURE_HW_INTRINSICS
7397             copy = new (this, oper)
7398                 GenTreeBoundsChk(oper, tree->TypeGet(),
7399                                  gtCloneExpr(tree->gtBoundsChk.gtIndex, addFlags, deepVarNum, deepVarVal),
7400                                  gtCloneExpr(tree->gtBoundsChk.gtArrLen, addFlags, deepVarNum, deepVarVal),
7401                                  tree->gtBoundsChk.gtThrowKind);
7402             copy->gtBoundsChk.gtIndRngFailBB = tree->gtBoundsChk.gtIndRngFailBB;
7403             break;
7404
7405         case GT_STORE_DYN_BLK:
7406         case GT_DYN_BLK:
7407             copy = new (this, oper)
7408                 GenTreeDynBlk(gtCloneExpr(tree->gtDynBlk.Addr(), addFlags, deepVarNum, deepVarVal),
7409                               gtCloneExpr(tree->gtDynBlk.gtDynamicSize, addFlags, deepVarNum, deepVarVal));
7410             break;
7411
7412         default:
7413 #ifdef DEBUG
7414             gtDispTree(tree);
7415 #endif
7416             NO_WAY("unexpected operator");
7417     }
7418
7419 DONE:
7420
7421     // If it has a zero-offset field seq, copy annotation.
7422     if (tree->TypeGet() == TYP_BYREF)
7423     {
7424         FieldSeqNode* fldSeq = nullptr;
7425         if (GetZeroOffsetFieldMap()->Lookup(tree, &fldSeq))
7426         {
7427             GetZeroOffsetFieldMap()->Set(copy, fldSeq);
7428         }
7429     }
7430
7431     copy->gtVNPair = tree->gtVNPair; // A cloned tree gets the orginal's Value number pair
7432
7433     /* Compute the flags for the copied node. Note that we can do this only
7434        if we didnt gtFoldExpr(copy) */
7435
7436     if (copy->gtOper == oper)
7437     {
7438         addFlags |= tree->gtFlags;
7439
7440 #ifdef DEBUG
7441         /* GTF_NODE_MASK should not be propagated from 'tree' to 'copy' */
7442         addFlags &= ~GTF_NODE_MASK;
7443 #endif
7444         // Some other flags depend on the context of the expression, and should not be preserved.
7445         // For example, GTF_RELOP_QMARK:
7446         if (copy->OperKind() & GTK_RELOP)
7447         {
7448             addFlags &= ~GTF_RELOP_QMARK;
7449         }
7450         // On the other hand, if we're creating such a context, restore this flag.
7451         if (copy->OperGet() == GT_QMARK)
7452         {
7453             copy->gtOp.gtOp1->gtFlags |= GTF_RELOP_QMARK;
7454         }
7455
7456         copy->gtFlags |= addFlags;
7457
7458         // Update side effect flags since they may be different from the source side effect flags.
7459         // For example, we may have replaced some locals with constants and made indirections non-throwing.
7460         gtUpdateNodeSideEffects(copy);
7461     }
7462
7463     /* GTF_COLON_COND should be propagated from 'tree' to 'copy' */
7464     copy->gtFlags |= (tree->gtFlags & GTF_COLON_COND);
7465
7466 #if defined(DEBUG)
7467     // Non-node debug flags should be propagated from 'tree' to 'copy'
7468     copy->gtDebugFlags |= (tree->gtDebugFlags & ~GTF_DEBUG_NODE_MASK);
7469 #endif
7470
7471     /* Make sure to copy back fields that may have been initialized */
7472
7473     copy->CopyRawCosts(tree);
7474     copy->gtRsvdRegs = tree->gtRsvdRegs;
7475     copy->CopyReg(tree);
7476     return copy;
7477 }
7478
7479 //------------------------------------------------------------------------
7480 // gtCloneExprCallHelper: clone a call tree
7481 //
7482 // Notes:
7483 //    Do not invoke this method directly, instead call either gtCloneExpr
7484 //    or gtCloneCandidateCall, as appropriate.
7485 //
7486 // Arguments:
7487 //    tree - the call to clone
7488 //    addFlags - GTF_* flags to add to the copied tree nodes
7489 //    deepVarNum - lclNum to replace uses of beyond the root, or BAD_VAR_NUM for no replacement
7490 //    deepVarVal - If replacing beyond root, replace `deepVarNum` with IntCns `deepVarVal`
7491 //
7492 // Returns:
7493 //    Cloned copy of call and all subtrees.
7494
7495 GenTreeCall* Compiler::gtCloneExprCallHelper(GenTreeCall* tree, unsigned addFlags, unsigned deepVarNum, int deepVarVal)
7496 {
7497     GenTreeCall* copy = new (this, GT_CALL) GenTreeCall(tree->TypeGet());
7498
7499     copy->gtCallObjp = tree->gtCallObjp ? gtCloneExpr(tree->gtCallObjp, addFlags, deepVarNum, deepVarVal) : nullptr;
7500     copy->gtCallArgs =
7501         tree->gtCallArgs ? gtCloneExpr(tree->gtCallArgs, addFlags, deepVarNum, deepVarVal)->AsArgList() : nullptr;
7502     copy->gtCallMoreFlags = tree->gtCallMoreFlags;
7503     copy->gtCallLateArgs  = tree->gtCallLateArgs
7504                                ? gtCloneExpr(tree->gtCallLateArgs, addFlags, deepVarNum, deepVarVal)->AsArgList()
7505                                : nullptr;
7506
7507 #if !FEATURE_FIXED_OUT_ARGS
7508     copy->regArgList      = tree->regArgList;
7509     copy->regArgListCount = tree->regArgListCount;
7510 #endif
7511
7512     // The call sig comes from the EE and doesn't change throughout the compilation process, meaning
7513     // we only really need one physical copy of it. Therefore a shallow pointer copy will suffice.
7514     // (Note that this still holds even if the tree we are cloning was created by an inlinee compiler,
7515     // because the inlinee still uses the inliner's memory allocator anyway.)
7516     copy->callSig = tree->callSig;
7517
7518     copy->gtCallType    = tree->gtCallType;
7519     copy->gtReturnType  = tree->gtReturnType;
7520     copy->gtControlExpr = tree->gtControlExpr;
7521
7522     /* Copy the union */
7523     if (tree->gtCallType == CT_INDIRECT)
7524     {
7525         copy->gtCallCookie =
7526             tree->gtCallCookie ? gtCloneExpr(tree->gtCallCookie, addFlags, deepVarNum, deepVarVal) : nullptr;
7527         copy->gtCallAddr = tree->gtCallAddr ? gtCloneExpr(tree->gtCallAddr, addFlags, deepVarNum, deepVarVal) : nullptr;
7528     }
7529     else if (tree->IsVirtualStub())
7530     {
7531         copy->gtCallMethHnd      = tree->gtCallMethHnd;
7532         copy->gtStubCallStubAddr = tree->gtStubCallStubAddr;
7533     }
7534     else
7535     {
7536         copy->gtCallMethHnd         = tree->gtCallMethHnd;
7537         copy->gtInlineCandidateInfo = nullptr;
7538     }
7539
7540     if (tree->fgArgInfo)
7541     {
7542         // Create and initialize the fgArgInfo for our copy of the call tree
7543         copy->fgArgInfo = new (this, CMK_Unknown) fgArgInfo(copy, tree);
7544     }
7545     else
7546     {
7547         copy->fgArgInfo = nullptr;
7548     }
7549
7550     copy->gtRetClsHnd = tree->gtRetClsHnd;
7551
7552 #if FEATURE_MULTIREG_RET
7553     copy->gtReturnTypeDesc = tree->gtReturnTypeDesc;
7554 #endif
7555
7556 #ifdef FEATURE_READYTORUN_COMPILER
7557     copy->setEntryPoint(tree->gtEntryPoint);
7558 #endif
7559
7560 #if defined(DEBUG) || defined(INLINE_DATA)
7561     copy->gtInlineObservation = tree->gtInlineObservation;
7562     copy->gtRawILOffset       = tree->gtCall.gtRawILOffset;
7563 #endif
7564
7565     copy->CopyOtherRegFlags(tree);
7566
7567     return copy;
7568 }
7569
7570 //------------------------------------------------------------------------
7571 // gtCloneCandidateCall: clone a call that is an inline or guarded
7572 //    devirtualization candidate (~ any call that can have a GT_RET_EXPR)
7573 //
7574 // Notes:
7575 //    If the call really is a candidate, the caller must take additional steps
7576 //    after cloning to re-establish candidate info and the relationship between
7577 //    the candidate and any associated GT_RET_EXPR.
7578 //
7579 // Arguments:
7580 //    call - the call to clone
7581 //
7582 // Returns:
7583 //    Cloned copy of call and all subtrees.
7584
7585 GenTreeCall* Compiler::gtCloneCandidateCall(GenTreeCall* call)
7586 {
7587     assert(call->IsInlineCandidate() || call->IsGuardedDevirtualizationCandidate());
7588
7589     GenTreeCall* result = gtCloneExprCallHelper(call);
7590
7591     // There is some common post-processing in gtCloneExpr that we reproduce
7592     // here, for the fields that make sense for candidate calls.
7593     result->gtFlags |= call->gtFlags;
7594
7595 #if defined(DEBUG)
7596     result->gtDebugFlags |= (call->gtDebugFlags & ~GTF_DEBUG_NODE_MASK);
7597 #endif
7598
7599     result->CopyReg(call);
7600
7601     return result;
7602 }
7603
7604 //------------------------------------------------------------------------
7605 // gtReplaceTree: Replace a tree with a new tree.
7606 //
7607 // Arguments:
7608 //    stmt            - The top-level root stmt of the tree being replaced.
7609 //                      Must not be null.
7610 //    tree            - The tree being replaced. Must not be null.
7611 //    replacementTree - The replacement tree. Must not be null.
7612 //
7613 // Return Value:
7614 //    The tree node that replaces the old tree.
7615 //
7616 // Assumptions:
7617 //    The sequencing of the stmt has been done.
7618 //
7619 // Notes:
7620 //    The caller must ensure that the original statement has been sequenced,
7621 //    and the side effect flags are updated on the statement nodes,
7622 //    but this method will sequence 'replacementTree', and insert it into the
7623 //    proper place in the statement sequence.
7624
7625 GenTree* Compiler::gtReplaceTree(GenTree* stmt, GenTree* tree, GenTree* replacementTree)
7626 {
7627     assert(fgStmtListThreaded);
7628     assert(tree != nullptr);
7629     assert(stmt != nullptr);
7630     assert(replacementTree != nullptr);
7631
7632     GenTree** treePtr    = nullptr;
7633     GenTree*  treeParent = tree->gtGetParent(&treePtr);
7634
7635     assert(treeParent != nullptr || tree == stmt->gtStmt.gtStmtExpr);
7636
7637     if (treePtr == nullptr)
7638     {
7639         // Replace the stmt expr and rebuild the linear order for "stmt".
7640         assert(treeParent == nullptr);
7641         assert(fgOrder != FGOrderLinear);
7642         stmt->gtStmt.gtStmtExpr = tree;
7643         fgSetStmtSeq(stmt);
7644     }
7645     else
7646     {
7647         assert(treeParent != nullptr);
7648
7649         // Check to see if the node to be replaced is a call argument and if so,
7650         // set `treeParent` to the call node.
7651         GenTree* cursor = treeParent;
7652         while ((cursor != nullptr) && (cursor->OperGet() == GT_LIST))
7653         {
7654             cursor = cursor->gtNext;
7655         }
7656
7657         if ((cursor != nullptr) && (cursor->OperGet() == GT_CALL))
7658         {
7659             treeParent = cursor;
7660         }
7661
7662 #ifdef DEBUG
7663         GenTree** useEdge;
7664         assert(treeParent->TryGetUse(tree, &useEdge));
7665         assert(useEdge == treePtr);
7666 #endif // DEBUG
7667
7668         GenTree* treeFirstNode = fgGetFirstNode(tree);
7669         GenTree* treeLastNode  = tree;
7670         GenTree* treePrevNode  = treeFirstNode->gtPrev;
7671         GenTree* treeNextNode  = treeLastNode->gtNext;
7672
7673         treeParent->ReplaceOperand(treePtr, replacementTree);
7674
7675         // Build the linear order for "replacementTree".
7676         fgSetTreeSeq(replacementTree, treePrevNode);
7677
7678         // Restore linear-order Prev and Next for "replacementTree".
7679         if (treePrevNode != nullptr)
7680         {
7681             treeFirstNode         = fgGetFirstNode(replacementTree);
7682             treeFirstNode->gtPrev = treePrevNode;
7683             treePrevNode->gtNext  = treeFirstNode;
7684         }
7685         else
7686         {
7687             // Update the linear oder start of "stmt" if treeFirstNode
7688             // appears to have replaced the original first node.
7689             assert(treeFirstNode == stmt->gtStmt.gtStmtList);
7690             stmt->gtStmt.gtStmtList = fgGetFirstNode(replacementTree);
7691         }
7692
7693         if (treeNextNode != nullptr)
7694         {
7695             treeLastNode         = replacementTree;
7696             treeLastNode->gtNext = treeNextNode;
7697             treeNextNode->gtPrev = treeLastNode;
7698         }
7699     }
7700
7701     return replacementTree;
7702 }
7703
7704 //------------------------------------------------------------------------
7705 // gtUpdateSideEffects: Update the side effects of a tree and its ancestors
7706 //
7707 // Arguments:
7708 //    stmt            - The tree's statement
7709 //    tree            - Tree to update the side effects for
7710 //
7711 // Note: If tree's order hasn't been established, the method updates side effect
7712 //       flags on all statement's nodes.
7713
7714 void Compiler::gtUpdateSideEffects(GenTree* stmt, GenTree* tree)
7715 {
7716     if (fgStmtListThreaded)
7717     {
7718         gtUpdateTreeAncestorsSideEffects(tree);
7719     }
7720     else
7721     {
7722         gtUpdateStmtSideEffects(stmt);
7723     }
7724 }
7725
7726 //------------------------------------------------------------------------
7727 // gtUpdateTreeAncestorsSideEffects: Update the side effects of a tree and its ancestors
7728 //                                   when statement order has been established.
7729 //
7730 // Arguments:
7731 //    tree            - Tree to update the side effects for
7732
7733 void Compiler::gtUpdateTreeAncestorsSideEffects(GenTree* tree)
7734 {
7735     assert(fgStmtListThreaded);
7736     while (tree != nullptr)
7737     {
7738         gtUpdateNodeSideEffects(tree);
7739         tree = tree->gtGetParent(nullptr);
7740     }
7741 }
7742
7743 //------------------------------------------------------------------------
7744 // gtUpdateStmtSideEffects: Update the side effects for statement tree nodes.
7745 //
7746 // Arguments:
7747 //    stmt            - The statement to update side effects on
7748
7749 void Compiler::gtUpdateStmtSideEffects(GenTree* stmt)
7750 {
7751     fgWalkTree(&stmt->gtStmt.gtStmtExpr, fgUpdateSideEffectsPre, fgUpdateSideEffectsPost);
7752 }
7753
7754 //------------------------------------------------------------------------
7755 // gtUpdateNodeOperSideEffects: Update the side effects based on the node operation.
7756 //
7757 // Arguments:
7758 //    tree            - Tree to update the side effects on
7759 //
7760 // Notes:
7761 //    This method currently only updates GTF_EXCEPT, GTF_ASG, and GTF_CALL flags.
7762 //    The other side effect flags may remain unnecessarily (conservatively) set.
7763 //    The caller of this method is expected to update the flags based on the children's flags.
7764
7765 void Compiler::gtUpdateNodeOperSideEffects(GenTree* tree)
7766 {
7767     if (tree->OperMayThrow(this))
7768     {
7769         tree->gtFlags |= GTF_EXCEPT;
7770     }
7771     else
7772     {
7773         tree->gtFlags &= ~GTF_EXCEPT;
7774         if (tree->OperIsIndirOrArrLength())
7775         {
7776             tree->gtFlags |= GTF_IND_NONFAULTING;
7777         }
7778     }
7779
7780     if (tree->OperRequiresAsgFlag())
7781     {
7782         tree->gtFlags |= GTF_ASG;
7783     }
7784     else
7785     {
7786         tree->gtFlags &= ~GTF_ASG;
7787     }
7788
7789     if (tree->OperRequiresCallFlag(this))
7790     {
7791         tree->gtFlags |= GTF_CALL;
7792     }
7793     else
7794     {
7795         tree->gtFlags &= ~GTF_CALL;
7796     }
7797 }
7798
7799 //------------------------------------------------------------------------
7800 // gtUpdateNodeSideEffects: Update the side effects based on the node operation and
7801 //                          children's side efects.
7802 //
7803 // Arguments:
7804 //    tree            - Tree to update the side effects on
7805 //
7806 // Notes:
7807 //    This method currently only updates GTF_EXCEPT and GTF_ASG flags. The other side effect
7808 //    flags may remain unnecessarily (conservatively) set.
7809
7810 void Compiler::gtUpdateNodeSideEffects(GenTree* tree)
7811 {
7812     gtUpdateNodeOperSideEffects(tree);
7813     unsigned nChildren = tree->NumChildren();
7814     for (unsigned childNum = 0; childNum < nChildren; childNum++)
7815     {
7816         GenTree* child = tree->GetChild(childNum);
7817         if (child != nullptr)
7818         {
7819             tree->gtFlags |= (child->gtFlags & GTF_ALL_EFFECT);
7820         }
7821     }
7822 }
7823
7824 //------------------------------------------------------------------------
7825 // fgUpdateSideEffectsPre: Update the side effects based on the tree operation.
7826 //
7827 // Arguments:
7828 //    pTree            - Pointer to the tree to update the side effects
7829 //    fgWalkPre        - Walk data
7830 //
7831 // Notes:
7832 //    This method currently only updates GTF_EXCEPT and GTF_ASG flags. The other side effect
7833 //    flags may remain unnecessarily (conservatively) set.
7834
7835 Compiler::fgWalkResult Compiler::fgUpdateSideEffectsPre(GenTree** pTree, fgWalkData* fgWalkPre)
7836 {
7837     fgWalkPre->compiler->gtUpdateNodeOperSideEffects(*pTree);
7838
7839     return WALK_CONTINUE;
7840 }
7841
7842 //------------------------------------------------------------------------
7843 // fgUpdateSideEffectsPost: Update the side effects of the parent based on the tree's flags.
7844 //
7845 // Arguments:
7846 //    pTree            - Pointer to the tree
7847 //    fgWalkPost       - Walk data
7848 //
7849 // Notes:
7850 //    The routine is used for updating the stale side effect flags for ancestor
7851 //    nodes starting from treeParent up to the top-level stmt expr.
7852
7853 Compiler::fgWalkResult Compiler::fgUpdateSideEffectsPost(GenTree** pTree, fgWalkData* fgWalkPost)
7854 {
7855     GenTree* tree   = *pTree;
7856     GenTree* parent = fgWalkPost->parent;
7857     if (parent != nullptr)
7858     {
7859         parent->gtFlags |= (tree->gtFlags & GTF_ALL_EFFECT);
7860     }
7861     return WALK_CONTINUE;
7862 }
7863
7864 /*****************************************************************************
7865  *
7866  *  Compares two trees and returns true when both trees are the same.
7867  *  Instead of fully comparing the two trees this method can just return false.
7868  *  Thus callers should not assume that the trees are different when false is returned.
7869  *  Only when true is returned can the caller perform code optimizations.
7870  *  The current implementation only compares a limited set of LEAF/CONST node
7871  *  and returns false for all othere trees.
7872  */
7873 bool Compiler::gtCompareTree(GenTree* op1, GenTree* op2)
7874 {
7875     /* Make sure that both trees are of the same GT node kind */
7876     if (op1->OperGet() != op2->OperGet())
7877     {
7878         return false;
7879     }
7880
7881     /* Make sure that both trees are returning the same type */
7882     if (op1->gtType != op2->gtType)
7883     {
7884         return false;
7885     }
7886
7887     /* Figure out what kind of a node we have */
7888
7889     genTreeOps oper = op1->OperGet();
7890     unsigned   kind = op1->OperKind();
7891
7892     /* Is this a constant or leaf node? */
7893
7894     if (kind & (GTK_CONST | GTK_LEAF))
7895     {
7896         switch (oper)
7897         {
7898             case GT_CNS_INT:
7899                 if ((op1->gtIntCon.gtIconVal == op2->gtIntCon.gtIconVal) && GenTree::SameIconHandleFlag(op1, op2))
7900                 {
7901                     return true;
7902                 }
7903                 break;
7904
7905             case GT_CNS_LNG:
7906                 if (op1->gtLngCon.gtLconVal == op2->gtLngCon.gtLconVal)
7907                 {
7908                     return true;
7909                 }
7910                 break;
7911
7912             case GT_CNS_STR:
7913                 if (op1->gtStrCon.gtSconCPX == op2->gtStrCon.gtSconCPX)
7914                 {
7915                     return true;
7916                 }
7917                 break;
7918
7919             case GT_LCL_VAR:
7920                 if (op1->gtLclVarCommon.gtLclNum == op2->gtLclVarCommon.gtLclNum)
7921                 {
7922                     return true;
7923                 }
7924                 break;
7925
7926             case GT_CLS_VAR:
7927                 if (op1->gtClsVar.gtClsVarHnd == op2->gtClsVar.gtClsVarHnd)
7928                 {
7929                     return true;
7930                 }
7931                 break;
7932
7933             default:
7934                 // we return false for these unhandled 'oper' kinds
7935                 break;
7936         }
7937     }
7938     return false;
7939 }
7940
7941 GenTree* Compiler::gtGetThisArg(GenTreeCall* call)
7942 {
7943     if (call->gtCallObjp != nullptr)
7944     {
7945         if (call->gtCallObjp->gtOper != GT_NOP && call->gtCallObjp->gtOper != GT_ASG)
7946         {
7947             if (!(call->gtCallObjp->gtFlags & GTF_LATE_ARG))
7948             {
7949                 return call->gtCallObjp;
7950             }
7951         }
7952
7953         if (call->gtCallLateArgs)
7954         {
7955             regNumber      thisReg         = REG_ARG_0;
7956             unsigned       argNum          = 0;
7957             fgArgTabEntry* thisArgTabEntry = gtArgEntryByArgNum(call, argNum);
7958             GenTree*       result          = thisArgTabEntry->node;
7959
7960 #if !FEATURE_FIXED_OUT_ARGS
7961             GenTree* lateArgs = call->gtCallLateArgs;
7962             regList  list     = call->regArgList;
7963             int      index    = 0;
7964             while (lateArgs != NULL)
7965             {
7966                 assert(lateArgs->gtOper == GT_LIST);
7967                 assert(index < call->regArgListCount);
7968                 regNumber curArgReg = list[index];
7969                 if (curArgReg == thisReg)
7970                 {
7971                     if (optAssertionPropagatedCurrentStmt)
7972                         result = lateArgs->gtOp.gtOp1;
7973
7974                     assert(result == lateArgs->gtOp.gtOp1);
7975                 }
7976
7977                 lateArgs = lateArgs->gtOp.gtOp2;
7978                 index++;
7979             }
7980 #endif
7981             return result;
7982         }
7983     }
7984     return nullptr;
7985 }
7986
7987 bool GenTree::gtSetFlags() const
7988 {
7989     //
7990     // When FEATURE_SET_FLAGS (_TARGET_ARM_) is active the method returns true
7991     //    when the gtFlags has the flag GTF_SET_FLAGS set
7992     // otherwise the architecture will be have instructions that typically set
7993     //    the flags and this method will return true.
7994     //
7995     //    Exceptions: GT_IND (load/store) is not allowed to set the flags
7996     //                and on XARCH the GT_MUL/GT_DIV and all overflow instructions
7997     //                do not set the condition flags
7998     //
7999     // Precondition we have a GTK_SMPOP
8000     //
8001     if (!varTypeIsIntegralOrI(TypeGet()) && (TypeGet() != TYP_VOID))
8002     {
8003         return false;
8004     }
8005
8006     if (((gtFlags & GTF_SET_FLAGS) != 0) && (gtOper != GT_IND))
8007     {
8008         // GTF_SET_FLAGS is not valid on GT_IND and is overlaid with GTF_NONFAULTING_IND
8009         return true;
8010     }
8011     else
8012     {
8013         return false;
8014     }
8015 }
8016
8017 bool GenTree::gtRequestSetFlags()
8018 {
8019     bool result = false;
8020
8021 #if FEATURE_SET_FLAGS
8022     // This method is a Nop unless FEATURE_SET_FLAGS is defined
8023
8024     // In order to set GTF_SET_FLAGS
8025     //              we must have a GTK_SMPOP
8026     //          and we have a integer or machine size type (not floating point or TYP_LONG on 32-bit)
8027     //
8028     if (!OperIsSimple())
8029         return false;
8030
8031     if (!varTypeIsIntegralOrI(TypeGet()))
8032         return false;
8033
8034     switch (gtOper)
8035     {
8036         case GT_IND:
8037         case GT_ARR_LENGTH:
8038             // These will turn into simple load from memory instructions
8039             // and we can't force the setting of the flags on load from memory
8040             break;
8041
8042         case GT_MUL:
8043         case GT_DIV:
8044             // These instructions don't set the flags (on x86/x64)
8045             //
8046             break;
8047
8048         default:
8049             // Otherwise we can set the flags for this gtOper
8050             // and codegen must set the condition flags.
8051             //
8052             gtFlags |= GTF_SET_FLAGS;
8053             result = true;
8054             break;
8055     }
8056 #endif // FEATURE_SET_FLAGS
8057
8058     // Codegen for this tree must set the condition flags if
8059     // this method returns true.
8060     //
8061     return result;
8062 }
8063
8064 unsigned GenTree::NumChildren()
8065 {
8066     if (OperIsConst() || OperIsLeaf())
8067     {
8068         return 0;
8069     }
8070     else if (OperIsUnary())
8071     {
8072         if (OperGet() == GT_NOP || OperGet() == GT_RETURN || OperGet() == GT_RETFILT)
8073         {
8074             if (gtOp.gtOp1 == nullptr)
8075             {
8076                 return 0;
8077             }
8078             else
8079             {
8080                 return 1;
8081             }
8082         }
8083         else
8084         {
8085             return 1;
8086         }
8087     }
8088     else if (OperIsBinary())
8089     {
8090         // All binary operators except LEA have at least one arg; the second arg may sometimes be null, however.
8091         if (OperGet() == GT_LEA)
8092         {
8093             unsigned childCount = 0;
8094             if (gtOp.gtOp1 != nullptr)
8095             {
8096                 childCount++;
8097             }
8098             if (gtOp.gtOp2 != nullptr)
8099             {
8100                 childCount++;
8101             }
8102             return childCount;
8103         }
8104 #ifdef FEATURE_HW_INTRINSICS
8105         // GT_HWIntrinsic require special handling
8106         if (OperGet() == GT_HWIntrinsic)
8107         {
8108             if (gtOp.gtOp1 == nullptr)
8109             {
8110                 return 0;
8111             }
8112         }
8113 #endif
8114         assert(gtOp.gtOp1 != nullptr);
8115         if (gtOp.gtOp2 == nullptr)
8116         {
8117             return 1;
8118         }
8119         else
8120         {
8121             return 2;
8122         }
8123     }
8124     else
8125     {
8126         // Special
8127         switch (OperGet())
8128         {
8129             case GT_CMPXCHG:
8130                 return 3;
8131
8132             case GT_ARR_BOUNDS_CHECK:
8133 #ifdef FEATURE_SIMD
8134             case GT_SIMD_CHK:
8135 #endif // FEATURE_SIMD
8136 #ifdef FEATURE_HW_INTRINSICS
8137             case GT_HW_INTRINSIC_CHK:
8138 #endif // FEATURE_HW_INTRINSICS
8139                 return 2;
8140
8141             case GT_FIELD:
8142             case GT_STMT:
8143                 return 1;
8144
8145             case GT_ARR_ELEM:
8146                 return 1 + AsArrElem()->gtArrRank;
8147
8148             case GT_DYN_BLK:
8149                 return 2;
8150
8151             case GT_ARR_OFFSET:
8152             case GT_STORE_DYN_BLK:
8153                 return 3;
8154
8155             case GT_CALL:
8156             {
8157                 GenTreeCall* call = AsCall();
8158                 unsigned     res  = 0; // arg list(s) (including late args).
8159                 if (call->gtCallObjp != nullptr)
8160                 {
8161                     res++; // Add objp?
8162                 }
8163                 if (call->gtCallArgs != nullptr)
8164                 {
8165                     res++; // Add args?
8166                 }
8167                 if (call->gtCallLateArgs != nullptr)
8168                 {
8169                     res++; // Add late args?
8170                 }
8171                 if (call->gtControlExpr != nullptr)
8172                 {
8173                     res++;
8174                 }
8175
8176                 if (call->gtCallType == CT_INDIRECT)
8177                 {
8178                     if (call->gtCallCookie != nullptr)
8179                     {
8180                         res++;
8181                     }
8182                     if (call->gtCallAddr != nullptr)
8183                     {
8184                         res++;
8185                     }
8186                 }
8187                 return res;
8188             }
8189             case GT_NONE:
8190                 return 0;
8191             default:
8192                 unreached();
8193         }
8194     }
8195 }
8196
8197 GenTree* GenTree::GetChild(unsigned childNum)
8198 {
8199     assert(childNum < NumChildren()); // Precondition.
8200     assert(NumChildren() <= MAX_CHILDREN);
8201     assert(!(OperIsConst() || OperIsLeaf()));
8202     if (OperIsUnary())
8203     {
8204         return AsUnOp()->gtOp1;
8205     }
8206     // Special case for assignment of dynamic block.
8207     // This code is here to duplicate the former case where the size may be evaluated prior to the
8208     // source and destination addresses. In order to do this, we treat the size as a child of the
8209     // assignment.
8210     // TODO-1stClassStructs: Revisit the need to duplicate former behavior, so that we can remove
8211     // these special cases.
8212     if ((OperGet() == GT_ASG) && (gtOp.gtOp1->OperGet() == GT_DYN_BLK) && (childNum == 2))
8213     {
8214         return gtOp.gtOp1->AsDynBlk()->gtDynamicSize;
8215     }
8216     else if (OperIsBinary())
8217     {
8218         if (OperIsAddrMode())
8219         {
8220             // If this is the first (0th) child, only return op1 if it is non-null
8221             // Otherwise, we return gtOp2.
8222             if (childNum == 0 && AsOp()->gtOp1 != nullptr)
8223             {
8224                 return AsOp()->gtOp1;
8225             }
8226             return AsOp()->gtOp2;
8227         }
8228         // TODO-Cleanup: Consider handling ReverseOps here, and then we wouldn't have to handle it in
8229         // fgGetFirstNode().  However, it seems that it causes loop hoisting behavior to change.
8230         if (childNum == 0)
8231         {
8232             return AsOp()->gtOp1;
8233         }
8234         else
8235         {
8236             return AsOp()->gtOp2;
8237         }
8238     }
8239     else
8240     {
8241         // Special
8242         switch (OperGet())
8243         {
8244             case GT_CMPXCHG:
8245                 switch (childNum)
8246                 {
8247                     case 0:
8248                         return AsCmpXchg()->gtOpLocation;
8249                     case 1:
8250                         return AsCmpXchg()->gtOpValue;
8251                     case 2:
8252                         return AsCmpXchg()->gtOpComparand;
8253                     default:
8254                         unreached();
8255                 }
8256             case GT_ARR_BOUNDS_CHECK:
8257 #ifdef FEATURE_SIMD
8258             case GT_SIMD_CHK:
8259 #endif // FEATURE_SIMD
8260 #ifdef FEATURE_HW_INTRINSICS
8261             case GT_HW_INTRINSIC_CHK:
8262 #endif // FEATURE_HW_INTRINSICS
8263                 switch (childNum)
8264                 {
8265                     case 0:
8266                         return AsBoundsChk()->gtIndex;
8267                     case 1:
8268                         return AsBoundsChk()->gtArrLen;
8269                     default:
8270                         unreached();
8271                 }
8272
8273             case GT_STORE_DYN_BLK:
8274                 switch (childNum)
8275                 {
8276                     case 0:
8277                         return AsDynBlk()->Addr();
8278                     case 1:
8279                         return AsDynBlk()->Data();
8280                     case 2:
8281                         return AsDynBlk()->gtDynamicSize;
8282                     default:
8283                         unreached();
8284                 }
8285             case GT_DYN_BLK:
8286                 switch (childNum)
8287                 {
8288                     case 0:
8289                         return AsDynBlk()->gtEvalSizeFirst ? AsDynBlk()->gtDynamicSize : AsDynBlk()->Addr();
8290                     case 1:
8291                         return AsDynBlk()->gtEvalSizeFirst ? AsDynBlk()->Addr() : AsDynBlk()->gtDynamicSize;
8292                     default:
8293                         unreached();
8294                 }
8295
8296             case GT_FIELD:
8297                 return AsField()->gtFldObj;
8298
8299             case GT_STMT:
8300                 return AsStmt()->gtStmtExpr;
8301
8302             case GT_ARR_ELEM:
8303                 if (childNum == 0)
8304                 {
8305                     return AsArrElem()->gtArrObj;
8306                 }
8307                 else
8308                 {
8309                     return AsArrElem()->gtArrInds[childNum - 1];
8310                 }
8311
8312             case GT_ARR_OFFSET:
8313                 switch (childNum)
8314                 {
8315                     case 0:
8316                         return AsArrOffs()->gtOffset;
8317                     case 1:
8318                         return AsArrOffs()->gtIndex;
8319                     case 2:
8320                         return AsArrOffs()->gtArrObj;
8321                     default:
8322                         unreached();
8323                 }
8324
8325             case GT_CALL:
8326             {
8327                 // The if chain below assumes that all possible children are non-null.
8328                 // If some are null, "virtually skip them."
8329                 // If there isn't "virtually skip it."
8330                 GenTreeCall* call = AsCall();
8331
8332                 if (call->gtCallObjp == nullptr)
8333                 {
8334                     childNum++;
8335                 }
8336                 if (childNum >= 1 && call->gtCallArgs == nullptr)
8337                 {
8338                     childNum++;
8339                 }
8340                 if (childNum >= 2 && call->gtCallLateArgs == nullptr)
8341                 {
8342                     childNum++;
8343                 }
8344                 if (childNum >= 3 && call->gtControlExpr == nullptr)
8345                 {
8346                     childNum++;
8347                 }
8348                 if (call->gtCallType == CT_INDIRECT)
8349                 {
8350                     if (childNum >= 4 && call->gtCallCookie == nullptr)
8351                     {
8352                         childNum++;
8353                     }
8354                 }
8355
8356                 if (childNum == 0)
8357                 {
8358                     return call->gtCallObjp;
8359                 }
8360                 else if (childNum == 1)
8361                 {
8362                     return call->gtCallArgs;
8363                 }
8364                 else if (childNum == 2)
8365                 {
8366                     return call->gtCallLateArgs;
8367                 }
8368                 else if (childNum == 3)
8369                 {
8370                     return call->gtControlExpr;
8371                 }
8372                 else
8373                 {
8374                     assert(call->gtCallType == CT_INDIRECT);
8375                     if (childNum == 4)
8376                     {
8377                         return call->gtCallCookie;
8378                     }
8379                     else
8380                     {
8381                         assert(childNum == 5);
8382                         return call->gtCallAddr;
8383                     }
8384                 }
8385             }
8386             case GT_NONE:
8387                 unreached();
8388             default:
8389                 unreached();
8390         }
8391     }
8392 }
8393
8394 GenTreeUseEdgeIterator::GenTreeUseEdgeIterator()
8395     : m_advance(nullptr), m_node(nullptr), m_edge(nullptr), m_argList(nullptr), m_state(-1)
8396 {
8397 }
8398
8399 GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
8400     : m_advance(nullptr), m_node(node), m_edge(nullptr), m_argList(nullptr), m_state(0)
8401 {
8402     assert(m_node != nullptr);
8403
8404     // NOTE: the switch statement below must be updated when introducing new nodes.
8405
8406     switch (m_node->OperGet())
8407     {
8408         // Leaf nodes
8409         case GT_LCL_VAR:
8410         case GT_LCL_FLD:
8411         case GT_LCL_VAR_ADDR:
8412         case GT_LCL_FLD_ADDR:
8413         case GT_CATCH_ARG:
8414         case GT_LABEL:
8415         case GT_FTN_ADDR:
8416         case GT_RET_EXPR:
8417         case GT_CNS_INT:
8418         case GT_CNS_LNG:
8419         case GT_CNS_DBL:
8420         case GT_CNS_STR:
8421         case GT_MEMORYBARRIER:
8422         case GT_JMP:
8423         case GT_JCC:
8424         case GT_SETCC:
8425         case GT_NO_OP:
8426         case GT_START_NONGC:
8427         case GT_PROF_HOOK:
8428 #if !FEATURE_EH_FUNCLETS
8429         case GT_END_LFIN:
8430 #endif // !FEATURE_EH_FUNCLETS
8431         case GT_PHI_ARG:
8432         case GT_JMPTABLE:
8433         case GT_CLS_VAR:
8434         case GT_CLS_VAR_ADDR:
8435         case GT_ARGPLACE:
8436         case GT_PHYSREG:
8437         case GT_EMITNOP:
8438         case GT_PINVOKE_PROLOG:
8439         case GT_PINVOKE_EPILOG:
8440         case GT_IL_OFFSET:
8441             m_state = -1;
8442             return;
8443
8444         // Standard unary operators
8445         case GT_STORE_LCL_VAR:
8446         case GT_STORE_LCL_FLD:
8447         case GT_NOT:
8448         case GT_NEG:
8449         case GT_COPY:
8450         case GT_RELOAD:
8451         case GT_ARR_LENGTH:
8452         case GT_CAST:
8453         case GT_BITCAST:
8454         case GT_CKFINITE:
8455         case GT_LCLHEAP:
8456         case GT_ADDR:
8457         case GT_IND:
8458         case GT_OBJ:
8459         case GT_BLK:
8460         case GT_BOX:
8461         case GT_ALLOCOBJ:
8462         case GT_RUNTIMELOOKUP:
8463         case GT_INIT_VAL:
8464         case GT_JTRUE:
8465         case GT_SWITCH:
8466         case GT_NULLCHECK:
8467         case GT_PUTARG_REG:
8468         case GT_PUTARG_STK:
8469         case GT_BSWAP:
8470         case GT_BSWAP16:
8471 #if FEATURE_ARG_SPLIT
8472         case GT_PUTARG_SPLIT:
8473 #endif // FEATURE_ARG_SPLIT
8474         case GT_RETURNTRAP:
8475             m_edge = &m_node->AsUnOp()->gtOp1;
8476             assert(*m_edge != nullptr);
8477             m_advance = &GenTreeUseEdgeIterator::Terminate;
8478             return;
8479
8480         // Unary operators with an optional operand
8481         case GT_NOP:
8482         case GT_RETURN:
8483         case GT_RETFILT:
8484             if (m_node->AsUnOp()->gtOp1 == nullptr)
8485             {
8486                 assert(m_node->NullOp1Legal());
8487                 m_state = -1;
8488             }
8489             else
8490             {
8491                 m_edge    = &m_node->AsUnOp()->gtOp1;
8492                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8493             }
8494             return;
8495
8496         // Variadic nodes
8497         case GT_PHI:
8498             SetEntryStateForList(m_node->AsUnOp()->gtOp1);
8499             return;
8500
8501         case GT_FIELD_LIST:
8502             SetEntryStateForList(m_node);
8503             return;
8504
8505 #ifdef FEATURE_SIMD
8506         case GT_SIMD:
8507             if (m_node->AsSIMD()->gtSIMDIntrinsicID == SIMDIntrinsicInitN)
8508             {
8509                 SetEntryStateForList(m_node->AsSIMD()->gtOp1);
8510             }
8511             else
8512             {
8513                 SetEntryStateForBinOp();
8514             }
8515             return;
8516 #endif // FEATURE_SIMD
8517
8518 #ifdef FEATURE_HW_INTRINSICS
8519         case GT_HWIntrinsic:
8520             if (m_node->AsHWIntrinsic()->gtOp1 == nullptr)
8521             {
8522                 assert(m_node->NullOp1Legal());
8523                 m_state = -1;
8524             }
8525             else if (m_node->AsHWIntrinsic()->gtOp1->OperIsList())
8526             {
8527                 SetEntryStateForList(m_node->AsHWIntrinsic()->gtOp1);
8528             }
8529             else
8530             {
8531                 SetEntryStateForBinOp();
8532             }
8533             return;
8534 #endif // FEATURE_HW_INTRINSICS
8535
8536         // LEA, which may have no first operand
8537         case GT_LEA:
8538             if (m_node->AsAddrMode()->gtOp1 == nullptr)
8539             {
8540                 m_edge    = &m_node->AsAddrMode()->gtOp2;
8541                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8542             }
8543             else
8544             {
8545                 SetEntryStateForBinOp();
8546             }
8547             return;
8548
8549         // Special nodes
8550         case GT_CMPXCHG:
8551             m_edge = &m_node->AsCmpXchg()->gtOpLocation;
8552             assert(*m_edge != nullptr);
8553             m_advance = &GenTreeUseEdgeIterator::AdvanceCmpXchg;
8554             return;
8555
8556         case GT_ARR_BOUNDS_CHECK:
8557 #ifdef FEATURE_SIMD
8558         case GT_SIMD_CHK:
8559 #endif // FEATURE_SIMD
8560 #ifdef FEATURE_HW_INTRINSICS
8561         case GT_HW_INTRINSIC_CHK:
8562 #endif // FEATURE_HW_INTRINSICS
8563             m_edge = &m_node->AsBoundsChk()->gtIndex;
8564             assert(*m_edge != nullptr);
8565             m_advance = &GenTreeUseEdgeIterator::AdvanceBoundsChk;
8566             return;
8567
8568         case GT_FIELD:
8569             if (m_node->AsField()->gtFldObj == nullptr)
8570             {
8571                 m_state = -1;
8572             }
8573             else
8574             {
8575                 m_edge    = &m_node->AsField()->gtFldObj;
8576                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8577             }
8578             return;
8579
8580         case GT_STMT:
8581             if (m_node->AsStmt()->gtStmtExpr == nullptr)
8582             {
8583                 m_state = -1;
8584             }
8585             else
8586             {
8587                 m_edge    = &m_node->AsStmt()->gtStmtExpr;
8588                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8589             }
8590             return;
8591
8592         case GT_ARR_ELEM:
8593             m_edge = &m_node->AsArrElem()->gtArrObj;
8594             assert(*m_edge != nullptr);
8595             m_advance = &GenTreeUseEdgeIterator::AdvanceArrElem;
8596             return;
8597
8598         case GT_ARR_OFFSET:
8599             m_edge = &m_node->AsArrOffs()->gtOffset;
8600             assert(*m_edge != nullptr);
8601             m_advance = &GenTreeUseEdgeIterator::AdvanceArrOffset;
8602             return;
8603
8604         case GT_DYN_BLK:
8605         {
8606             GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
8607             m_edge                        = dynBlock->gtEvalSizeFirst ? &dynBlock->gtDynamicSize : &dynBlock->gtOp1;
8608             assert(*m_edge != nullptr);
8609             m_advance = &GenTreeUseEdgeIterator::AdvanceDynBlk;
8610         }
8611             return;
8612
8613         case GT_STORE_DYN_BLK:
8614         {
8615             GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
8616             if (dynBlock->gtEvalSizeFirst)
8617             {
8618                 m_edge = &dynBlock->gtDynamicSize;
8619             }
8620             else
8621             {
8622                 m_edge = dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1;
8623             }
8624             assert(*m_edge != nullptr);
8625
8626             m_advance = &GenTreeUseEdgeIterator::AdvanceStoreDynBlk;
8627         }
8628             return;
8629
8630         case GT_CALL:
8631             AdvanceCall<CALL_INSTANCE>();
8632             return;
8633
8634         // Binary nodes
8635         default:
8636             assert(m_node->OperIsBinary());
8637             SetEntryStateForBinOp();
8638             return;
8639     }
8640 }
8641
8642 //------------------------------------------------------------------------
8643 // GenTreeUseEdgeIterator::AdvanceCmpXchg: produces the next operand of a CmpXchg node and advances the state.
8644 //
8645 void GenTreeUseEdgeIterator::AdvanceCmpXchg()
8646 {
8647     switch (m_state)
8648     {
8649         case 0:
8650             m_edge  = &m_node->AsCmpXchg()->gtOpValue;
8651             m_state = 1;
8652             break;
8653         case 1:
8654             m_edge    = &m_node->AsCmpXchg()->gtOpComparand;
8655             m_advance = &GenTreeUseEdgeIterator::Terminate;
8656             break;
8657         default:
8658             unreached();
8659     }
8660
8661     assert(*m_edge != nullptr);
8662 }
8663
8664 //------------------------------------------------------------------------
8665 // GenTreeUseEdgeIterator::AdvanceBoundsChk: produces the next operand of a BoundsChk node and advances the state.
8666 //
8667 void GenTreeUseEdgeIterator::AdvanceBoundsChk()
8668 {
8669     m_edge = &m_node->AsBoundsChk()->gtArrLen;
8670     assert(*m_edge != nullptr);
8671     m_advance = &GenTreeUseEdgeIterator::Terminate;
8672 }
8673
8674 //------------------------------------------------------------------------
8675 // GenTreeUseEdgeIterator::AdvanceArrElem: produces the next operand of a ArrElem node and advances the state.
8676 //
8677 // Because these nodes are variadic, this function uses `m_state` to index into the list of array indices.
8678 //
8679 void GenTreeUseEdgeIterator::AdvanceArrElem()
8680 {
8681     if (m_state < m_node->AsArrElem()->gtArrRank)
8682     {
8683         m_edge = &m_node->AsArrElem()->gtArrInds[m_state];
8684         assert(*m_edge != nullptr);
8685         m_state++;
8686     }
8687     else
8688     {
8689         m_state = -1;
8690     }
8691 }
8692
8693 //------------------------------------------------------------------------
8694 // GenTreeUseEdgeIterator::AdvanceArrOffset: produces the next operand of a ArrOffset node and advances the state.
8695 //
8696 void GenTreeUseEdgeIterator::AdvanceArrOffset()
8697 {
8698     switch (m_state)
8699     {
8700         case 0:
8701             m_edge  = &m_node->AsArrOffs()->gtIndex;
8702             m_state = 1;
8703             break;
8704         case 1:
8705             m_edge    = &m_node->AsArrOffs()->gtArrObj;
8706             m_advance = &GenTreeUseEdgeIterator::Terminate;
8707             break;
8708         default:
8709             unreached();
8710     }
8711
8712     assert(*m_edge != nullptr);
8713 }
8714
8715 //------------------------------------------------------------------------
8716 // GenTreeUseEdgeIterator::AdvanceDynBlk: produces the next operand of a DynBlk node and advances the state.
8717 //
8718 void GenTreeUseEdgeIterator::AdvanceDynBlk()
8719 {
8720     GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
8721
8722     m_edge = dynBlock->gtEvalSizeFirst ? &dynBlock->gtOp1 : &dynBlock->gtDynamicSize;
8723     assert(*m_edge != nullptr);
8724     m_advance = &GenTreeUseEdgeIterator::Terminate;
8725 }
8726
8727 //------------------------------------------------------------------------
8728 // GenTreeUseEdgeIterator::AdvanceStoreDynBlk: produces the next operand of a StoreDynBlk node and advances the state.
8729 //
8730 // These nodes are moderately complicated but rare enough that templating this function is probably not
8731 // worth the extra complexity.
8732 //
8733 void GenTreeUseEdgeIterator::AdvanceStoreDynBlk()
8734 {
8735     GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
8736     if (dynBlock->gtEvalSizeFirst)
8737     {
8738         switch (m_state)
8739         {
8740             case 0:
8741                 m_edge  = dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1;
8742                 m_state = 1;
8743                 break;
8744             case 1:
8745                 m_edge    = dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2;
8746                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8747                 break;
8748             default:
8749                 unreached();
8750         }
8751     }
8752     else
8753     {
8754         switch (m_state)
8755         {
8756             case 0:
8757                 m_edge  = dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2;
8758                 m_state = 1;
8759                 break;
8760             case 1:
8761                 m_edge    = &dynBlock->gtDynamicSize;
8762                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8763                 break;
8764             default:
8765                 unreached();
8766         }
8767     }
8768
8769     assert(*m_edge != nullptr);
8770 }
8771
8772 //------------------------------------------------------------------------
8773 // GenTreeUseEdgeIterator::AdvanceBinOp: produces the next operand of a binary node and advances the state.
8774 //
8775 // This function must be instantiated s.t. `ReverseOperands` is `true` iff the node is marked with the
8776 // `GTF_REVERSE_OPS` flag.
8777 //
8778 template <bool ReverseOperands>
8779 void           GenTreeUseEdgeIterator::AdvanceBinOp()
8780 {
8781     assert(ReverseOperands == ((m_node->gtFlags & GTF_REVERSE_OPS) != 0));
8782
8783     m_edge = !ReverseOperands ? &m_node->AsOp()->gtOp2 : &m_node->AsOp()->gtOp1;
8784     assert(*m_edge != nullptr);
8785     m_advance = &GenTreeUseEdgeIterator::Terminate;
8786 }
8787
8788 //------------------------------------------------------------------------
8789 // GenTreeUseEdgeIterator::SetEntryStateForBinOp: produces the first operand of a binary node and chooses
8790 //                                                the appropriate advance function.
8791 //
8792 void GenTreeUseEdgeIterator::SetEntryStateForBinOp()
8793 {
8794     assert(m_node != nullptr);
8795     assert(m_node->OperIsBinary());
8796
8797     GenTreeOp* const node = m_node->AsOp();
8798
8799     if (node->gtOp2 == nullptr)
8800     {
8801         assert(node->gtOp1 != nullptr);
8802         assert(node->NullOp2Legal());
8803         m_edge    = &node->gtOp1;
8804         m_advance = &GenTreeUseEdgeIterator::Terminate;
8805     }
8806     else if ((node->gtFlags & GTF_REVERSE_OPS) != 0)
8807     {
8808         m_edge    = &m_node->AsOp()->gtOp2;
8809         m_advance = &GenTreeUseEdgeIterator::AdvanceBinOp<true>;
8810     }
8811     else
8812     {
8813         m_edge    = &m_node->AsOp()->gtOp1;
8814         m_advance = &GenTreeUseEdgeIterator::AdvanceBinOp<false>;
8815     }
8816 }
8817
8818 //------------------------------------------------------------------------
8819 // GenTreeUseEdgeIterator::AdvanceList: produces the next operand of a variadic node and advances the state.
8820 //
8821 // This function does not use `m_state` for anything meaningful; it simply walks the `m_argList` until
8822 // there are no further entries.
8823 //
8824 void GenTreeUseEdgeIterator::AdvanceList()
8825 {
8826     assert(m_state == 0);
8827
8828     if (m_argList == nullptr)
8829     {
8830         m_state = -1;
8831     }
8832     else
8833     {
8834         GenTreeArgList* listNode = m_argList->AsArgList();
8835         m_edge                   = &listNode->gtOp1;
8836         m_argList                = listNode->Rest();
8837     }
8838 }
8839
8840 //------------------------------------------------------------------------
8841 // GenTreeUseEdgeIterator::SetEntryStateForList: produces the first operand of a list node.
8842 //
8843 void GenTreeUseEdgeIterator::SetEntryStateForList(GenTree* list)
8844 {
8845     m_argList = list;
8846     m_advance = &GenTreeUseEdgeIterator::AdvanceList;
8847     AdvanceList();
8848 }
8849
8850 //------------------------------------------------------------------------
8851 // GenTreeUseEdgeIterator::AdvanceCall: produces the next operand of a call node and advances the state.
8852 //
8853 // This function is a bit tricky: in order to avoid doing unnecessary work, it is instantiated with the
8854 // state number the iterator will be in when it is called. For example, `AdvanceCall<CALL_INSTANCE>`
8855 // is the instantiation used when the iterator is at the `CALL_INSTANCE` state (i.e. the entry state).
8856 // This sort of templating allows each state to avoid processing earlier states without unnecessary
8857 // duplication of code.
8858 //
8859 // Note that this method expands the argument lists (`gtCallArgs` and `gtCallLateArgs`) into their
8860 // component operands.
8861 //
8862 template <int state>
8863 void          GenTreeUseEdgeIterator::AdvanceCall()
8864 {
8865     GenTreeCall* const call = m_node->AsCall();
8866
8867     switch (state)
8868     {
8869         case CALL_INSTANCE:
8870             m_argList = call->gtCallArgs;
8871             m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_ARGS>;
8872             if (call->gtCallObjp != nullptr)
8873             {
8874                 m_edge = &call->gtCallObjp;
8875                 return;
8876             }
8877             __fallthrough;
8878
8879         case CALL_ARGS:
8880             if (m_argList != nullptr)
8881             {
8882                 GenTreeArgList* argNode = m_argList->AsArgList();
8883                 m_edge                  = &argNode->gtOp1;
8884                 m_argList               = argNode->Rest();
8885                 return;
8886             }
8887             m_argList = call->gtCallLateArgs;
8888             m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_LATE_ARGS>;
8889             __fallthrough;
8890
8891         case CALL_LATE_ARGS:
8892             if (m_argList != nullptr)
8893             {
8894                 GenTreeArgList* argNode = m_argList->AsArgList();
8895                 m_edge                  = &argNode->gtOp1;
8896                 m_argList               = argNode->Rest();
8897                 return;
8898             }
8899             m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_CONTROL_EXPR>;
8900             __fallthrough;
8901
8902         case CALL_CONTROL_EXPR:
8903             if (call->gtControlExpr != nullptr)
8904             {
8905                 if (call->gtCallType == CT_INDIRECT)
8906                 {
8907                     m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_COOKIE>;
8908                 }
8909                 else
8910                 {
8911                     m_advance = &GenTreeUseEdgeIterator::Terminate;
8912                 }
8913                 m_edge = &call->gtControlExpr;
8914                 return;
8915             }
8916             else if (call->gtCallType != CT_INDIRECT)
8917             {
8918                 m_state = -1;
8919                 return;
8920             }
8921             __fallthrough;
8922
8923         case CALL_COOKIE:
8924             assert(call->gtCallType == CT_INDIRECT);
8925
8926             m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_ADDRESS>;
8927             if (call->gtCallCookie != nullptr)
8928             {
8929                 m_edge = &call->gtCallCookie;
8930                 return;
8931             }
8932             __fallthrough;
8933
8934         case CALL_ADDRESS:
8935             assert(call->gtCallType == CT_INDIRECT);
8936
8937             m_advance = &GenTreeUseEdgeIterator::Terminate;
8938             if (call->gtCallAddr != nullptr)
8939             {
8940                 m_edge = &call->gtCallAddr;
8941             }
8942             return;
8943
8944         default:
8945             unreached();
8946     }
8947 }
8948
8949 //------------------------------------------------------------------------
8950 // GenTreeUseEdgeIterator::Terminate: advances the iterator to the terminal state.
8951 //
8952 void GenTreeUseEdgeIterator::Terminate()
8953 {
8954     m_state = -1;
8955 }
8956
8957 //------------------------------------------------------------------------
8958 // GenTreeUseEdgeIterator::operator++: advances the iterator to the next operand.
8959 //
8960 GenTreeUseEdgeIterator& GenTreeUseEdgeIterator::operator++()
8961 {
8962     // If we've reached the terminal state, do nothing.
8963     if (m_state != -1)
8964     {
8965         (this->*m_advance)();
8966     }
8967
8968     return *this;
8969 }
8970
8971 GenTreeUseEdgeIterator GenTree::UseEdgesBegin()
8972 {
8973     return GenTreeUseEdgeIterator(this);
8974 }
8975
8976 GenTreeUseEdgeIterator GenTree::UseEdgesEnd()
8977 {
8978     return GenTreeUseEdgeIterator();
8979 }
8980
8981 IteratorPair<GenTreeUseEdgeIterator> GenTree::UseEdges()
8982 {
8983     return MakeIteratorPair(UseEdgesBegin(), UseEdgesEnd());
8984 }
8985
8986 GenTreeOperandIterator GenTree::OperandsBegin()
8987 {
8988     return GenTreeOperandIterator(this);
8989 }
8990
8991 GenTreeOperandIterator GenTree::OperandsEnd()
8992 {
8993     return GenTreeOperandIterator();
8994 }
8995
8996 IteratorPair<GenTreeOperandIterator> GenTree::Operands()
8997 {
8998     return MakeIteratorPair(OperandsBegin(), OperandsEnd());
8999 }
9000
9001 bool GenTree::Precedes(GenTree* other)
9002 {
9003     assert(other != nullptr);
9004
9005     for (GenTree* node = gtNext; node != nullptr; node = node->gtNext)
9006     {
9007         if (node == other)
9008         {
9009             return true;
9010         }
9011     }
9012
9013     return false;
9014 }
9015
9016 #ifdef DEBUG
9017
9018 /* static */ int GenTree::gtDispFlags(unsigned flags, unsigned debugFlags)
9019 {
9020     int charsDisplayed = 11; // 11 is the "baseline" number of flag characters displayed
9021
9022     printf("%c", (flags & GTF_ASG) ? 'A' : (IsContained(flags) ? 'c' : '-'));
9023     printf("%c", (flags & GTF_CALL) ? 'C' : '-');
9024     printf("%c", (flags & GTF_EXCEPT) ? 'X' : '-');
9025     printf("%c", (flags & GTF_GLOB_REF) ? 'G' : '-');
9026     printf("%c", (debugFlags & GTF_DEBUG_NODE_MORPHED) ? '+' : // First print '+' if GTF_DEBUG_NODE_MORPHED is set
9027                      (flags & GTF_ORDER_SIDEEFF) ? 'O' : '-'); // otherwise print 'O' or '-'
9028     printf("%c", (flags & GTF_COLON_COND) ? '?' : '-');
9029     printf("%c", (flags & GTF_DONT_CSE) ? 'N' :           // N is for No cse
9030                      (flags & GTF_MAKE_CSE) ? 'H' : '-'); // H is for Hoist this expr
9031     printf("%c", (flags & GTF_REVERSE_OPS) ? 'R' : '-');
9032     printf("%c", (flags & GTF_UNSIGNED) ? 'U' : (flags & GTF_BOOLEAN) ? 'B' : '-');
9033 #if FEATURE_SET_FLAGS
9034     printf("%c", (flags & GTF_SET_FLAGS) ? 'S' : '-');
9035     ++charsDisplayed;
9036 #endif
9037     printf("%c", (flags & GTF_LATE_ARG) ? 'L' : '-');
9038     printf("%c", (flags & GTF_SPILLED) ? 'z' : (flags & GTF_SPILL) ? 'Z' : '-');
9039
9040     return charsDisplayed;
9041 }
9042
9043 /*****************************************************************************/
9044
9045 void Compiler::gtDispNodeName(GenTree* tree)
9046 {
9047     /* print the node name */
9048
9049     const char* name;
9050
9051     assert(tree);
9052     if (tree->gtOper < GT_COUNT)
9053     {
9054         name = GenTree::OpName(tree->OperGet());
9055     }
9056     else
9057     {
9058         name = "<ERROR>";
9059     }
9060     char  buf[32];
9061     char* bufp = &buf[0];
9062
9063     if ((tree->gtOper == GT_CNS_INT) && tree->IsIconHandle())
9064     {
9065         sprintf_s(bufp, sizeof(buf), " %s(h)%c", name, 0);
9066     }
9067     else if (tree->gtOper == GT_PUTARG_STK)
9068     {
9069         sprintf_s(bufp, sizeof(buf), " %s [+0x%02x]%c", name, tree->AsPutArgStk()->getArgOffset(), 0);
9070     }
9071     else if (tree->gtOper == GT_CALL)
9072     {
9073         const char* callType = "CALL";
9074         const char* gtfType  = "";
9075         const char* ctType   = "";
9076         char        gtfTypeBuf[100];
9077
9078         if (tree->gtCall.gtCallType == CT_USER_FUNC)
9079         {
9080             if (tree->gtCall.IsVirtual())
9081             {
9082                 callType = "CALLV";
9083             }
9084         }
9085         else if (tree->gtCall.gtCallType == CT_HELPER)
9086         {
9087             ctType = " help";
9088         }
9089         else if (tree->gtCall.gtCallType == CT_INDIRECT)
9090         {
9091             ctType = " ind";
9092         }
9093         else
9094         {
9095             assert(!"Unknown gtCallType");
9096         }
9097
9098         if (tree->gtFlags & GTF_CALL_NULLCHECK)
9099         {
9100             gtfType = " nullcheck";
9101         }
9102         if (tree->gtCall.IsVirtualVtable())
9103         {
9104             gtfType = " ind";
9105         }
9106         else if (tree->gtCall.IsVirtualStub())
9107         {
9108             gtfType = " stub";
9109         }
9110 #ifdef FEATURE_READYTORUN_COMPILER
9111         else if (tree->gtCall.IsR2RRelativeIndir())
9112         {
9113             gtfType = " r2r_ind";
9114         }
9115 #endif // FEATURE_READYTORUN_COMPILER
9116         else if (tree->gtFlags & GTF_CALL_UNMANAGED)
9117         {
9118             char* gtfTypeBufWalk = gtfTypeBuf;
9119             gtfTypeBufWalk += SimpleSprintf_s(gtfTypeBufWalk, gtfTypeBuf, sizeof(gtfTypeBuf), " unman");
9120             if (tree->gtFlags & GTF_CALL_POP_ARGS)
9121             {
9122                 gtfTypeBufWalk += SimpleSprintf_s(gtfTypeBufWalk, gtfTypeBuf, sizeof(gtfTypeBuf), " popargs");
9123             }
9124             if (tree->gtCall.gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL)
9125             {
9126                 gtfTypeBufWalk += SimpleSprintf_s(gtfTypeBufWalk, gtfTypeBuf, sizeof(gtfTypeBuf), " thiscall");
9127             }
9128             gtfType = gtfTypeBuf;
9129         }
9130
9131         sprintf_s(bufp, sizeof(buf), " %s%s%s%c", callType, ctType, gtfType, 0);
9132     }
9133     else if (tree->gtOper == GT_ARR_ELEM)
9134     {
9135         bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), " %s[", name);
9136         for (unsigned rank = tree->gtArrElem.gtArrRank - 1; rank; rank--)
9137         {
9138             bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), ",");
9139         }
9140         SimpleSprintf_s(bufp, buf, sizeof(buf), "]");
9141     }
9142     else if (tree->gtOper == GT_ARR_OFFSET || tree->gtOper == GT_ARR_INDEX)
9143     {
9144         bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), " %s[", name);
9145         unsigned char currDim;
9146         unsigned char rank;
9147         if (tree->gtOper == GT_ARR_OFFSET)
9148         {
9149             currDim = tree->gtArrOffs.gtCurrDim;
9150             rank    = tree->gtArrOffs.gtArrRank;
9151         }
9152         else
9153         {
9154             currDim = tree->gtArrIndex.gtCurrDim;
9155             rank    = tree->gtArrIndex.gtArrRank;
9156         }
9157
9158         for (unsigned char dim = 0; dim < rank; dim++)
9159         {
9160             // Use a defacto standard i,j,k for the dimensions.
9161             // Note that we only support up to rank 3 arrays with these nodes, so we won't run out of characters.
9162             char dimChar = '*';
9163             if (dim == currDim)
9164             {
9165                 dimChar = 'i' + dim;
9166             }
9167             else if (dim > currDim)
9168             {
9169                 dimChar = ' ';
9170             }
9171
9172             bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "%c", dimChar);
9173             if (dim != rank - 1)
9174             {
9175                 bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), ",");
9176             }
9177         }
9178         SimpleSprintf_s(bufp, buf, sizeof(buf), "]");
9179     }
9180     else if (tree->gtOper == GT_LEA)
9181     {
9182         GenTreeAddrMode* lea = tree->AsAddrMode();
9183         bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), " %s(", name);
9184         if (lea->Base() != nullptr)
9185         {
9186             bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "b+");
9187         }
9188         if (lea->Index() != nullptr)
9189         {
9190             bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "(i*%d)+", lea->gtScale);
9191         }
9192         bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "%d)", lea->Offset());
9193     }
9194     else if (tree->gtOper == GT_ARR_BOUNDS_CHECK)
9195     {
9196         switch (tree->gtBoundsChk.gtThrowKind)
9197         {
9198             case SCK_RNGCHK_FAIL:
9199                 sprintf_s(bufp, sizeof(buf), " %s_Rng", name);
9200                 break;
9201             case SCK_ARG_EXCPN:
9202                 sprintf_s(bufp, sizeof(buf), " %s_Arg", name);
9203                 break;
9204             case SCK_ARG_RNG_EXCPN:
9205                 sprintf_s(bufp, sizeof(buf), " %s_ArgRng", name);
9206                 break;
9207             default:
9208                 unreached();
9209         }
9210     }
9211     else if (tree->gtOverflowEx())
9212     {
9213         sprintf_s(bufp, sizeof(buf), " %s_ovfl%c", name, 0);
9214     }
9215     else if (tree->OperIsBlk() && !tree->OperIsDynBlk())
9216     {
9217         sprintf_s(bufp, sizeof(buf), " %s(%d)", name, tree->AsBlk()->gtBlkSize);
9218     }
9219     else
9220     {
9221         sprintf_s(bufp, sizeof(buf), " %s%c", name, 0);
9222     }
9223
9224     if (strlen(buf) < 10)
9225     {
9226         printf(" %-10s", buf);
9227     }
9228     else
9229     {
9230         printf(" %s", buf);
9231     }
9232 }
9233
9234 void Compiler::gtDispVN(GenTree* tree)
9235 {
9236     if (tree->gtVNPair.GetLiberal() != ValueNumStore::NoVN)
9237     {
9238         assert(tree->gtVNPair.GetConservative() != ValueNumStore::NoVN);
9239         printf(" ");
9240         vnpPrint(tree->gtVNPair, 0);
9241     }
9242 }
9243
9244 //------------------------------------------------------------------------
9245 // gtDispNode: Print a tree to jitstdout.
9246 //
9247 // Arguments:
9248 //    tree - the tree to be printed
9249 //    indentStack - the specification for the current level of indentation & arcs
9250 //    msg         - a contextual method (i.e. from the parent) to print
9251 //
9252 // Return Value:
9253 //    None.
9254 //
9255 // Notes:
9256 //    'indentStack' may be null, in which case no indentation or arcs are printed
9257 //    'msg' may be null
9258
9259 void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, __in __in_z __in_opt const char* msg, bool isLIR)
9260 {
9261     bool printPointer = true; // always true..
9262     bool printFlags   = true; // always true..
9263     bool printCost    = true; // always true..
9264
9265     int msgLength = 25;
9266
9267     GenTree* prev;
9268
9269     if (tree->gtSeqNum)
9270     {
9271         printf("N%03u ", tree->gtSeqNum);
9272         if (tree->gtCostsInitialized)
9273         {
9274             printf("(%3u,%3u) ", tree->gtCostEx, tree->gtCostSz);
9275         }
9276         else
9277         {
9278             printf("(???"
9279                    ",???"
9280                    ") "); // This probably indicates a bug: the node has a sequence number, but not costs.
9281         }
9282     }
9283     else
9284     {
9285         if (tree->gtOper == GT_STMT)
9286         {
9287             prev = tree->gtStmt.gtStmtExpr;
9288         }
9289         else
9290         {
9291             prev = tree;
9292         }
9293
9294         bool     hasSeqNum = true;
9295         unsigned dotNum    = 0;
9296         do
9297         {
9298             dotNum++;
9299             prev = prev->gtPrev;
9300
9301             if ((prev == nullptr) || (prev == tree))
9302             {
9303                 hasSeqNum = false;
9304                 break;
9305             }
9306
9307             assert(prev);
9308         } while (prev->gtSeqNum == 0);
9309
9310         // If we have an indent stack, don't add additional characters,
9311         // as it will mess up the alignment.
9312         bool displayDotNum = tree->gtOper != GT_STMT && hasSeqNum && (indentStack == nullptr);
9313         if (displayDotNum)
9314         {
9315             printf("N%03u.%02u ", prev->gtSeqNum, dotNum);
9316         }
9317         else
9318         {
9319             printf("     ");
9320         }
9321
9322         if (tree->gtCostsInitialized)
9323         {
9324             printf("(%3u,%3u) ", tree->gtCostEx, tree->gtCostSz);
9325         }
9326         else
9327         {
9328             if (displayDotNum)
9329             {
9330                 // Do better alignment in this case
9331                 printf("       ");
9332             }
9333             else
9334             {
9335                 printf("          ");
9336             }
9337         }
9338     }
9339
9340     if (optValnumCSE_phase)
9341     {
9342         if (IS_CSE_INDEX(tree->gtCSEnum))
9343         {
9344             printf("CSE #%02d (%s)", GET_CSE_INDEX(tree->gtCSEnum), (IS_CSE_USE(tree->gtCSEnum) ? "use" : "def"));
9345         }
9346         else
9347         {
9348             printf("             ");
9349         }
9350     }
9351
9352     /* Print the node ID */
9353     printTreeID(tree);
9354     printf(" ");
9355
9356     if (tree->gtOper >= GT_COUNT)
9357     {
9358         printf(" **** ILLEGAL NODE ****");
9359         return;
9360     }
9361
9362     if (printFlags)
9363     {
9364         /* First print the flags associated with the node */
9365         switch (tree->gtOper)
9366         {
9367             case GT_LEA:
9368             case GT_BLK:
9369             case GT_OBJ:
9370             case GT_DYN_BLK:
9371             case GT_STORE_BLK:
9372             case GT_STORE_OBJ:
9373             case GT_STORE_DYN_BLK:
9374
9375             case GT_IND:
9376                 // We prefer printing V or U
9377                 if ((tree->gtFlags & (GTF_IND_VOLATILE | GTF_IND_UNALIGNED)) == 0)
9378                 {
9379                     if (tree->gtFlags & GTF_IND_TGTANYWHERE)
9380                     {
9381                         printf("*");
9382                         --msgLength;
9383                         break;
9384                     }
9385                     if (tree->gtFlags & GTF_IND_INVARIANT)
9386                     {
9387                         printf("#");
9388                         --msgLength;
9389                         break;
9390                     }
9391                     if (tree->gtFlags & GTF_IND_ARR_INDEX)
9392                     {
9393                         printf("a");
9394                         --msgLength;
9395                         break;
9396                     }
9397                     if (tree->gtFlags & GTF_IND_NONFAULTING)
9398                     {
9399                         printf("n"); // print a n for non-faulting
9400                         --msgLength;
9401                         break;
9402                     }
9403                     if (tree->gtFlags & GTF_IND_ASG_LHS)
9404                     {
9405                         printf("D"); // print a D for definition
9406                         --msgLength;
9407                         break;
9408                     }
9409                 }
9410                 __fallthrough;
9411
9412             case GT_INDEX:
9413             case GT_INDEX_ADDR:
9414
9415                 if ((tree->gtFlags & (GTF_IND_VOLATILE | GTF_IND_UNALIGNED)) == 0) // We prefer printing V or U over R
9416                 {
9417                     if (tree->gtFlags & GTF_INX_REFARR_LAYOUT)
9418                     {
9419                         printf("R");
9420                         --msgLength;
9421                         break;
9422                     } // R means RefArray
9423                 }
9424                 __fallthrough;
9425
9426             case GT_FIELD:
9427             case GT_CLS_VAR:
9428                 if (tree->gtFlags & GTF_IND_VOLATILE)
9429                 {
9430                     printf("V");
9431                     --msgLength;
9432                     break;
9433                 }
9434                 if (tree->gtFlags & GTF_IND_UNALIGNED)
9435                 {
9436                     printf("U");
9437                     --msgLength;
9438                     break;
9439                 }
9440                 goto DASH;
9441
9442             case GT_ASG:
9443                 if (tree->OperIsInitBlkOp())
9444                 {
9445                     printf("I");
9446                     --msgLength;
9447                     break;
9448                 }
9449                 goto DASH;
9450
9451             case GT_CALL:
9452                 if (tree->gtCall.IsInlineCandidate())
9453                 {
9454                     if (tree->gtCall.IsGuardedDevirtualizationCandidate())
9455                     {
9456                         printf("&");
9457                     }
9458                     else
9459                     {
9460                         printf("I");
9461                     }
9462                     --msgLength;
9463                     break;
9464                 }
9465                 else if (tree->gtCall.IsGuardedDevirtualizationCandidate())
9466                 {
9467                     printf("G");
9468                     --msgLength;
9469                     break;
9470                 }
9471                 if (tree->gtCall.gtCallMoreFlags & GTF_CALL_M_RETBUFFARG)
9472                 {
9473                     printf("S");
9474                     --msgLength;
9475                     break;
9476                 }
9477                 if (tree->gtFlags & GTF_CALL_HOISTABLE)
9478                 {
9479                     printf("H");
9480                     --msgLength;
9481                     break;
9482                 }
9483
9484                 goto DASH;
9485
9486             case GT_MUL:
9487 #if !defined(_TARGET_64BIT_)
9488             case GT_MUL_LONG:
9489 #endif
9490                 if (tree->gtFlags & GTF_MUL_64RSLT)
9491                 {
9492                     printf("L");
9493                     --msgLength;
9494                     break;
9495                 }
9496                 goto DASH;
9497
9498             case GT_ADDR:
9499                 if (tree->gtFlags & GTF_ADDR_ONSTACK)
9500                 {
9501                     printf("L");
9502                     --msgLength;
9503                     break;
9504                 } // L means LclVar
9505                 goto DASH;
9506
9507             case GT_LCL_FLD:
9508             case GT_LCL_VAR:
9509             case GT_LCL_VAR_ADDR:
9510             case GT_LCL_FLD_ADDR:
9511             case GT_STORE_LCL_FLD:
9512             case GT_STORE_LCL_VAR:
9513                 if (tree->gtFlags & GTF_VAR_USEASG)
9514                 {
9515                     printf("U");
9516                     --msgLength;
9517                     break;
9518                 }
9519                 if (tree->gtFlags & GTF_VAR_DEF)
9520                 {
9521                     printf("D");
9522                     --msgLength;
9523                     break;
9524                 }
9525                 if (tree->gtFlags & GTF_VAR_CAST)
9526                 {
9527                     printf("C");
9528                     --msgLength;
9529                     break;
9530                 }
9531                 if (tree->gtFlags & GTF_VAR_ARR_INDEX)
9532                 {
9533                     printf("i");
9534                     --msgLength;
9535                     break;
9536                 }
9537                 goto DASH;
9538
9539             case GT_EQ:
9540             case GT_NE:
9541             case GT_LT:
9542             case GT_LE:
9543             case GT_GE:
9544             case GT_GT:
9545             case GT_TEST_EQ:
9546             case GT_TEST_NE:
9547                 if (tree->gtFlags & GTF_RELOP_NAN_UN)
9548                 {
9549                     printf("N");
9550                     --msgLength;
9551                     break;
9552                 }
9553                 if (tree->gtFlags & GTF_RELOP_JMP_USED)
9554                 {
9555                     printf("J");
9556                     --msgLength;
9557                     break;
9558                 }
9559                 if (tree->gtFlags & GTF_RELOP_QMARK)
9560                 {
9561                     printf("Q");
9562                     --msgLength;
9563                     break;
9564                 }
9565                 goto DASH;
9566
9567             case GT_JCMP:
9568                 printf((tree->gtFlags & GTF_JCMP_TST) ? "T" : "C");
9569                 printf((tree->gtFlags & GTF_JCMP_EQ) ? "EQ" : "NE");
9570                 goto DASH;
9571
9572             case GT_FIELD_LIST:
9573                 if (tree->gtFlags & GTF_FIELD_LIST_HEAD)
9574                 {
9575                     printf("H");
9576                     --msgLength;
9577                     break;
9578                 }
9579                 goto DASH;
9580
9581             default:
9582             DASH:
9583                 printf("-");
9584                 --msgLength;
9585                 break;
9586         }
9587
9588         /* Then print the general purpose flags */
9589         unsigned flags = tree->gtFlags;
9590
9591         if (tree->OperIsBinary())
9592         {
9593             genTreeOps oper = tree->OperGet();
9594
9595             // Check for GTF_ADDRMODE_NO_CSE flag on add/mul/shl Binary Operators
9596             if ((oper == GT_ADD) || (oper == GT_MUL) || (oper == GT_LSH))
9597             {
9598                 if ((tree->gtFlags & GTF_ADDRMODE_NO_CSE) != 0)
9599                 {
9600                     flags |= GTF_DONT_CSE; // Force the GTF_ADDRMODE_NO_CSE flag to print out like GTF_DONT_CSE
9601                 }
9602             }
9603         }
9604         else // !tree->OperIsBinary()
9605         {
9606             // the GTF_REVERSE flag only applies to binary operations
9607             flags &= ~GTF_REVERSE_OPS; // we use this value for GTF_VAR_ARR_INDEX above
9608         }
9609
9610         msgLength -= GenTree::gtDispFlags(flags, tree->gtDebugFlags);
9611         /*
9612             printf("%c", (flags & GTF_ASG           ) ? 'A' : '-');
9613             printf("%c", (flags & GTF_CALL          ) ? 'C' : '-');
9614             printf("%c", (flags & GTF_EXCEPT        ) ? 'X' : '-');
9615             printf("%c", (flags & GTF_GLOB_REF      ) ? 'G' : '-');
9616             printf("%c", (flags & GTF_ORDER_SIDEEFF ) ? 'O' : '-');
9617             printf("%c", (flags & GTF_COLON_COND    ) ? '?' : '-');
9618             printf("%c", (flags & GTF_DONT_CSE      ) ? 'N' :        // N is for No cse
9619                          (flags & GTF_MAKE_CSE      ) ? 'H' : '-');  // H is for Hoist this expr
9620             printf("%c", (flags & GTF_REVERSE_OPS   ) ? 'R' : '-');
9621             printf("%c", (flags & GTF_UNSIGNED      ) ? 'U' :
9622                          (flags & GTF_BOOLEAN       ) ? 'B' : '-');
9623             printf("%c", (flags & GTF_SET_FLAGS     ) ? 'S' : '-');
9624             printf("%c", (flags & GTF_SPILLED       ) ? 'z' : '-');
9625             printf("%c", (flags & GTF_SPILL         ) ? 'Z' : '-');
9626         */
9627     }
9628
9629     // If we're printing a node for LIR, we use the space normally associated with the message
9630     // to display the node's temp name (if any)
9631     const bool hasOperands = tree->OperandsBegin() != tree->OperandsEnd();
9632     if (isLIR)
9633     {
9634         assert(msg == nullptr);
9635
9636         // If the tree does not have any operands, we do not display the indent stack. This gives us
9637         // two additional characters for alignment.
9638         if (!hasOperands)
9639         {
9640             msgLength += 1;
9641         }
9642
9643         if (tree->IsValue())
9644         {
9645             const size_t bufLength = msgLength - 1;
9646             msg                    = reinterpret_cast<char*>(alloca(bufLength * sizeof(char)));
9647             sprintf_s(const_cast<char*>(msg), bufLength, "t%d = %s", tree->gtTreeID, hasOperands ? "" : " ");
9648         }
9649     }
9650
9651     /* print the msg associated with the node */
9652
9653     if (msg == nullptr)
9654     {
9655         msg = "";
9656     }
9657     if (msgLength < 0)
9658     {
9659         msgLength = 0;
9660     }
9661
9662     printf(isLIR ? " %+*s" : " %-*s", msgLength, msg);
9663
9664     /* Indent the node accordingly */
9665     if (!isLIR || hasOperands)
9666     {
9667         printIndent(indentStack);
9668     }
9669
9670     gtDispNodeName(tree);
9671
9672     assert(tree == nullptr || tree->gtOper < GT_COUNT);
9673
9674     if (tree)
9675     {
9676         /* print the type of the node */
9677         if (tree->gtOper != GT_CAST)
9678         {
9679             printf(" %-6s", varTypeName(tree->TypeGet()));
9680             if (tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_STORE_LCL_VAR)
9681             {
9682                 LclVarDsc* varDsc = &lvaTable[tree->gtLclVarCommon.gtLclNum];
9683                 if (varDsc->lvAddrExposed)
9684                 {
9685                     printf("(AX)"); // Variable has address exposed.
9686                 }
9687
9688                 if (varDsc->lvUnusedStruct)
9689                 {
9690                     assert(varDsc->lvPromoted);
9691                     printf("(U)"); // Unused struct
9692                 }
9693                 else if (varDsc->lvPromoted)
9694                 {
9695                     if (varTypeIsPromotable(varDsc))
9696                     {
9697                         printf("(P)"); // Promoted struct
9698                     }
9699                     else
9700                     {
9701                         // Promoted implicit by-refs can have this state during
9702                         // global morph while they are being rewritten
9703                         assert(fgGlobalMorph);
9704                         printf("(P?!)"); // Promoted struct
9705                     }
9706                 }
9707             }
9708
9709             if (tree->gtOper == GT_STMT)
9710             {
9711                 if (opts.compDbgInfo)
9712                 {
9713                     IL_OFFSET endIL = tree->gtStmt.gtStmtLastILoffs;
9714
9715                     printf("(IL ");
9716                     if (tree->gtStmt.gtStmtILoffsx == BAD_IL_OFFSET)
9717                     {
9718                         printf("  ???");
9719                     }
9720                     else
9721                     {
9722                         printf("0x%03X", jitGetILoffs(tree->gtStmt.gtStmtILoffsx));
9723                     }
9724                     printf("...");
9725                     if (endIL == BAD_IL_OFFSET)
9726                     {
9727                         printf("  ???");
9728                     }
9729                     else
9730                     {
9731                         printf("0x%03X", endIL);
9732                     }
9733                     printf(")");
9734                 }
9735             }
9736
9737             if (tree->IsArgPlaceHolderNode() && (tree->gtArgPlace.gtArgPlaceClsHnd != nullptr))
9738             {
9739                 printf(" => [clsHnd=%08X]", dspPtr(tree->gtArgPlace.gtArgPlaceClsHnd));
9740             }
9741
9742             if (tree->gtOper == GT_RUNTIMELOOKUP)
9743             {
9744 #ifdef _TARGET_64BIT_
9745                 printf(" 0x%llx", dspPtr(tree->gtRuntimeLookup.gtHnd));
9746 #else
9747                 printf(" 0x%x", dspPtr(tree->gtRuntimeLookup.gtHnd));
9748 #endif
9749
9750                 switch (tree->gtRuntimeLookup.gtHndType)
9751                 {
9752                     case CORINFO_HANDLETYPE_CLASS:
9753                         printf(" class");
9754                         break;
9755                     case CORINFO_HANDLETYPE_METHOD:
9756                         printf(" method");
9757                         break;
9758                     case CORINFO_HANDLETYPE_FIELD:
9759                         printf(" field");
9760                         break;
9761                     default:
9762                         printf(" unknown");
9763                         break;
9764                 }
9765             }
9766         }
9767
9768         // for tracking down problems in reguse prediction or liveness tracking
9769
9770         if (verbose && 0)
9771         {
9772             printf(" RR=");
9773             dspRegMask(tree->gtRsvdRegs);
9774             printf("\n");
9775         }
9776     }
9777 }
9778
9779 void Compiler::gtDispRegVal(GenTree* tree)
9780 {
9781     switch (tree->GetRegTag())
9782     {
9783         // Don't display NOREG; the absence of this tag will imply this state
9784         // case GenTree::GT_REGTAG_NONE:       printf(" NOREG");   break;
9785
9786         case GenTree::GT_REGTAG_REG:
9787             printf(" REG %s", compRegVarName(tree->gtRegNum));
9788             break;
9789
9790         default:
9791             break;
9792     }
9793
9794     if (tree->IsMultiRegCall())
9795     {
9796         // 0th reg is gtRegNum, which is already printed above.
9797         // Print the remaining regs of a multi-reg call node.
9798         GenTreeCall* call     = tree->AsCall();
9799         unsigned     regCount = call->GetReturnTypeDesc()->TryGetReturnRegCount();
9800         for (unsigned i = 1; i < regCount; ++i)
9801         {
9802             printf(",%s", compRegVarName(call->GetRegNumByIdx(i)));
9803         }
9804     }
9805     else if (tree->IsCopyOrReloadOfMultiRegCall())
9806     {
9807         GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload();
9808         GenTreeCall*         call         = tree->gtGetOp1()->AsCall();
9809         unsigned             regCount     = call->GetReturnTypeDesc()->TryGetReturnRegCount();
9810         for (unsigned i = 1; i < regCount; ++i)
9811         {
9812             printf(",%s", compRegVarName(copyOrReload->GetRegNumByIdx(i)));
9813         }
9814     }
9815
9816 #if FEATURE_MULTIREG_RET
9817     if (tree->IsCopyOrReload())
9818     {
9819         for (int i = 1; i < MAX_RET_REG_COUNT; i++)
9820         {
9821             regNumber reg = (regNumber)tree->AsCopyOrReload()->GetRegNumByIdx(i);
9822             if (reg == REG_NA)
9823             {
9824                 break;
9825             }
9826             printf(",%s", compRegVarName(reg));
9827         }
9828     }
9829 #endif
9830
9831 #if defined(_TARGET_ARM_)
9832     if (tree->OperIsMultiRegOp() && (tree->AsMultiRegOp()->gtOtherReg != REG_NA))
9833     {
9834         printf(",%s", compRegVarName(tree->AsMultiRegOp()->gtOtherReg));
9835     }
9836 #endif
9837 }
9838
9839 // We usually/commonly don't expect to print anything longer than this string,
9840 #define LONGEST_COMMON_LCL_VAR_DISPLAY "V99 PInvokeFrame"
9841 #define LONGEST_COMMON_LCL_VAR_DISPLAY_LENGTH (sizeof(LONGEST_COMMON_LCL_VAR_DISPLAY))
9842 #define BUF_SIZE (LONGEST_COMMON_LCL_VAR_DISPLAY_LENGTH * 2)
9843
9844 void Compiler::gtGetLclVarNameInfo(unsigned lclNum, const char** ilKindOut, const char** ilNameOut, unsigned* ilNumOut)
9845 {
9846     const char* ilKind = nullptr;
9847     const char* ilName = nullptr;
9848
9849     unsigned ilNum = compMap2ILvarNum(lclNum);
9850
9851     if (ilNum == (unsigned)ICorDebugInfo::RETBUF_ILNUM)
9852     {
9853         ilName = "RetBuf";
9854     }
9855     else if (ilNum == (unsigned)ICorDebugInfo::VARARGS_HND_ILNUM)
9856     {
9857         ilName = "VarArgHandle";
9858     }
9859     else if (ilNum == (unsigned)ICorDebugInfo::TYPECTXT_ILNUM)
9860     {
9861         ilName = "TypeCtx";
9862     }
9863     else if (ilNum == (unsigned)ICorDebugInfo::UNKNOWN_ILNUM)
9864     {
9865 #if FEATURE_ANYCSE
9866         if (lclNumIsTrueCSE(lclNum))
9867         {
9868             ilKind = "cse";
9869             ilNum  = lclNum - optCSEstart;
9870         }
9871         else if (lclNum >= optCSEstart)
9872         {
9873             // Currently any new LclVar's introduced after the CSE phase
9874             // are believed to be created by the "rationalizer" that is what is meant by the "rat" prefix.
9875             ilKind = "rat";
9876             ilNum  = lclNum - (optCSEstart + optCSEcount);
9877         }
9878         else
9879 #endif // FEATURE_ANYCSE
9880         {
9881             if (lclNum == info.compLvFrameListRoot)
9882             {
9883                 ilName = "FramesRoot";
9884             }
9885             else if (lclNum == lvaInlinedPInvokeFrameVar)
9886             {
9887                 ilName = "PInvokeFrame";
9888             }
9889             else if (lclNum == lvaGSSecurityCookie)
9890             {
9891                 ilName = "GsCookie";
9892             }
9893 #if FEATURE_FIXED_OUT_ARGS
9894             else if (lclNum == lvaPInvokeFrameRegSaveVar)
9895             {
9896                 ilName = "PInvokeFrameRegSave";
9897             }
9898             else if (lclNum == lvaOutgoingArgSpaceVar)
9899             {
9900                 ilName = "OutArgs";
9901             }
9902 #endif // FEATURE_FIXED_OUT_ARGS
9903 #ifdef _TARGET_ARM_
9904             else if (lclNum == lvaPromotedStructAssemblyScratchVar)
9905             {
9906                 ilName = "PromotedStructScratch";
9907             }
9908 #endif // _TARGET_ARM_
9909 #if !FEATURE_EH_FUNCLETS
9910             else if (lclNum == lvaShadowSPslotsVar)
9911             {
9912                 ilName = "EHSlots";
9913             }
9914 #endif // !FEATURE_EH_FUNCLETS
9915 #ifdef JIT32_GCENCODER
9916             else if (lclNum == lvaLocAllocSPvar)
9917             {
9918                 ilName = "LocAllocSP";
9919             }
9920 #endif // JIT32_GCENCODER
9921 #if FEATURE_EH_FUNCLETS
9922             else if (lclNum == lvaPSPSym)
9923             {
9924                 ilName = "PSPSym";
9925             }
9926 #endif // FEATURE_EH_FUNCLETS
9927             else
9928             {
9929                 ilKind = "tmp";
9930                 if (compIsForInlining())
9931                 {
9932                     ilNum = lclNum - impInlineInfo->InlinerCompiler->info.compLocalsCount;
9933                 }
9934                 else
9935                 {
9936                     ilNum = lclNum - info.compLocalsCount;
9937                 }
9938             }
9939         }
9940     }
9941     else if (lclNum < (compIsForInlining() ? impInlineInfo->InlinerCompiler->info.compArgsCount : info.compArgsCount))
9942     {
9943         if (ilNum == 0 && !info.compIsStatic)
9944         {
9945             ilName = "this";
9946         }
9947         else
9948         {
9949             ilKind = "arg";
9950         }
9951     }
9952     else
9953     {
9954         if (!lvaTable[lclNum].lvIsStructField)
9955         {
9956             ilKind = "loc";
9957         }
9958         if (compIsForInlining())
9959         {
9960             ilNum -= impInlineInfo->InlinerCompiler->info.compILargsCount;
9961         }
9962         else
9963         {
9964             ilNum -= info.compILargsCount;
9965         }
9966     }
9967
9968     *ilKindOut = ilKind;
9969     *ilNameOut = ilName;
9970     *ilNumOut  = ilNum;
9971 }
9972
9973 /*****************************************************************************/
9974 int Compiler::gtGetLclVarName(unsigned lclNum, char* buf, unsigned buf_remaining)
9975 {
9976     char*    bufp_next    = buf;
9977     unsigned charsPrinted = 0;
9978     int      sprintf_result;
9979
9980     sprintf_result = sprintf_s(bufp_next, buf_remaining, "V%02u", lclNum);
9981
9982     if (sprintf_result < 0)
9983     {
9984         return sprintf_result;
9985     }
9986
9987     charsPrinted += sprintf_result;
9988     bufp_next += sprintf_result;
9989     buf_remaining -= sprintf_result;
9990
9991     const char* ilKind = nullptr;
9992     const char* ilName = nullptr;
9993     unsigned    ilNum  = 0;
9994
9995     gtGetLclVarNameInfo(lclNum, &ilKind, &ilName, &ilNum);
9996
9997     if (ilName != nullptr)
9998     {
9999         sprintf_result = sprintf_s(bufp_next, buf_remaining, " %s", ilName);
10000         if (sprintf_result < 0)
10001         {
10002             return sprintf_result;
10003         }
10004         charsPrinted += sprintf_result;
10005         bufp_next += sprintf_result;
10006         buf_remaining -= sprintf_result;
10007     }
10008     else if (ilKind != nullptr)
10009     {
10010         sprintf_result = sprintf_s(bufp_next, buf_remaining, " %s%d", ilKind, ilNum);
10011         if (sprintf_result < 0)
10012         {
10013             return sprintf_result;
10014         }
10015         charsPrinted += sprintf_result;
10016         bufp_next += sprintf_result;
10017         buf_remaining -= sprintf_result;
10018     }
10019
10020     assert(charsPrinted > 0);
10021     assert(buf_remaining > 0);
10022
10023     return (int)charsPrinted;
10024 }
10025
10026 /*****************************************************************************
10027  * Get the local var name, and create a copy of the string that can be used in debug output.
10028  */
10029 char* Compiler::gtGetLclVarName(unsigned lclNum)
10030 {
10031     char buf[BUF_SIZE];
10032     int  charsPrinted = gtGetLclVarName(lclNum, buf, _countof(buf));
10033     if (charsPrinted < 0)
10034     {
10035         return nullptr;
10036     }
10037
10038     char* retBuf = new (this, CMK_DebugOnly) char[charsPrinted + 1];
10039     strcpy_s(retBuf, charsPrinted + 1, buf);
10040     return retBuf;
10041 }
10042
10043 /*****************************************************************************/
10044 void Compiler::gtDispLclVar(unsigned lclNum, bool padForBiggestDisp)
10045 {
10046     char buf[BUF_SIZE];
10047     int  charsPrinted = gtGetLclVarName(lclNum, buf, _countof(buf));
10048
10049     if (charsPrinted < 0)
10050     {
10051         return;
10052     }
10053
10054     printf("%s", buf);
10055
10056     if (padForBiggestDisp && (charsPrinted < LONGEST_COMMON_LCL_VAR_DISPLAY_LENGTH))
10057     {
10058         printf("%*c", LONGEST_COMMON_LCL_VAR_DISPLAY_LENGTH - charsPrinted, ' ');
10059     }
10060 }
10061
10062 /*****************************************************************************/
10063 void Compiler::gtDispConst(GenTree* tree)
10064 {
10065     assert(tree->OperKind() & GTK_CONST);
10066
10067     switch (tree->gtOper)
10068     {
10069         case GT_CNS_INT:
10070             if (tree->IsIconHandle(GTF_ICON_STR_HDL))
10071             {
10072                 const wchar_t* str = eeGetCPString(tree->gtIntCon.gtIconVal);
10073                 if (str != nullptr)
10074                 {
10075                     printf(" 0x%X \"%S\"", dspPtr(tree->gtIntCon.gtIconVal), str);
10076                 }
10077                 else
10078                 {
10079                     // Note that eGetCPString isn't currently implemented on Linux/ARM
10080                     // and instead always returns nullptr
10081                     printf(" 0x%X [ICON_STR_HDL]", dspPtr(tree->gtIntCon.gtIconVal));
10082                 }
10083             }
10084             else
10085             {
10086                 ssize_t dspIconVal = tree->IsIconHandle() ? dspPtr(tree->gtIntCon.gtIconVal) : tree->gtIntCon.gtIconVal;
10087
10088                 if (tree->TypeGet() == TYP_REF)
10089                 {
10090                     assert(tree->gtIntCon.gtIconVal == 0);
10091                     printf(" null");
10092                 }
10093                 else if ((tree->gtIntCon.gtIconVal > -1000) && (tree->gtIntCon.gtIconVal < 1000))
10094                 {
10095                     printf(" %ld", dspIconVal);
10096 #ifdef _TARGET_64BIT_
10097                 }
10098                 else if ((tree->gtIntCon.gtIconVal & 0xFFFFFFFF00000000LL) != 0)
10099                 {
10100                     printf(" 0x%llx", dspIconVal);
10101 #endif
10102                 }
10103                 else
10104                 {
10105                     printf(" 0x%X", dspIconVal);
10106                 }
10107
10108                 if (tree->IsIconHandle())
10109                 {
10110                     switch (tree->GetIconHandleFlag())
10111                     {
10112                         case GTF_ICON_SCOPE_HDL:
10113                             printf(" scope");
10114                             break;
10115                         case GTF_ICON_CLASS_HDL:
10116                             printf(" class");
10117                             break;
10118                         case GTF_ICON_METHOD_HDL:
10119                             printf(" method");
10120                             break;
10121                         case GTF_ICON_FIELD_HDL:
10122                             printf(" field");
10123                             break;
10124                         case GTF_ICON_STATIC_HDL:
10125                             printf(" static");
10126                             break;
10127                         case GTF_ICON_STR_HDL:
10128                             unreached(); // This case is handled above
10129                             break;
10130                         case GTF_ICON_PSTR_HDL:
10131                             printf(" pstr");
10132                             break;
10133                         case GTF_ICON_PTR_HDL:
10134                             printf(" ptr");
10135                             break;
10136                         case GTF_ICON_VARG_HDL:
10137                             printf(" vararg");
10138                             break;
10139                         case GTF_ICON_PINVKI_HDL:
10140                             printf(" pinvoke");
10141                             break;
10142                         case GTF_ICON_TOKEN_HDL:
10143                             printf(" token");
10144                             break;
10145                         case GTF_ICON_TLS_HDL:
10146                             printf(" tls");
10147                             break;
10148                         case GTF_ICON_FTN_ADDR:
10149                             printf(" ftn");
10150                             break;
10151                         case GTF_ICON_CIDMID_HDL:
10152                             printf(" cid/mid");
10153                             break;
10154                         case GTF_ICON_BBC_PTR:
10155                             printf(" bbc");
10156                             break;
10157                         default:
10158                             printf(" UNKNOWN");
10159                             break;
10160                     }
10161                 }
10162
10163                 if ((tree->gtFlags & GTF_ICON_FIELD_OFF) != 0)
10164                 {
10165                     printf(" field offset");
10166                 }
10167
10168 #ifdef FEATURE_SIMD
10169                 if ((tree->gtFlags & GTF_ICON_SIMD_COUNT) != 0)
10170                 {
10171                     printf(" Vector<T>.Count");
10172                 }
10173 #endif
10174
10175                 if ((tree->IsReuseRegVal()) != 0)
10176                 {
10177                     printf(" reuse reg val");
10178                 }
10179             }
10180
10181             gtDispFieldSeq(tree->gtIntCon.gtFieldSeq);
10182
10183             break;
10184
10185         case GT_CNS_LNG:
10186             printf(" 0x%016I64x", tree->gtLngCon.gtLconVal);
10187             break;
10188
10189         case GT_CNS_DBL:
10190             if (*((__int64*)&tree->gtDblCon.gtDconVal) == (__int64)I64(0x8000000000000000))
10191             {
10192                 printf(" -0.00000");
10193             }
10194             else
10195             {
10196                 printf(" %#.17g", tree->gtDblCon.gtDconVal);
10197             }
10198             break;
10199         case GT_CNS_STR:
10200             printf("<string constant>");
10201             break;
10202         default:
10203             assert(!"unexpected constant node");
10204     }
10205
10206     gtDispRegVal(tree);
10207 }
10208
10209 void Compiler::gtDispFieldSeq(FieldSeqNode* pfsn)
10210 {
10211     if (pfsn == FieldSeqStore::NotAField() || (pfsn == nullptr))
10212     {
10213         return;
10214     }
10215
10216     // Otherwise...
10217     printf(" Fseq[");
10218     while (pfsn != nullptr)
10219     {
10220         assert(pfsn != FieldSeqStore::NotAField()); // Can't exist in a field sequence list except alone
10221         CORINFO_FIELD_HANDLE fldHnd = pfsn->m_fieldHnd;
10222         // First check the "pseudo" field handles...
10223         if (fldHnd == FieldSeqStore::FirstElemPseudoField)
10224         {
10225             printf("#FirstElem");
10226         }
10227         else if (fldHnd == FieldSeqStore::ConstantIndexPseudoField)
10228         {
10229             printf("#ConstantIndex");
10230         }
10231         else
10232         {
10233             printf("%s", eeGetFieldName(fldHnd));
10234         }
10235         pfsn = pfsn->m_next;
10236         if (pfsn != nullptr)
10237         {
10238             printf(", ");
10239         }
10240     }
10241     printf("]");
10242 }
10243
10244 //------------------------------------------------------------------------
10245 // gtDispLeaf: Print a single leaf node to jitstdout.
10246 //
10247 // Arguments:
10248 //    tree - the tree to be printed
10249 //    indentStack - the specification for the current level of indentation & arcs
10250 //
10251 // Return Value:
10252 //    None.
10253 //
10254 // Notes:
10255 //    'indentStack' may be null, in which case no indentation or arcs are printed
10256
10257 void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack)
10258 {
10259     if (tree->OperKind() & GTK_CONST)
10260     {
10261         gtDispConst(tree);
10262         return;
10263     }
10264
10265     bool isLclFld = false;
10266
10267     switch (tree->gtOper)
10268     {
10269         unsigned   varNum;
10270         LclVarDsc* varDsc;
10271
10272         case GT_LCL_FLD:
10273         case GT_LCL_FLD_ADDR:
10274         case GT_STORE_LCL_FLD:
10275             isLclFld = true;
10276             __fallthrough;
10277
10278         case GT_PHI_ARG:
10279         case GT_LCL_VAR:
10280         case GT_LCL_VAR_ADDR:
10281         case GT_STORE_LCL_VAR:
10282             printf(" ");
10283             varNum = tree->gtLclVarCommon.gtLclNum;
10284             varDsc = &lvaTable[varNum];
10285             gtDispLclVar(varNum);
10286             if (tree->gtLclVarCommon.HasSsaName())
10287             {
10288                 if (tree->gtFlags & GTF_VAR_USEASG)
10289                 {
10290                     assert(tree->gtFlags & GTF_VAR_DEF);
10291                     printf("ud:%d->%d", tree->gtLclVarCommon.gtSsaNum, GetSsaNumForLocalVarDef(tree));
10292                 }
10293                 else
10294                 {
10295                     printf("%s:%d", (tree->gtFlags & GTF_VAR_DEF) ? "d" : "u", tree->gtLclVarCommon.gtSsaNum);
10296                 }
10297             }
10298
10299             if (isLclFld)
10300             {
10301                 printf("[+%u]", tree->gtLclFld.gtLclOffs);
10302                 gtDispFieldSeq(tree->gtLclFld.gtFieldSeq);
10303             }
10304
10305             if (varDsc->lvRegister)
10306             {
10307                 printf(" ");
10308                 varDsc->PrintVarReg();
10309             }
10310             else if (tree->InReg())
10311             {
10312                 printf(" %s", compRegVarName(tree->gtRegNum));
10313             }
10314
10315             if (varDsc->lvPromoted)
10316             {
10317                 if (!varTypeIsPromotable(varDsc) && !varDsc->lvUnusedStruct)
10318                 {
10319                     // Promoted implicit byrefs can get in this state while they are being rewritten
10320                     // in global morph.
10321                     assert(fgGlobalMorph);
10322                 }
10323                 else
10324                 {
10325                     CORINFO_CLASS_HANDLE typeHnd = varDsc->lvVerTypeInfo.GetClassHandle();
10326                     CORINFO_FIELD_HANDLE fldHnd;
10327
10328                     for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i)
10329                     {
10330                         LclVarDsc*  fieldVarDsc = &lvaTable[i];
10331                         const char* fieldName;
10332 #if !defined(_TARGET_64BIT_)
10333                         if (varTypeIsLong(varDsc))
10334                         {
10335                             fieldName = (i == 0) ? "lo" : "hi";
10336                         }
10337                         else
10338 #endif // !defined(_TARGET_64BIT_)
10339                         {
10340                             fldHnd    = info.compCompHnd->getFieldInClass(typeHnd, fieldVarDsc->lvFldOrdinal);
10341                             fieldName = eeGetFieldName(fldHnd);
10342                         }
10343
10344                         printf("\n");
10345                         printf("                                                  ");
10346                         printIndent(indentStack);
10347                         printf("    %-6s V%02u.%s (offs=0x%02x) -> ", varTypeName(fieldVarDsc->TypeGet()),
10348                                tree->gtLclVarCommon.gtLclNum, fieldName, fieldVarDsc->lvFldOffset);
10349                         gtDispLclVar(i);
10350
10351                         if (fieldVarDsc->lvRegister)
10352                         {
10353                             printf(" ");
10354                             fieldVarDsc->PrintVarReg();
10355                         }
10356
10357                         if (fieldVarDsc->lvTracked && fgLocalVarLivenessDone && // Includes local variable liveness
10358                             ((tree->gtFlags & GTF_VAR_DEATH) != 0))
10359                         {
10360                             printf(" (last use)");
10361                         }
10362                     }
10363                 }
10364             }
10365             else // a normal not-promoted lclvar
10366             {
10367                 if (varDsc->lvTracked && fgLocalVarLivenessDone && ((tree->gtFlags & GTF_VAR_DEATH) != 0))
10368                 {
10369                     printf(" (last use)");
10370                 }
10371             }
10372             break;
10373
10374         case GT_JMP:
10375         {
10376             const char* methodName;
10377             const char* className;
10378
10379             methodName = eeGetMethodName((CORINFO_METHOD_HANDLE)tree->gtVal.gtVal1, &className);
10380             printf(" %s.%s\n", className, methodName);
10381         }
10382         break;
10383
10384         case GT_CLS_VAR:
10385             printf(" Hnd=%#x", dspPtr(tree->gtClsVar.gtClsVarHnd));
10386             gtDispFieldSeq(tree->gtClsVar.gtFieldSeq);
10387             break;
10388
10389         case GT_CLS_VAR_ADDR:
10390             printf(" Hnd=%#x", dspPtr(tree->gtClsVar.gtClsVarHnd));
10391             break;
10392
10393         case GT_LABEL:
10394             if (tree->gtLabel.gtLabBB)
10395             {
10396                 printf(" dst=" FMT_BB, tree->gtLabel.gtLabBB->bbNum);
10397             }
10398             else
10399             {
10400                 printf(" dst=<null>");
10401             }
10402
10403             break;
10404
10405         case GT_FTN_ADDR:
10406         {
10407             const char* methodName;
10408             const char* className;
10409
10410             methodName = eeGetMethodName((CORINFO_METHOD_HANDLE)tree->gtFptrVal.gtFptrMethod, &className);
10411             printf(" %s.%s\n", className, methodName);
10412         }
10413         break;
10414
10415 #if !FEATURE_EH_FUNCLETS
10416         case GT_END_LFIN:
10417             printf(" endNstLvl=%d", tree->gtVal.gtVal1);
10418             break;
10419 #endif // !FEATURE_EH_FUNCLETS
10420
10421         // Vanilla leaves. No qualifying information available. So do nothing
10422
10423         case GT_NO_OP:
10424         case GT_START_NONGC:
10425         case GT_PROF_HOOK:
10426         case GT_CATCH_ARG:
10427         case GT_MEMORYBARRIER:
10428         case GT_ARGPLACE:
10429         case GT_PINVOKE_PROLOG:
10430         case GT_JMPTABLE:
10431             break;
10432
10433         case GT_RET_EXPR:
10434             printf("(inl return from call ");
10435             printTreeID(tree->gtRetExpr.gtInlineCandidate);
10436             printf(")");
10437             break;
10438
10439         case GT_PHYSREG:
10440             printf(" %s", getRegName(tree->gtPhysReg.gtSrcReg, varTypeIsFloating(tree)));
10441             break;
10442
10443         case GT_IL_OFFSET:
10444             printf(" IL offset: ");
10445             if (tree->gtStmt.gtStmtILoffsx == BAD_IL_OFFSET)
10446             {
10447                 printf("???");
10448             }
10449             else
10450             {
10451                 printf("0x%x", jitGetILoffs(tree->gtStmt.gtStmtILoffsx));
10452             }
10453             break;
10454
10455         case GT_JCC:
10456         case GT_SETCC:
10457             printf(" cond=%s", GenTree::OpName(tree->AsCC()->gtCondition));
10458             break;
10459         case GT_JCMP:
10460             printf(" cond=%s%s", (tree->gtFlags & GTF_JCMP_TST) ? "TEST_" : "",
10461                    (tree->gtFlags & GTF_JCMP_EQ) ? "EQ" : "NE");
10462
10463         default:
10464             assert(!"don't know how to display tree leaf node");
10465     }
10466
10467     gtDispRegVal(tree);
10468 }
10469
10470 //------------------------------------------------------------------------
10471 // gtDispLeaf: Print a child node to jitstdout.
10472 //
10473 // Arguments:
10474 //    tree - the tree to be printed
10475 //    indentStack - the specification for the current level of indentation & arcs
10476 //    arcType     - the type of arc to use for this child
10477 //    msg         - a contextual method (i.e. from the parent) to print
10478 //    topOnly     - a boolean indicating whether to print the children, or just the top node
10479 //
10480 // Return Value:
10481 //    None.
10482 //
10483 // Notes:
10484 //    'indentStack' may be null, in which case no indentation or arcs are printed
10485 //    'msg' has a default value of null
10486 //    'topOnly' is an optional argument that defaults to false
10487
10488 void Compiler::gtDispChild(GenTree*             child,
10489                            IndentStack*         indentStack,
10490                            IndentInfo           arcType,
10491                            __in_opt const char* msg,     /* = nullptr  */
10492                            bool                 topOnly) /* = false */
10493 {
10494     indentStack->Push(arcType);
10495     gtDispTree(child, indentStack, msg, topOnly);
10496     indentStack->Pop();
10497 }
10498
10499 #ifdef FEATURE_SIMD
10500 // Intrinsic Id to name map
10501 extern const char* const simdIntrinsicNames[] = {
10502 #define SIMD_INTRINSIC(mname, inst, id, name, r, ac, arg1, arg2, arg3, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) name,
10503 #include "simdintrinsiclist.h"
10504 };
10505 #endif // FEATURE_SIMD
10506
10507 /*****************************************************************************/
10508
10509 void Compiler::gtDispTree(GenTree*     tree,
10510                           IndentStack* indentStack,                 /* = nullptr */
10511                           __in __in_z __in_opt const char* msg,     /* = nullptr  */
10512                           bool                             topOnly, /* = false */
10513                           bool                             isLIR)   /* = false */
10514 {
10515     if (tree == nullptr)
10516     {
10517         printf(" [%08X] <NULL>\n", tree);
10518         printf(""); // null string means flush
10519         return;
10520     }
10521
10522     if (indentStack == nullptr)
10523     {
10524         indentStack = new (this, CMK_DebugOnly) IndentStack(this);
10525     }
10526
10527     if (IsUninitialized(tree))
10528     {
10529         /* Value used to initalize nodes */
10530         printf("Uninitialized tree node!");
10531         return;
10532     }
10533
10534     if (tree->gtOper >= GT_COUNT)
10535     {
10536         gtDispNode(tree, indentStack, msg, isLIR);
10537         printf("Bogus operator!");
10538         return;
10539     }
10540
10541     /* Is tree a leaf node? */
10542
10543     if (tree->OperIsLeaf() || tree->OperIsLocalStore()) // local stores used to be leaves
10544     {
10545         gtDispNode(tree, indentStack, msg, isLIR);
10546         gtDispLeaf(tree, indentStack);
10547         gtDispVN(tree);
10548         printf("\n");
10549         if (tree->OperIsLocalStore() && !topOnly)
10550         {
10551             gtDispChild(tree->gtOp.gtOp1, indentStack, IINone);
10552         }
10553         return;
10554     }
10555
10556     // Determine what kind of arc to propagate.
10557     IndentInfo myArc    = IINone;
10558     IndentInfo lowerArc = IINone;
10559     if (indentStack->Depth() > 0)
10560     {
10561         myArc = indentStack->Pop();
10562         switch (myArc)
10563         {
10564             case IIArcBottom:
10565                 indentStack->Push(IIArc);
10566                 lowerArc = IINone;
10567                 break;
10568             case IIArc:
10569                 indentStack->Push(IIArc);
10570                 lowerArc = IIArc;
10571                 break;
10572             case IIArcTop:
10573                 indentStack->Push(IINone);
10574                 lowerArc = IIArc;
10575                 break;
10576             case IIEmbedded:
10577                 indentStack->Push(IIEmbedded);
10578                 lowerArc = IIEmbedded;
10579                 break;
10580             case IINone:
10581                 indentStack->Push(IINone);
10582                 lowerArc = IINone;
10583                 break;
10584             default:
10585                 unreached();
10586                 break;
10587         }
10588     }
10589
10590     // Special case formatting for PHI nodes -- arg lists like calls.
10591
10592     if (tree->OperGet() == GT_PHI)
10593     {
10594         gtDispNode(tree, indentStack, msg, isLIR);
10595         gtDispVN(tree);
10596         printf("\n");
10597
10598         if (!topOnly)
10599         {
10600             if (tree->gtOp.gtOp1 != nullptr)
10601             {
10602                 IndentInfo arcType = IIArcTop;
10603                 for (GenTreeArgList* args = tree->gtOp.gtOp1->AsArgList(); args != nullptr; args = args->Rest())
10604                 {
10605                     if (args->Rest() == nullptr)
10606                     {
10607                         arcType = IIArcBottom;
10608                     }
10609                     gtDispChild(args->Current(), indentStack, arcType);
10610                     arcType = IIArc;
10611                 }
10612             }
10613         }
10614         return;
10615     }
10616
10617     /* Is it a 'simple' unary/binary operator? */
10618
10619     const char* childMsg = nullptr;
10620
10621     if (tree->OperIsSimple())
10622     {
10623         if (!topOnly)
10624         {
10625             if (tree->gtGetOp2IfPresent())
10626             {
10627                 // Label the childMsgs of the GT_COLON operator
10628                 // op2 is the then part
10629
10630                 if (tree->gtOper == GT_COLON)
10631                 {
10632                     childMsg = "then";
10633                 }
10634                 gtDispChild(tree->gtOp.gtOp2, indentStack, IIArcTop, childMsg, topOnly);
10635             }
10636         }
10637
10638         // Now, get the right type of arc for this node
10639         if (myArc != IINone)
10640         {
10641             indentStack->Pop();
10642             indentStack->Push(myArc);
10643         }
10644
10645         gtDispNode(tree, indentStack, msg, isLIR);
10646
10647         // Propagate lowerArc to the lower children.
10648         if (indentStack->Depth() > 0)
10649         {
10650             (void)indentStack->Pop();
10651             indentStack->Push(lowerArc);
10652         }
10653
10654         if (tree->gtOper == GT_CAST)
10655         {
10656             /* Format a message that explains the effect of this GT_CAST */
10657
10658             var_types fromType  = genActualType(tree->gtCast.CastOp()->TypeGet());
10659             var_types toType    = tree->CastToType();
10660             var_types finalType = tree->TypeGet();
10661
10662             /* if GTF_UNSIGNED is set then force fromType to an unsigned type */
10663             if (tree->gtFlags & GTF_UNSIGNED)
10664             {
10665                 fromType = genUnsignedType(fromType);
10666             }
10667
10668             if (finalType != toType)
10669             {
10670                 printf(" %s <-", varTypeName(finalType));
10671             }
10672
10673             printf(" %s <- %s", varTypeName(toType), varTypeName(fromType));
10674         }
10675
10676         if (tree->gtOper == GT_OBJ && (tree->gtFlags & GTF_VAR_DEATH))
10677         {
10678             printf(" (last use)");
10679         }
10680         if (tree->OperIsBlkOp())
10681         {
10682             if (tree->OperIsCopyBlkOp())
10683             {
10684                 printf(" (copy)");
10685             }
10686             else if (tree->OperIsInitBlkOp())
10687             {
10688                 printf(" (init)");
10689             }
10690             if (tree->OperIsStoreBlk() && (tree->AsBlk()->gtBlkOpKind != GenTreeBlk::BlkOpKindInvalid))
10691             {
10692                 switch (tree->AsBlk()->gtBlkOpKind)
10693                 {
10694                     case GenTreeBlk::BlkOpKindRepInstr:
10695                         printf(" (RepInstr)");
10696                         break;
10697                     case GenTreeBlk::BlkOpKindUnroll:
10698                         printf(" (Unroll)");
10699                         break;
10700                     case GenTreeBlk::BlkOpKindHelper:
10701                         printf(" (Helper)");
10702                         break;
10703                     default:
10704                         unreached();
10705                 }
10706             }
10707         }
10708         else if (tree->OperIsFieldList())
10709         {
10710             printf(" %s at offset %d", varTypeName(tree->AsFieldList()->gtFieldType),
10711                    tree->AsFieldList()->gtFieldOffset);
10712         }
10713 #if FEATURE_PUT_STRUCT_ARG_STK
10714         else if (tree->OperGet() == GT_PUTARG_STK)
10715         {
10716             printf(" (%d slots)", tree->AsPutArgStk()->gtNumSlots);
10717             if (tree->AsPutArgStk()->gtPutArgStkKind != GenTreePutArgStk::Kind::Invalid)
10718             {
10719                 switch (tree->AsPutArgStk()->gtPutArgStkKind)
10720                 {
10721                     case GenTreePutArgStk::Kind::RepInstr:
10722                         printf(" (RepInstr)");
10723                         break;
10724                     case GenTreePutArgStk::Kind::Unroll:
10725                         printf(" (Unroll)");
10726                         break;
10727                     case GenTreePutArgStk::Kind::Push:
10728                         printf(" (Push)");
10729                         break;
10730                     case GenTreePutArgStk::Kind::PushAllSlots:
10731                         printf(" (PushAllSlots)");
10732                         break;
10733                     default:
10734                         unreached();
10735                 }
10736             }
10737         }
10738 #endif // FEATURE_PUT_STRUCT_ARG_STK
10739
10740         if (tree->gtOper == GT_INTRINSIC)
10741         {
10742             switch (tree->gtIntrinsic.gtIntrinsicId)
10743             {
10744                 case CORINFO_INTRINSIC_Sin:
10745                     printf(" sin");
10746                     break;
10747                 case CORINFO_INTRINSIC_Cos:
10748                     printf(" cos");
10749                     break;
10750                 case CORINFO_INTRINSIC_Cbrt:
10751                     printf(" cbrt");
10752                     break;
10753                 case CORINFO_INTRINSIC_Sqrt:
10754                     printf(" sqrt");
10755                     break;
10756                 case CORINFO_INTRINSIC_Abs:
10757                     printf(" abs");
10758                     break;
10759                 case CORINFO_INTRINSIC_Round:
10760                     printf(" round");
10761                     break;
10762                 case CORINFO_INTRINSIC_Cosh:
10763                     printf(" cosh");
10764                     break;
10765                 case CORINFO_INTRINSIC_Sinh:
10766                     printf(" sinh");
10767                     break;
10768                 case CORINFO_INTRINSIC_Tan:
10769                     printf(" tan");
10770                     break;
10771                 case CORINFO_INTRINSIC_Tanh:
10772                     printf(" tanh");
10773                     break;
10774                 case CORINFO_INTRINSIC_Asin:
10775                     printf(" asin");
10776                     break;
10777                 case CORINFO_INTRINSIC_Asinh:
10778                     printf(" asinh");
10779                     break;
10780                 case CORINFO_INTRINSIC_Acos:
10781                     printf(" acos");
10782                     break;
10783                 case CORINFO_INTRINSIC_Acosh:
10784                     printf(" acosh");
10785                     break;
10786                 case CORINFO_INTRINSIC_Atan:
10787                     printf(" atan");
10788                     break;
10789                 case CORINFO_INTRINSIC_Atan2:
10790                     printf(" atan2");
10791                     break;
10792                 case CORINFO_INTRINSIC_Atanh:
10793                     printf(" atanh");
10794                     break;
10795                 case CORINFO_INTRINSIC_Log10:
10796                     printf(" log10");
10797                     break;
10798                 case CORINFO_INTRINSIC_Pow:
10799                     printf(" pow");
10800                     break;
10801                 case CORINFO_INTRINSIC_Exp:
10802                     printf(" exp");
10803                     break;
10804                 case CORINFO_INTRINSIC_Ceiling:
10805                     printf(" ceiling");
10806                     break;
10807                 case CORINFO_INTRINSIC_Floor:
10808                     printf(" floor");
10809                     break;
10810                 case CORINFO_INTRINSIC_Object_GetType:
10811                     printf(" objGetType");
10812                     break;
10813
10814                 default:
10815                     unreached();
10816             }
10817         }
10818
10819 #ifdef FEATURE_SIMD
10820         if (tree->gtOper == GT_SIMD)
10821         {
10822             printf(" %s %s", varTypeName(tree->gtSIMD.gtSIMDBaseType),
10823                    simdIntrinsicNames[tree->gtSIMD.gtSIMDIntrinsicID]);
10824         }
10825 #endif // FEATURE_SIMD
10826
10827 #ifdef FEATURE_HW_INTRINSICS
10828         if (tree->gtOper == GT_HWIntrinsic)
10829         {
10830             printf(" %s %s",
10831                    tree->gtHWIntrinsic.gtSIMDBaseType == TYP_UNKNOWN ? ""
10832                                                                      : varTypeName(tree->gtHWIntrinsic.gtSIMDBaseType),
10833                    HWIntrinsicInfo::lookupName(tree->gtHWIntrinsic.gtHWIntrinsicId));
10834         }
10835 #endif // FEATURE_HW_INTRINSICS
10836
10837         gtDispRegVal(tree);
10838         gtDispVN(tree);
10839         printf("\n");
10840
10841         if (!topOnly && tree->gtOp.gtOp1)
10842         {
10843
10844             // Label the child of the GT_COLON operator
10845             // op1 is the else part
10846
10847             if (tree->gtOper == GT_COLON)
10848             {
10849                 childMsg = "else";
10850             }
10851             else if (tree->gtOper == GT_QMARK)
10852             {
10853                 childMsg = "   if";
10854             }
10855             gtDispChild(tree->gtOp.gtOp1, indentStack, IIArcBottom, childMsg, topOnly);
10856         }
10857
10858         return;
10859     }
10860
10861     // Now, get the right type of arc for this node
10862     if (myArc != IINone)
10863     {
10864         indentStack->Pop();
10865         indentStack->Push(myArc);
10866     }
10867     gtDispNode(tree, indentStack, msg, isLIR);
10868
10869     // Propagate lowerArc to the lower children.
10870     if (indentStack->Depth() > 0)
10871     {
10872         (void)indentStack->Pop();
10873         indentStack->Push(lowerArc);
10874     }
10875
10876     // See what kind of a special operator we have here, and handle its special children.
10877
10878     switch (tree->gtOper)
10879     {
10880         case GT_FIELD:
10881             if (FieldSeqStore::IsPseudoField(tree->gtField.gtFldHnd))
10882             {
10883                 printf(" #PseudoField:0x%x", tree->gtField.gtFldOffset);
10884             }
10885             else
10886             {
10887                 printf(" %s", eeGetFieldName(tree->gtField.gtFldHnd), 0);
10888             }
10889
10890             if (tree->gtField.gtFldObj && !topOnly)
10891             {
10892                 gtDispVN(tree);
10893                 printf("\n");
10894                 gtDispChild(tree->gtField.gtFldObj, indentStack, IIArcBottom);
10895             }
10896             else
10897             {
10898                 gtDispRegVal(tree);
10899                 gtDispVN(tree);
10900                 printf("\n");
10901             }
10902             break;
10903
10904         case GT_CALL:
10905         {
10906             GenTreeCall* call = tree->AsCall();
10907             assert(call->gtFlags & GTF_CALL);
10908             unsigned numChildren = call->NumChildren();
10909             GenTree* lastChild   = nullptr;
10910             if (numChildren != 0)
10911             {
10912                 lastChild = call->GetChild(numChildren - 1);
10913             }
10914
10915             if (call->gtCallType != CT_INDIRECT)
10916             {
10917                 const char* methodName;
10918                 const char* className;
10919
10920                 methodName = eeGetMethodName(call->gtCallMethHnd, &className);
10921
10922                 printf(" %s.%s", className, methodName);
10923             }
10924
10925             if ((call->gtFlags & GTF_CALL_UNMANAGED) && (call->gtCallMoreFlags & GTF_CALL_M_FRAME_VAR_DEATH))
10926             {
10927                 printf(" (FramesRoot last use)");
10928             }
10929
10930             if (((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) && (call->gtInlineCandidateInfo != nullptr) &&
10931                 (call->gtInlineCandidateInfo->exactContextHnd != nullptr))
10932             {
10933                 printf(" (exactContextHnd=0x%p)", dspPtr(call->gtInlineCandidateInfo->exactContextHnd));
10934             }
10935
10936             gtDispVN(call);
10937             if (call->IsMultiRegCall())
10938             {
10939                 gtDispRegVal(call);
10940             }
10941             printf("\n");
10942
10943             if (!topOnly)
10944             {
10945                 char  buf[64];
10946                 char* bufp;
10947
10948                 bufp = &buf[0];
10949
10950                 if ((call->gtCallObjp != nullptr) && (call->gtCallObjp->gtOper != GT_NOP) &&
10951                     (!call->gtCallObjp->IsArgPlaceHolderNode()))
10952                 {
10953                     if (call->gtCallObjp->gtOper == GT_ASG)
10954                     {
10955                         sprintf_s(bufp, sizeof(buf), "this SETUP%c", 0);
10956                     }
10957                     else
10958                     {
10959                         sprintf_s(bufp, sizeof(buf), "this in %s%c", compRegVarName(REG_ARG_0), 0);
10960                     }
10961                     gtDispChild(call->gtCallObjp, indentStack, (call->gtCallObjp == lastChild) ? IIArcBottom : IIArc,
10962                                 bufp, topOnly);
10963                 }
10964
10965                 if (call->gtCallArgs)
10966                 {
10967                     gtDispArgList(call, indentStack);
10968                 }
10969
10970                 if (call->gtCallType == CT_INDIRECT)
10971                 {
10972                     gtDispChild(call->gtCallAddr, indentStack, (call->gtCallAddr == lastChild) ? IIArcBottom : IIArc,
10973                                 "calli tgt", topOnly);
10974                 }
10975
10976                 if (call->gtControlExpr != nullptr)
10977                 {
10978                     gtDispChild(call->gtControlExpr, indentStack,
10979                                 (call->gtControlExpr == lastChild) ? IIArcBottom : IIArc, "control expr", topOnly);
10980                 }
10981
10982 #if !FEATURE_FIXED_OUT_ARGS
10983                 regList list = call->regArgList;
10984 #endif
10985                 /* process the late argument list */
10986                 int lateArgIndex = 0;
10987                 for (GenTreeArgList* lateArgs = call->gtCallLateArgs; lateArgs;
10988                      (lateArgIndex++, lateArgs = lateArgs->Rest()))
10989                 {
10990                     GenTree* argx;
10991
10992                     argx = lateArgs->Current();
10993
10994                     IndentInfo arcType = (lateArgs->Rest() == nullptr) ? IIArcBottom : IIArc;
10995                     gtGetLateArgMsg(call, argx, lateArgIndex, -1, bufp, sizeof(buf));
10996                     gtDispChild(argx, indentStack, arcType, bufp, topOnly);
10997                 }
10998             }
10999         }
11000         break;
11001
11002         case GT_STMT:
11003             printf("\n");
11004
11005             if (!topOnly)
11006             {
11007                 gtDispChild(tree->gtStmt.gtStmtExpr, indentStack, IIArcBottom);
11008             }
11009             break;
11010
11011         case GT_ARR_ELEM:
11012             gtDispVN(tree);
11013             printf("\n");
11014
11015             if (!topOnly)
11016             {
11017                 gtDispChild(tree->gtArrElem.gtArrObj, indentStack, IIArc, nullptr, topOnly);
11018
11019                 unsigned dim;
11020                 for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
11021                 {
11022                     IndentInfo arcType = ((dim + 1) == tree->gtArrElem.gtArrRank) ? IIArcBottom : IIArc;
11023                     gtDispChild(tree->gtArrElem.gtArrInds[dim], indentStack, arcType, nullptr, topOnly);
11024                 }
11025             }
11026             break;
11027
11028         case GT_ARR_OFFSET:
11029             gtDispVN(tree);
11030             printf("\n");
11031             if (!topOnly)
11032             {
11033                 gtDispChild(tree->gtArrOffs.gtOffset, indentStack, IIArc, nullptr, topOnly);
11034                 gtDispChild(tree->gtArrOffs.gtIndex, indentStack, IIArc, nullptr, topOnly);
11035                 gtDispChild(tree->gtArrOffs.gtArrObj, indentStack, IIArcBottom, nullptr, topOnly);
11036             }
11037             break;
11038
11039         case GT_CMPXCHG:
11040             gtDispVN(tree);
11041             printf("\n");
11042             if (!topOnly)
11043             {
11044                 gtDispChild(tree->gtCmpXchg.gtOpLocation, indentStack, IIArc, nullptr, topOnly);
11045                 gtDispChild(tree->gtCmpXchg.gtOpValue, indentStack, IIArc, nullptr, topOnly);
11046                 gtDispChild(tree->gtCmpXchg.gtOpComparand, indentStack, IIArcBottom, nullptr, topOnly);
11047             }
11048             break;
11049
11050         case GT_ARR_BOUNDS_CHECK:
11051 #ifdef FEATURE_SIMD
11052         case GT_SIMD_CHK:
11053 #endif // FEATURE_SIMD
11054 #ifdef FEATURE_HW_INTRINSICS
11055         case GT_HW_INTRINSIC_CHK:
11056 #endif // FEATURE_HW_INTRINSICS
11057             gtDispVN(tree);
11058             printf("\n");
11059             if (!topOnly)
11060             {
11061                 gtDispChild(tree->gtBoundsChk.gtIndex, indentStack, IIArc, nullptr, topOnly);
11062                 gtDispChild(tree->gtBoundsChk.gtArrLen, indentStack, IIArcBottom, nullptr, topOnly);
11063             }
11064             break;
11065
11066         case GT_STORE_DYN_BLK:
11067         case GT_DYN_BLK:
11068             if (tree->OperIsCopyBlkOp())
11069             {
11070                 printf(" (copy)");
11071             }
11072             else if (tree->OperIsInitBlkOp())
11073             {
11074                 printf(" (init)");
11075             }
11076             gtDispVN(tree);
11077             printf("\n");
11078             if (!topOnly)
11079             {
11080                 if (tree->gtDynBlk.Data() != nullptr)
11081                 {
11082                     gtDispChild(tree->gtDynBlk.Data(), indentStack, IIArc, nullptr, topOnly);
11083                 }
11084                 gtDispChild(tree->gtDynBlk.Addr(), indentStack, IIArc, nullptr, topOnly);
11085                 gtDispChild(tree->gtDynBlk.gtDynamicSize, indentStack, IIArcBottom, nullptr, topOnly);
11086             }
11087             break;
11088
11089         default:
11090             printf("<DON'T KNOW HOW TO DISPLAY THIS NODE> :");
11091             printf(""); // null string means flush
11092             break;
11093     }
11094 }
11095
11096 //------------------------------------------------------------------------
11097 // gtGetArgMsg: Construct a message about the given argument
11098 //
11099 // Arguments:
11100 //    call      - The call for which 'arg' is an argument
11101 //    arg       - The argument for which a message should be constructed
11102 //    argNum    - The ordinal number of the arg in the argument list
11103 //    listCount - When printing in LIR form this is the count for a GT_FIELD_LIST
11104 //                or -1 if we are not printing in LIR form
11105 //    bufp      - A pointer to the buffer into which the message is written
11106 //    bufLength - The length of the buffer pointed to by bufp
11107 //
11108 // Return Value:
11109 //    No return value, but bufp is written.
11110 //
11111 // Assumptions:
11112 //    'call' must be a call node
11113 //    'arg' must be an argument to 'call' (else gtArgEntryByNode will assert)
11114
11115 void Compiler::gtGetArgMsg(
11116     GenTreeCall* call, GenTree* arg, unsigned argNum, int listCount, char* bufp, unsigned bufLength)
11117 {
11118     if (call->gtCallLateArgs != nullptr)
11119     {
11120         fgArgTabEntry* curArgTabEntry = gtArgEntryByArgNum(call, argNum);
11121         assert(curArgTabEntry);
11122
11123         if (arg->gtFlags & GTF_LATE_ARG)
11124         {
11125             sprintf_s(bufp, bufLength, "arg%d SETUP%c", argNum, 0);
11126         }
11127         else
11128         {
11129 #ifdef _TARGET_ARM_
11130             if (curArgTabEntry->isSplit)
11131             {
11132                 regNumber firstReg = curArgTabEntry->regNum;
11133                 if (listCount == -1)
11134                 {
11135                     if (curArgTabEntry->numRegs == 1)
11136                     {
11137                         sprintf_s(bufp, bufLength, "arg%d %s out+%02x%c", argNum, compRegVarName(firstReg),
11138                                   (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE, 0);
11139                     }
11140                     else
11141                     {
11142                         regNumber lastReg   = REG_STK;
11143                         char      separator = (curArgTabEntry->numRegs == 2) ? ',' : '-';
11144                         if (curArgTabEntry->isHfaRegArg)
11145                         {
11146                             unsigned lastRegNum = genMapFloatRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
11147                             lastReg             = genMapFloatRegArgNumToRegNum(lastRegNum);
11148                         }
11149                         else
11150                         {
11151                             unsigned lastRegNum = genMapIntRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
11152                             lastReg             = genMapIntRegArgNumToRegNum(lastRegNum);
11153                         }
11154                         sprintf_s(bufp, bufLength, "arg%d %s%c%s out+%02x%c", argNum, compRegVarName(firstReg),
11155                                   separator, compRegVarName(lastReg), (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE,
11156                                   0);
11157                     }
11158                 }
11159                 else
11160                 {
11161                     unsigned curArgNum = BAD_VAR_NUM;
11162                     bool     isFloat   = curArgTabEntry->isHfaRegArg;
11163                     if (isFloat)
11164                     {
11165                         curArgNum = genMapFloatRegNumToRegArgNum(firstReg) + listCount;
11166                     }
11167                     else
11168                     {
11169                         curArgNum = genMapIntRegNumToRegArgNum(firstReg) + listCount;
11170                     }
11171
11172                     if (!isFloat && curArgNum < MAX_REG_ARG)
11173                     {
11174                         regNumber curReg = genMapIntRegArgNumToRegNum(curArgNum);
11175                         sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
11176                     }
11177                     else if (isFloat && curArgNum < MAX_FLOAT_REG_ARG)
11178                     {
11179                         regNumber curReg = genMapFloatRegArgNumToRegNum(curArgNum);
11180                         sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
11181                     }
11182                     else
11183                     {
11184                         unsigned stackSlot = listCount - curArgTabEntry->numRegs;
11185                         sprintf_s(bufp, bufLength, "arg%d m%d out+%02x%c", argNum, listCount,
11186                                   stackSlot * TARGET_POINTER_SIZE, 0);
11187                     }
11188                 }
11189                 return;
11190             }
11191 #endif // _TARGET_ARM_
11192 #if FEATURE_FIXED_OUT_ARGS
11193             if (listCount == -1)
11194             {
11195                 sprintf_s(bufp, bufLength, "arg%d out+%02x%c", argNum, curArgTabEntry->slotNum * TARGET_POINTER_SIZE,
11196                           0);
11197             }
11198             else // listCount is 0,1,2 or 3
11199             {
11200                 assert(listCount <= MAX_ARG_REG_COUNT);
11201                 sprintf_s(bufp, bufLength, "arg%d out+%02x%c", argNum,
11202                           (curArgTabEntry->slotNum + listCount) * TARGET_POINTER_SIZE, 0);
11203             }
11204 #else
11205             sprintf_s(bufp, bufLength, "arg%d on STK%c", argNum, 0);
11206 #endif
11207         }
11208     }
11209     else
11210     {
11211         sprintf_s(bufp, bufLength, "arg%d%c", argNum, 0);
11212     }
11213 }
11214
11215 //------------------------------------------------------------------------
11216 // gtGetLateArgMsg: Construct a message about the given argument
11217 //
11218 // Arguments:
11219 //    call         - The call for which 'arg' is an argument
11220 //    argx         - The argument for which a message should be constructed
11221 //    lateArgIndex - The ordinal number of the arg in the lastArg  list
11222 //    listCount    - When printing in LIR form this is the count for a multireg GT_FIELD_LIST
11223 //                   or -1 if we are not printing in LIR form
11224 //    bufp         - A pointer to the buffer into which the message is written
11225 //    bufLength    - The length of the buffer pointed to by bufp
11226 //
11227 // Return Value:
11228 //    No return value, but bufp is written.
11229 //
11230 // Assumptions:
11231 //    'call' must be a call node
11232 //    'arg' must be an argument to 'call' (else gtArgEntryByNode will assert)
11233
11234 void Compiler::gtGetLateArgMsg(
11235     GenTreeCall* call, GenTree* argx, int lateArgIndex, int listCount, char* bufp, unsigned bufLength)
11236 {
11237     assert(!argx->IsArgPlaceHolderNode()); // No place holders nodes are in gtCallLateArgs;
11238
11239     fgArgTabEntry* curArgTabEntry = gtArgEntryByLateArgIndex(call, lateArgIndex);
11240     assert(curArgTabEntry);
11241     regNumber argReg = curArgTabEntry->regNum;
11242
11243 #if !FEATURE_FIXED_OUT_ARGS
11244     assert(lateArgIndex < call->regArgListCount);
11245     assert(argReg == call->regArgList[lateArgIndex]);
11246 #else
11247     if (argReg == REG_STK)
11248     {
11249         sprintf_s(bufp, bufLength, "arg%d in out+%02x%c", curArgTabEntry->argNum,
11250                   curArgTabEntry->slotNum * TARGET_POINTER_SIZE, 0);
11251     }
11252     else
11253 #endif
11254     {
11255         if (gtArgIsThisPtr(curArgTabEntry))
11256         {
11257             sprintf_s(bufp, bufLength, "this in %s%c", compRegVarName(argReg), 0);
11258         }
11259 #ifdef _TARGET_ARM_
11260         else if (curArgTabEntry->isSplit)
11261         {
11262             regNumber firstReg = curArgTabEntry->regNum;
11263             unsigned  argNum   = curArgTabEntry->argNum;
11264             if (listCount == -1)
11265             {
11266                 if (curArgTabEntry->numRegs == 1)
11267                 {
11268                     sprintf_s(bufp, bufLength, "arg%d %s out+%02x%c", argNum, compRegVarName(firstReg),
11269                               (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE, 0);
11270                 }
11271                 else
11272                 {
11273                     regNumber lastReg   = REG_STK;
11274                     char      separator = (curArgTabEntry->numRegs == 2) ? ',' : '-';
11275                     if (curArgTabEntry->isHfaRegArg)
11276                     {
11277                         unsigned lastRegNum = genMapFloatRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
11278                         lastReg             = genMapFloatRegArgNumToRegNum(lastRegNum);
11279                     }
11280                     else
11281                     {
11282                         unsigned lastRegNum = genMapIntRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
11283                         lastReg             = genMapIntRegArgNumToRegNum(lastRegNum);
11284                     }
11285                     sprintf_s(bufp, bufLength, "arg%d %s%c%s out+%02x%c", argNum, compRegVarName(firstReg), separator,
11286                               compRegVarName(lastReg), (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE, 0);
11287                 }
11288             }
11289             else
11290             {
11291                 unsigned curArgNum = BAD_VAR_NUM;
11292                 bool     isFloat   = curArgTabEntry->isHfaRegArg;
11293                 if (isFloat)
11294                 {
11295                     curArgNum = genMapFloatRegNumToRegArgNum(firstReg) + listCount;
11296                 }
11297                 else
11298                 {
11299                     curArgNum = genMapIntRegNumToRegArgNum(firstReg) + listCount;
11300                 }
11301
11302                 if (!isFloat && curArgNum < MAX_REG_ARG)
11303                 {
11304                     regNumber curReg = genMapIntRegArgNumToRegNum(curArgNum);
11305                     sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
11306                 }
11307                 else if (isFloat && curArgNum < MAX_FLOAT_REG_ARG)
11308                 {
11309                     regNumber curReg = genMapFloatRegArgNumToRegNum(curArgNum);
11310                     sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
11311                 }
11312                 else
11313                 {
11314                     unsigned stackSlot = listCount - curArgTabEntry->numRegs;
11315                     sprintf_s(bufp, bufLength, "arg%d m%d out+%02x%c", argNum, listCount,
11316                               stackSlot * TARGET_POINTER_SIZE, 0);
11317                 }
11318             }
11319             return;
11320         }
11321 #endif // _TARGET_ARM_
11322         else
11323         {
11324 #if FEATURE_MULTIREG_ARGS
11325             if (curArgTabEntry->numRegs >= 2)
11326             {
11327                 // listCount could be -1 but it is signed, so this comparison is OK.
11328                 assert(listCount <= MAX_ARG_REG_COUNT);
11329                 char separator = (curArgTabEntry->numRegs == 2) ? ',' : '-';
11330                 sprintf_s(bufp, bufLength, "arg%d %s%c%s%c", curArgTabEntry->argNum, compRegVarName(argReg), separator,
11331                           compRegVarName(curArgTabEntry->getRegNum(curArgTabEntry->numRegs - 1)), 0);
11332             }
11333             else
11334 #endif
11335             {
11336                 sprintf_s(bufp, bufLength, "arg%d in %s%c", curArgTabEntry->argNum, compRegVarName(argReg), 0);
11337             }
11338         }
11339     }
11340 }
11341
11342 //------------------------------------------------------------------------
11343 // gtDispArgList: Dump the tree for a call arg list
11344 //
11345 // Arguments:
11346 //    call         - The call to dump arguments for
11347 //    indentStack  - the specification for the current level of indentation & arcs
11348 //
11349 // Return Value:
11350 //    None.
11351 //
11352 void Compiler::gtDispArgList(GenTreeCall* call, IndentStack* indentStack)
11353 {
11354     GenTree*  args      = call->gtCallArgs;
11355     unsigned  argnum    = 0;
11356     const int BufLength = 256;
11357     char      buf[BufLength];
11358     char*     bufp        = &buf[0];
11359     unsigned  numChildren = call->NumChildren();
11360     assert(numChildren != 0);
11361     bool argListIsLastChild = (args == call->GetChild(numChildren - 1));
11362
11363     IndentInfo arcType = IIArc;
11364     if (call->gtCallObjp != nullptr)
11365     {
11366         argnum++;
11367     }
11368
11369     while (args != nullptr)
11370     {
11371         assert(args->gtOper == GT_LIST);
11372         GenTree* arg = args->gtOp.gtOp1;
11373         if (!arg->IsNothingNode() && !arg->IsArgPlaceHolderNode())
11374         {
11375             gtGetArgMsg(call, arg, argnum, -1, bufp, BufLength);
11376             if (argListIsLastChild && (args->gtOp.gtOp2 == nullptr))
11377             {
11378                 arcType = IIArcBottom;
11379             }
11380             gtDispChild(arg, indentStack, arcType, bufp, false);
11381         }
11382         args = args->gtOp.gtOp2;
11383         argnum++;
11384     }
11385 }
11386
11387 //------------------------------------------------------------------------
11388 // gtDispArgList: Dump the tree for a call arg list
11389 //
11390 // Arguments:
11391 //    tree         - The call for which 'arg' is an argument
11392 //    indentStack  - the specification for the current level of indentation & arcs
11393 //
11394 // Return Value:
11395 //    None.
11396 //
11397 // Assumptions:
11398 //    'tree' must be a GT_LIST node
11399
11400 void Compiler::gtDispTreeList(GenTree* tree, IndentStack* indentStack /* = nullptr */)
11401 {
11402     for (/*--*/; tree != nullptr; tree = tree->gtNext)
11403     {
11404         gtDispTree(tree, indentStack);
11405         printf("\n");
11406     }
11407 }
11408
11409 //------------------------------------------------------------------------
11410 // Compiler::gtDispRange: dumps a range of LIR.
11411 //
11412 // Arguments:
11413 //    range - the range of LIR to display.
11414 //
11415 void Compiler::gtDispRange(LIR::ReadOnlyRange const& range)
11416 {
11417     for (GenTree* node : range)
11418     {
11419         gtDispLIRNode(node);
11420     }
11421 }
11422
11423 //------------------------------------------------------------------------
11424 // Compiler::gtDispTreeRange: dumps the LIR range that contains all of the
11425 //                            nodes in the dataflow tree rooted at a given
11426 //                            node.
11427 //
11428 // Arguments:
11429 //    containingRange - the LIR range that contains the root node.
11430 //    tree - the root of the dataflow tree.
11431 //
11432 void Compiler::gtDispTreeRange(LIR::Range& containingRange, GenTree* tree)
11433 {
11434     bool unused;
11435     gtDispRange(containingRange.GetTreeRange(tree, &unused));
11436 }
11437
11438 //------------------------------------------------------------------------
11439 // Compiler::gtDispLIRNode: dumps a single LIR node.
11440 //
11441 // Arguments:
11442 //    node - the LIR node to dump.
11443 //    prefixMsg - an optional prefix for each line of output.
11444 //
11445 void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr */)
11446 {
11447     auto displayOperand = [](GenTree* operand, const char* message, IndentInfo operandArc, IndentStack& indentStack,
11448                              size_t prefixIndent) {
11449         assert(operand != nullptr);
11450         assert(message != nullptr);
11451
11452         if (prefixIndent != 0)
11453         {
11454             printf("%*s", (int)prefixIndent, "");
11455         }
11456
11457         // 49 spaces for alignment
11458         printf("%-49s", "");
11459 #if FEATURE_SET_FLAGS
11460         // additional flag enlarges the flag field by one character
11461         printf(" ");
11462 #endif
11463
11464         indentStack.Push(operandArc);
11465         indentStack.print();
11466         indentStack.Pop();
11467         operandArc = IIArc;
11468
11469         printf("  t%-5d %-6s %s\n", operand->gtTreeID, varTypeName(operand->TypeGet()), message);
11470     };
11471
11472     IndentStack indentStack(this);
11473
11474     size_t prefixIndent = 0;
11475     if (prefixMsg != nullptr)
11476     {
11477         prefixIndent = strlen(prefixMsg);
11478     }
11479
11480     const int bufLength = 256;
11481     char      buf[bufLength];
11482
11483     const bool nodeIsCall = node->IsCall();
11484
11485     // Visit operands
11486     IndentInfo operandArc = IIArcTop;
11487     for (GenTree* operand : node->Operands())
11488     {
11489         if (operand->IsArgPlaceHolderNode() || !operand->IsValue())
11490         {
11491             // Either of these situations may happen with calls.
11492             continue;
11493         }
11494
11495         if (nodeIsCall)
11496         {
11497             GenTreeCall* call = node->AsCall();
11498             if (operand == call->gtCallObjp)
11499             {
11500                 sprintf_s(buf, sizeof(buf), "this in %s", compRegVarName(REG_ARG_0));
11501                 displayOperand(operand, buf, operandArc, indentStack, prefixIndent);
11502             }
11503             else if (operand == call->gtCallAddr)
11504             {
11505                 displayOperand(operand, "calli tgt", operandArc, indentStack, prefixIndent);
11506             }
11507             else if (operand == call->gtControlExpr)
11508             {
11509                 displayOperand(operand, "control expr", operandArc, indentStack, prefixIndent);
11510             }
11511             else if (operand == call->gtCallCookie)
11512             {
11513                 displayOperand(operand, "cookie", operandArc, indentStack, prefixIndent);
11514             }
11515             else
11516             {
11517                 fgArgTabEntry* curArgTabEntry = gtArgEntryByNode(call, operand);
11518                 assert(curArgTabEntry);
11519
11520                 if (operand->OperGet() == GT_LIST)
11521                 {
11522                     int listIndex = 0;
11523                     for (GenTreeArgList* element = operand->AsArgList(); element != nullptr; element = element->Rest())
11524                     {
11525                         operand = element->Current();
11526                         if (curArgTabEntry->lateArgInx == (unsigned)-1)
11527                         {
11528                             gtGetArgMsg(call, operand, curArgTabEntry->argNum, listIndex, buf, sizeof(buf));
11529                         }
11530                         else
11531                         {
11532                             gtGetLateArgMsg(call, operand, curArgTabEntry->lateArgInx, listIndex, buf, sizeof(buf));
11533                         }
11534
11535                         displayOperand(operand, buf, operandArc, indentStack, prefixIndent);
11536                         operandArc = IIArc;
11537                     }
11538                 }
11539                 else
11540                 {
11541                     if (!curArgTabEntry->isLateArg())
11542                     {
11543                         gtGetArgMsg(call, operand, curArgTabEntry->argNum, -1, buf, sizeof(buf));
11544                     }
11545                     else
11546                     {
11547                         gtGetLateArgMsg(call, operand, curArgTabEntry->lateArgInx, -1, buf, sizeof(buf));
11548                     }
11549
11550                     displayOperand(operand, buf, operandArc, indentStack, prefixIndent);
11551                 }
11552             }
11553         }
11554         else if (node->OperIsDynBlkOp())
11555         {
11556             if (operand == node->AsBlk()->Addr())
11557             {
11558                 displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent);
11559             }
11560             else if (operand == node->AsBlk()->Data())
11561             {
11562                 displayOperand(operand, "rhs", operandArc, indentStack, prefixIndent);
11563             }
11564             else
11565             {
11566                 assert(operand == node->AsDynBlk()->gtDynamicSize);
11567                 displayOperand(operand, "size", operandArc, indentStack, prefixIndent);
11568             }
11569         }
11570         else if (node->OperGet() == GT_DYN_BLK)
11571         {
11572             if (operand == node->AsBlk()->Addr())
11573             {
11574                 displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent);
11575             }
11576             else
11577             {
11578                 assert(operand == node->AsDynBlk()->gtDynamicSize);
11579                 displayOperand(operand, "size", operandArc, indentStack, prefixIndent);
11580             }
11581         }
11582         else if (node->OperIs(GT_ASG))
11583         {
11584             if (operand == node->gtGetOp1())
11585             {
11586                 displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent);
11587             }
11588             else
11589             {
11590                 displayOperand(operand, "rhs", operandArc, indentStack, prefixIndent);
11591             }
11592         }
11593         else
11594         {
11595             displayOperand(operand, "", operandArc, indentStack, prefixIndent);
11596         }
11597
11598         operandArc = IIArc;
11599     }
11600
11601     // Visit the operator
11602
11603     if (prefixMsg != nullptr)
11604     {
11605         printf("%s", prefixMsg);
11606     }
11607
11608     const bool topOnly = true;
11609     const bool isLIR   = true;
11610     gtDispTree(node, &indentStack, nullptr, topOnly, isLIR);
11611 }
11612
11613 /*****************************************************************************/
11614 #endif // DEBUG
11615
11616 /*****************************************************************************
11617  *
11618  *  Check if the given node can be folded,
11619  *  and call the methods to perform the folding
11620  */
11621
11622 GenTree* Compiler::gtFoldExpr(GenTree* tree)
11623 {
11624     unsigned kind = tree->OperKind();
11625
11626     /* We must have a simple operation to fold */
11627
11628     // If we're in CSE, it's not safe to perform tree
11629     // folding given that it can will potentially
11630     // change considered CSE candidates.
11631     if (optValnumCSE_phase)
11632     {
11633         return tree;
11634     }
11635
11636     if (!(kind & GTK_SMPOP))
11637     {
11638         return tree;
11639     }
11640
11641     GenTree* op1 = tree->gtOp.gtOp1;
11642
11643     /* Filter out non-foldable trees that can have constant children */
11644
11645     assert(kind & (GTK_UNOP | GTK_BINOP));
11646     switch (tree->gtOper)
11647     {
11648         case GT_RETFILT:
11649         case GT_RETURN:
11650         case GT_IND:
11651             return tree;
11652         default:
11653             break;
11654     }
11655
11656     /* try to fold the current node */
11657
11658     if ((kind & GTK_UNOP) && op1)
11659     {
11660         if (op1->OperKind() & GTK_CONST)
11661         {
11662             return gtFoldExprConst(tree);
11663         }
11664     }
11665     else if ((kind & GTK_BINOP) && op1 && tree->gtOp.gtOp2 &&
11666              // Don't take out conditionals for debugging
11667              !((opts.compDbgCode || opts.MinOpts()) && tree->OperIsCompare()))
11668     {
11669         GenTree* op2 = tree->gtOp.gtOp2;
11670
11671         // The atomic operations are exempted here because they are never computable statically;
11672         // one of their arguments is an address.
11673         if (((op1->OperKind() & op2->OperKind()) & GTK_CONST) && !tree->OperIsAtomicOp())
11674         {
11675             /* both nodes are constants - fold the expression */
11676             return gtFoldExprConst(tree);
11677         }
11678         else if ((op1->OperKind() | op2->OperKind()) & GTK_CONST)
11679         {
11680             /* at least one is a constant - see if we have a
11681              * special operator that can use only one constant
11682              * to fold - e.g. booleans */
11683
11684             return gtFoldExprSpecial(tree);
11685         }
11686         else if (tree->OperIsCompare())
11687         {
11688             /* comparisons of two local variables can sometimes be folded */
11689
11690             return gtFoldExprCompare(tree);
11691         }
11692         else if (op2->OperGet() == GT_COLON)
11693         {
11694             assert(tree->OperGet() == GT_QMARK);
11695
11696             GenTree* colon_op1 = op2->gtOp.gtOp1;
11697             GenTree* colon_op2 = op2->gtOp.gtOp2;
11698
11699             if (gtCompareTree(colon_op1, colon_op2))
11700             {
11701                 // Both sides of the GT_COLON are the same tree
11702
11703                 GenTree* sideEffList = nullptr;
11704                 gtExtractSideEffList(op1, &sideEffList);
11705
11706                 // Clear colon flags only if the qmark itself is not conditionaly executed
11707                 if ((tree->gtFlags & GTF_COLON_COND) == 0)
11708                 {
11709                     fgWalkTreePre(&colon_op2, gtClearColonCond);
11710                 }
11711
11712                 if (sideEffList == nullptr)
11713                 {
11714                     // No side-effects, just return colon_op2
11715                     return colon_op2;
11716                 }
11717                 else
11718                 {
11719 #ifdef DEBUG
11720                     if (verbose)
11721                     {
11722                         printf("\nIdentical GT_COLON trees with side effects! Extracting side effects...\n");
11723                         gtDispTree(sideEffList);
11724                         printf("\n");
11725                     }
11726 #endif
11727                     // Change the GT_COLON into a GT_COMMA node with the side-effects
11728                     op2->ChangeOper(GT_COMMA);
11729                     op2->gtFlags |= (sideEffList->gtFlags & GTF_ALL_EFFECT);
11730                     op2->gtOp.gtOp1 = sideEffList;
11731                     return op2;
11732                 }
11733             }
11734         }
11735     }
11736
11737     /* Return the original node (folded/bashed or not) */
11738
11739     return tree;
11740 }
11741
11742 //------------------------------------------------------------------------
11743 // gtFoldExprCall: see if a call is foldable
11744 //
11745 // Arguments:
11746 //    call - call to examine
11747 //
11748 // Returns:
11749 //    The original call if no folding happened.
11750 //    An alternative tree if folding happens.
11751 //
11752 // Notes:
11753 //    Checks for calls to Type.op_Equality, Type.op_Inequality, and
11754 //    Enum.HasFlag, and if the call is to one of these,
11755 //    attempts to optimize.
11756
11757 GenTree* Compiler::gtFoldExprCall(GenTreeCall* call)
11758 {
11759     // Can only fold calls to special intrinsics.
11760     if ((call->gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC) == 0)
11761     {
11762         return call;
11763     }
11764
11765     // Defer folding if not optimizing.
11766     if (opts.compDbgCode || opts.MinOpts())
11767     {
11768         return call;
11769     }
11770
11771     // Fetch id of the intrinsic.
11772     const CorInfoIntrinsics methodID = info.compCompHnd->getIntrinsicID(call->gtCallMethHnd);
11773
11774     switch (methodID)
11775     {
11776         case CORINFO_INTRINSIC_TypeEQ:
11777         case CORINFO_INTRINSIC_TypeNEQ:
11778         {
11779             noway_assert(call->TypeGet() == TYP_INT);
11780             GenTree* op1 = call->gtCallArgs->gtOp.gtOp1;
11781             GenTree* op2 = call->gtCallArgs->gtOp.gtOp2->gtOp.gtOp1;
11782
11783             // If either operand is known to be a RuntimeType, this can be folded
11784             GenTree* result = gtFoldTypeEqualityCall(methodID, op1, op2);
11785             if (result != nullptr)
11786             {
11787                 return result;
11788             }
11789             break;
11790         }
11791
11792         default:
11793             break;
11794     }
11795
11796     // Check for a new-style jit intrinsic.
11797     const NamedIntrinsic ni = lookupNamedIntrinsic(call->gtCallMethHnd);
11798
11799     if (ni == NI_System_Enum_HasFlag)
11800     {
11801         GenTree* thisOp = call->gtCallObjp;
11802         GenTree* flagOp = call->gtCallArgs->gtOp.gtOp1;
11803         GenTree* result = gtOptimizeEnumHasFlag(thisOp, flagOp);
11804
11805         if (result != nullptr)
11806         {
11807             return result;
11808         }
11809     }
11810
11811     return call;
11812 }
11813
11814 //------------------------------------------------------------------------
11815 // gtFoldTypeEqualityCall: see if a (potential) type equality call is foldable
11816 //
11817 // Arguments:
11818 //    methodID -- type equality intrinsic ID
11819 //    op1 -- first argument to call
11820 //    op2 -- second argument to call
11821 //
11822 // Returns:
11823 //    nulltpr if no folding happened.
11824 //    An alternative tree if folding happens.
11825 //
11826 // Notes:
11827 //    If either operand is known to be a a RuntimeType, then the type
11828 //    equality methods will simply check object identity and so we can
11829 //    fold the call into a simple compare of the call's operands.
11830
11831 GenTree* Compiler::gtFoldTypeEqualityCall(CorInfoIntrinsics methodID, GenTree* op1, GenTree* op2)
11832 {
11833     // The method must be be a type equality intrinsic
11834     assert(methodID == CORINFO_INTRINSIC_TypeEQ || methodID == CORINFO_INTRINSIC_TypeNEQ);
11835
11836     if ((gtGetTypeProducerKind(op1) == TPK_Unknown) && (gtGetTypeProducerKind(op2) == TPK_Unknown))
11837     {
11838         return nullptr;
11839     }
11840
11841     const genTreeOps simpleOp = (methodID == CORINFO_INTRINSIC_TypeEQ) ? GT_EQ : GT_NE;
11842
11843     JITDUMP("\nFolding call to Type:op_%s to a simple compare via %s\n",
11844             methodID == CORINFO_INTRINSIC_TypeEQ ? "Equality" : "Inequality", GenTree::OpName(simpleOp));
11845
11846     GenTree* compare = gtNewOperNode(simpleOp, TYP_INT, op1, op2);
11847
11848     return compare;
11849 }
11850
11851 /*****************************************************************************
11852  *
11853  *  Some comparisons can be folded:
11854  *
11855  *    locA        == locA
11856  *    classVarA   == classVarA
11857  *    locA + locB == locB + locA
11858  *
11859  */
11860
11861 GenTree* Compiler::gtFoldExprCompare(GenTree* tree)
11862 {
11863     GenTree* op1 = tree->gtOp.gtOp1;
11864     GenTree* op2 = tree->gtOp.gtOp2;
11865
11866     assert(tree->OperIsCompare());
11867
11868     /* Filter out cases that cannot be folded here */
11869
11870     /* Do not fold floats or doubles (e.g. NaN != Nan) */
11871
11872     if (varTypeIsFloating(op1->TypeGet()))
11873     {
11874         return tree;
11875     }
11876
11877     /* Currently we can only fold when the two subtrees exactly match */
11878
11879     if ((tree->gtFlags & GTF_SIDE_EFFECT) || GenTree::Compare(op1, op2, true) == false)
11880     {
11881         return tree; /* return unfolded tree */
11882     }
11883
11884     GenTree* cons;
11885
11886     switch (tree->gtOper)
11887     {
11888         case GT_EQ:
11889         case GT_LE:
11890         case GT_GE:
11891             cons = gtNewIconNode(true); /* Folds to GT_CNS_INT(true) */
11892             break;
11893
11894         case GT_NE:
11895         case GT_LT:
11896         case GT_GT:
11897             cons = gtNewIconNode(false); /* Folds to GT_CNS_INT(false) */
11898             break;
11899
11900         default:
11901             assert(!"Unexpected relOp");
11902             return tree;
11903     }
11904
11905     /* The node has beeen folded into 'cons' */
11906
11907     if (fgGlobalMorph)
11908     {
11909         fgMorphTreeDone(cons);
11910     }
11911     else
11912     {
11913         cons->gtNext = tree->gtNext;
11914         cons->gtPrev = tree->gtPrev;
11915     }
11916
11917     return cons;
11918 }
11919
11920 //------------------------------------------------------------------------
11921 // gtCreateHandleCompare: generate a type handle comparison
11922 //
11923 // Arguments:
11924 //    oper -- comparison operation (equal/not equal)
11925 //    op1 -- first operand
11926 //    op2 -- second operand
11927 //    typeCheckInliningResult -- indicates how the comparison should happen
11928 //
11929 // Returns:
11930 //    Type comparison tree
11931 //
11932
11933 GenTree* Compiler::gtCreateHandleCompare(genTreeOps             oper,
11934                                          GenTree*               op1,
11935                                          GenTree*               op2,
11936                                          CorInfoInlineTypeCheck typeCheckInliningResult)
11937 {
11938     // If we can compare pointers directly, just emit the binary operation
11939     if (typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_PASS)
11940     {
11941         return gtNewOperNode(oper, TYP_INT, op1, op2);
11942     }
11943
11944     assert(typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_USE_HELPER);
11945
11946     // Emit a call to a runtime helper
11947     GenTreeArgList* helperArgs = gtNewArgList(op1, op2);
11948     GenTree*        ret        = gtNewHelperCallNode(CORINFO_HELP_ARE_TYPES_EQUIVALENT, TYP_INT, helperArgs);
11949     if (oper == GT_EQ)
11950     {
11951         ret = gtNewOperNode(GT_NE, TYP_INT, ret, gtNewIconNode(0, TYP_INT));
11952     }
11953     else
11954     {
11955         assert(oper == GT_NE);
11956         ret = gtNewOperNode(GT_EQ, TYP_INT, ret, gtNewIconNode(0, TYP_INT));
11957     }
11958
11959     return ret;
11960 }
11961
11962 //------------------------------------------------------------------------
11963 // gtFoldTypeCompare: see if a type comparison can be further simplified
11964 //
11965 // Arguments:
11966 //    tree -- tree possibly comparing types
11967 //
11968 // Returns:
11969 //    An alternative tree if folding happens.
11970 //    Original tree otherwise.
11971 //
11972 // Notes:
11973 //    Checks for
11974 //        typeof(...) == obj.GetType()
11975 //        typeof(...) == typeof(...)
11976 //
11977 //    And potentially optimizes away the need to obtain actual
11978 //    RuntimeType objects to do the comparison.
11979
11980 GenTree* Compiler::gtFoldTypeCompare(GenTree* tree)
11981 {
11982     // Only handle EQ and NE
11983     // (maybe relop vs null someday)
11984     const genTreeOps oper = tree->OperGet();
11985     if ((oper != GT_EQ) && (oper != GT_NE))
11986     {
11987         return tree;
11988     }
11989
11990     // Screen for the right kinds of operands
11991     GenTree* const         op1     = tree->gtOp.gtOp1;
11992     const TypeProducerKind op1Kind = gtGetTypeProducerKind(op1);
11993     if (op1Kind == TPK_Unknown)
11994     {
11995         return tree;
11996     }
11997
11998     GenTree* const         op2     = tree->gtOp.gtOp2;
11999     const TypeProducerKind op2Kind = gtGetTypeProducerKind(op2);
12000     if (op2Kind == TPK_Unknown)
12001     {
12002         return tree;
12003     }
12004
12005     // We must have a handle on one side or the other here to optimize,
12006     // otherwise we can't be sure that optimizing is sound.
12007     const bool op1IsFromHandle = (op1Kind == TPK_Handle);
12008     const bool op2IsFromHandle = (op2Kind == TPK_Handle);
12009
12010     if (!(op1IsFromHandle || op2IsFromHandle))
12011     {
12012         return tree;
12013     }
12014
12015     // If both types are created via handles, we can simply compare
12016     // handles (or the indirection cells for handles) instead of the
12017     // types that they'd create.
12018     if (op1IsFromHandle && op2IsFromHandle)
12019     {
12020         JITDUMP("Optimizing compare of types-from-handles to instead compare handles\n");
12021         GenTree*             op1ClassFromHandle = tree->gtOp.gtOp1->gtCall.gtCallArgs->gtOp.gtOp1;
12022         GenTree*             op2ClassFromHandle = tree->gtOp.gtOp2->gtCall.gtCallArgs->gtOp.gtOp1;
12023         GenTree*             op1TunneledHandle  = nullptr;
12024         GenTree*             op2TunneledHandle  = nullptr;
12025         CORINFO_CLASS_HANDLE cls1Hnd            = NO_CLASS_HANDLE;
12026         CORINFO_CLASS_HANDLE cls2Hnd            = NO_CLASS_HANDLE;
12027         unsigned             runtimeLookupCount = 0;
12028
12029         // Try and find class handles from op1 and op2
12030         cls1Hnd = gtGetHelperArgClassHandle(op1ClassFromHandle, &runtimeLookupCount, &op1TunneledHandle);
12031         cls2Hnd = gtGetHelperArgClassHandle(op2ClassFromHandle, &runtimeLookupCount, &op2TunneledHandle);
12032
12033         // If we have both class handles, try and resolve the type equality test completely.
12034         bool resolveFailed = false;
12035
12036         if ((cls1Hnd != NO_CLASS_HANDLE) && (cls2Hnd != NO_CLASS_HANDLE))
12037         {
12038             JITDUMP("Asking runtime to compare %p (%s) and %p (%s) for equality\n", dspPtr(cls1Hnd),
12039                     info.compCompHnd->getClassName(cls1Hnd), dspPtr(cls2Hnd), info.compCompHnd->getClassName(cls2Hnd));
12040             TypeCompareState s = info.compCompHnd->compareTypesForEquality(cls1Hnd, cls2Hnd);
12041
12042             if (s != TypeCompareState::May)
12043             {
12044                 // Type comparison result is known.
12045                 const bool typesAreEqual = (s == TypeCompareState::Must);
12046                 const bool operatorIsEQ  = (oper == GT_EQ);
12047                 const int  compareResult = operatorIsEQ ^ typesAreEqual ? 0 : 1;
12048                 JITDUMP("Runtime reports comparison is known at jit time: %u\n", compareResult);
12049                 GenTree* result = gtNewIconNode(compareResult);
12050
12051                 // Any runtime lookups that fed into this compare are
12052                 // now dead code, so they no longer require the runtime context.
12053                 assert(lvaGenericsContextUseCount >= runtimeLookupCount);
12054                 lvaGenericsContextUseCount -= runtimeLookupCount;
12055                 return result;
12056             }
12057             else
12058             {
12059                 resolveFailed = true;
12060             }
12061         }
12062
12063         if (resolveFailed)
12064         {
12065             JITDUMP("Runtime reports comparison is NOT known at jit time\n");
12066         }
12067         else
12068         {
12069             JITDUMP("Could not find handle for %s%s\n", (cls1Hnd == NO_CLASS_HANDLE) ? " cls1" : "",
12070                     (cls2Hnd == NO_CLASS_HANDLE) ? " cls2" : "");
12071         }
12072
12073         // We can't answer the equality comparison definitively at jit
12074         // time, but can still simplfy the comparison.
12075         //
12076         // Find out how we can compare the two handles.
12077         // NOTE: We're potentially passing NO_CLASS_HANDLE, but the runtime knows what to do with it here.
12078         CorInfoInlineTypeCheck inliningKind =
12079             info.compCompHnd->canInlineTypeCheck(cls1Hnd, CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN);
12080
12081         // If the first type needs helper, check the other type: it might be okay with a simple compare.
12082         if (inliningKind == CORINFO_INLINE_TYPECHECK_USE_HELPER)
12083         {
12084             inliningKind = info.compCompHnd->canInlineTypeCheck(cls2Hnd, CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN);
12085         }
12086
12087         assert(inliningKind == CORINFO_INLINE_TYPECHECK_PASS || inliningKind == CORINFO_INLINE_TYPECHECK_USE_HELPER);
12088
12089         // If we successfully tunneled through both operands, compare
12090         // the tunneled values, otherwise compare the original values.
12091         GenTree* compare;
12092         if ((op1TunneledHandle != nullptr) && (op2TunneledHandle != nullptr))
12093         {
12094             compare = gtCreateHandleCompare(oper, op1TunneledHandle, op2TunneledHandle, inliningKind);
12095         }
12096         else
12097         {
12098             compare = gtCreateHandleCompare(oper, op1ClassFromHandle, op2ClassFromHandle, inliningKind);
12099         }
12100
12101         // Drop any now-irrelvant flags
12102         compare->gtFlags |= tree->gtFlags & (GTF_RELOP_JMP_USED | GTF_RELOP_QMARK | GTF_DONT_CSE);
12103
12104         return compare;
12105     }
12106
12107     // Just one operand creates a type from a handle.
12108     //
12109     // If the other operand is fetching the type from an object,
12110     // we can sometimes optimize the type compare into a simpler
12111     // method table comparison.
12112     //
12113     // TODO: if other operand is null...
12114     if ((op1Kind != TPK_GetType) && (op2Kind != TPK_GetType))
12115     {
12116         return tree;
12117     }
12118
12119     GenTree* const opHandle = op1IsFromHandle ? op1 : op2;
12120     GenTree* const opOther  = op1IsFromHandle ? op2 : op1;
12121
12122     // Tunnel through the handle operand to get at the class handle involved.
12123     GenTree* const       opHandleArgument = opHandle->gtCall.gtCallArgs->gtOp.gtOp1;
12124     CORINFO_CLASS_HANDLE clsHnd           = gtGetHelperArgClassHandle(opHandleArgument);
12125
12126     // If we couldn't find the class handle, give up.
12127     if (clsHnd == NO_CLASS_HANDLE)
12128     {
12129         return tree;
12130     }
12131
12132     // Ask the VM if this type can be equality tested by a simple method
12133     // table comparison.
12134     CorInfoInlineTypeCheck typeCheckInliningResult =
12135         info.compCompHnd->canInlineTypeCheck(clsHnd, CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE);
12136     if (typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_NONE)
12137     {
12138         return tree;
12139     }
12140
12141     // We're good to go.
12142     JITDUMP("Optimizing compare of obj.GetType()"
12143             " and type-from-handle to compare method table pointer\n");
12144
12145     // opHandleArgument is the method table we're looking for.
12146     GenTree* const knownMT = opHandleArgument;
12147
12148     // Fetch object method table from the object itself.
12149     GenTree* objOp = nullptr;
12150
12151     // Note we may see intrinsified or regular calls to GetType
12152     if (opOther->OperGet() == GT_INTRINSIC)
12153     {
12154         objOp = opOther->gtUnOp.gtOp1;
12155     }
12156     else
12157     {
12158         assert(opOther->OperGet() == GT_CALL);
12159         objOp = opOther->gtCall.gtCallObjp;
12160     }
12161
12162     GenTree* const objMT = gtNewOperNode(GT_IND, TYP_I_IMPL, objOp);
12163
12164     // Update various flags
12165     objMT->gtFlags |= GTF_EXCEPT;
12166     compCurBB->bbFlags |= BBF_HAS_VTABREF;
12167     optMethodFlags |= OMF_HAS_VTABLEREF;
12168
12169     // Compare the two method tables
12170     GenTree* const compare = gtCreateHandleCompare(oper, objMT, knownMT, typeCheckInliningResult);
12171
12172     // Drop any now irrelevant flags
12173     compare->gtFlags |= tree->gtFlags & (GTF_RELOP_JMP_USED | GTF_RELOP_QMARK | GTF_DONT_CSE);
12174
12175     // And we're done
12176     return compare;
12177 }
12178
12179 //------------------------------------------------------------------------
12180 // gtGetHelperArgClassHandle: find the compile time class handle from
12181 //   a helper call argument tree
12182 //
12183 // Arguments:
12184 //    tree - tree that passes the handle to the helper
12185 //    runtimeLookupCount [optional, in/out] - incremented if tree was a runtime lookup
12186 //    handleTree [optional, out] - set to the literal operand tree for indirect handles
12187 //
12188 // Returns:
12189 //    The compile time class handle if known.
12190 //
12191 CORINFO_CLASS_HANDLE Compiler::gtGetHelperArgClassHandle(GenTree*  tree,
12192                                                          unsigned* runtimeLookupCount,
12193                                                          GenTree** handleTree)
12194 {
12195     CORINFO_CLASS_HANDLE result = NO_CLASS_HANDLE;
12196
12197     // Walk through any wrapping nop.
12198     if ((tree->gtOper == GT_NOP) && (tree->gtType == TYP_I_IMPL))
12199     {
12200         tree = tree->gtOp.gtOp1;
12201     }
12202
12203     // The handle could be a literal constant
12204     if ((tree->OperGet() == GT_CNS_INT) && (tree->TypeGet() == TYP_I_IMPL))
12205     {
12206         assert(tree->IsIconHandle(GTF_ICON_CLASS_HDL));
12207         result = (CORINFO_CLASS_HANDLE)tree->gtIntCon.gtCompileTimeHandle;
12208     }
12209     // Or the result of a runtime lookup
12210     else if (tree->OperGet() == GT_RUNTIMELOOKUP)
12211     {
12212         result = tree->AsRuntimeLookup()->GetClassHandle();
12213
12214         if (runtimeLookupCount != nullptr)
12215         {
12216             *runtimeLookupCount = *runtimeLookupCount + 1;
12217         }
12218     }
12219     // Or something reached indirectly
12220     else if (tree->gtOper == GT_IND)
12221     {
12222         // The handle indirs we are looking for will be marked as non-faulting.
12223         // Certain others (eg from refanytype) may not be.
12224         if (tree->gtFlags & GTF_IND_NONFAULTING)
12225         {
12226             GenTree* handleTreeInternal = tree->gtOp.gtOp1;
12227
12228             if ((handleTreeInternal->OperGet() == GT_CNS_INT) && (handleTreeInternal->TypeGet() == TYP_I_IMPL))
12229             {
12230                 // These handle constants should be class handles.
12231                 assert(handleTreeInternal->IsIconHandle(GTF_ICON_CLASS_HDL));
12232                 result = (CORINFO_CLASS_HANDLE)handleTreeInternal->gtIntCon.gtCompileTimeHandle;
12233
12234                 if (handleTree != nullptr)
12235                 {
12236                     *handleTree = handleTreeInternal;
12237                 }
12238             }
12239         }
12240     }
12241
12242     return result;
12243 }
12244
12245 /*****************************************************************************
12246  *
12247  *  Some binary operators can be folded even if they have only one
12248  *  operand constant - e.g. boolean operators, add with 0
12249  *  multiply with 1, etc
12250  */
12251
12252 GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
12253 {
12254     GenTree*   op1  = tree->gtOp.gtOp1;
12255     GenTree*   op2  = tree->gtOp.gtOp2;
12256     genTreeOps oper = tree->OperGet();
12257
12258     GenTree* op;
12259     GenTree* cons;
12260     ssize_t  val;
12261
12262     assert(tree->OperKind() & GTK_BINOP);
12263
12264     /* Filter out operators that cannot be folded here */
12265     if (oper == GT_CAST)
12266     {
12267         return tree;
12268     }
12269
12270     /* We only consider TYP_INT for folding
12271      * Do not fold pointer arithmetic (e.g. addressing modes!) */
12272
12273     if (oper != GT_QMARK && !varTypeIsIntOrI(tree->gtType))
12274     {
12275         return tree;
12276     }
12277
12278     /* Find out which is the constant node */
12279
12280     if (op1->IsCnsIntOrI())
12281     {
12282         op   = op2;
12283         cons = op1;
12284     }
12285     else if (op2->IsCnsIntOrI())
12286     {
12287         op   = op1;
12288         cons = op2;
12289     }
12290     else
12291     {
12292         return tree;
12293     }
12294
12295     /* Get the constant value */
12296
12297     val = cons->gtIntConCommon.IconValue();
12298
12299     /* Here op is the non-constant operand, val is the constant,
12300        first is true if the constant is op1 */
12301
12302     switch (oper)
12303     {
12304         case GT_EQ:
12305         case GT_NE:
12306         case GT_GT:
12307
12308             // Optimize boxed value classes; these are always false.  This IL is
12309             // generated when a generic value is tested against null:
12310             //     <T> ... foo(T x) { ... if ((object)x == null) ...
12311             if (val == 0 && op->IsBoxedValue())
12312             {
12313                 JITDUMP("\nAttempting to optimize BOX(valueType) %s null [%06u]\n", GenTree::OpName(oper),
12314                         dspTreeID(tree));
12315
12316                 // We don't expect GT_GT with signed compares, and we
12317                 // can't predict the result if we do see it, since the
12318                 // boxed object addr could have its high bit set.
12319                 if ((oper == GT_GT) && !tree->IsUnsigned())
12320                 {
12321                     JITDUMP(" bailing; unexpected signed compare via GT_GT\n");
12322                 }
12323                 else
12324                 {
12325                     // The tree under the box must be side effect free
12326                     // since we will drop it if we optimize.
12327                     assert(!gtTreeHasSideEffects(op->gtBox.gtOp.gtOp1, GTF_SIDE_EFFECT));
12328
12329                     // See if we can optimize away the box and related statements.
12330                     GenTree* boxSourceTree = gtTryRemoveBoxUpstreamEffects(op);
12331                     bool     didOptimize   = (boxSourceTree != nullptr);
12332
12333                     // If optimization succeeded, remove the box.
12334                     if (didOptimize)
12335                     {
12336                         // Set up the result of the compare.
12337                         int compareResult = 0;
12338                         if (oper == GT_GT)
12339                         {
12340                             // GT_GT(null, box) == false
12341                             // GT_GT(box, null) == true
12342                             compareResult = (op1 == op);
12343                         }
12344                         else if (oper == GT_EQ)
12345                         {
12346                             // GT_EQ(box, null) == false
12347                             // GT_EQ(null, box) == false
12348                             compareResult = 0;
12349                         }
12350                         else
12351                         {
12352                             assert(oper == GT_NE);
12353                             // GT_NE(box, null) == true
12354                             // GT_NE(null, box) == true
12355                             compareResult = 1;
12356                         }
12357
12358                         JITDUMP("\nSuccess: replacing BOX(valueType) %s null with %d\n", GenTree::OpName(oper),
12359                                 compareResult);
12360
12361                         op = gtNewIconNode(compareResult);
12362
12363                         if (fgGlobalMorph)
12364                         {
12365                             fgMorphTreeDone(op);
12366                         }
12367                         else
12368                         {
12369                             op->gtNext = tree->gtNext;
12370                             op->gtPrev = tree->gtPrev;
12371                         }
12372
12373                         return op;
12374                     }
12375                 }
12376             }
12377
12378             break;
12379
12380         case GT_ADD:
12381             if (val == 0)
12382             {
12383                 goto DONE_FOLD;
12384             }
12385             break;
12386
12387         case GT_MUL:
12388             if (val == 1)
12389             {
12390                 goto DONE_FOLD;
12391             }
12392             else if (val == 0)
12393             {
12394                 /* Multiply by zero - return the 'zero' node, but not if side effects */
12395                 if (!(op->gtFlags & GTF_SIDE_EFFECT))
12396                 {
12397                     op = cons;
12398                     goto DONE_FOLD;
12399                 }
12400             }
12401             break;
12402
12403         case GT_DIV:
12404         case GT_UDIV:
12405             if ((op2 == cons) && (val == 1) && !(op1->OperKind() & GTK_CONST))
12406             {
12407                 goto DONE_FOLD;
12408             }
12409             break;
12410
12411         case GT_SUB:
12412             if ((op2 == cons) && (val == 0) && !(op1->OperKind() & GTK_CONST))
12413             {
12414                 goto DONE_FOLD;
12415             }
12416             break;
12417
12418         case GT_AND:
12419             if (val == 0)
12420             {
12421                 /* AND with zero - return the 'zero' node, but not if side effects */
12422
12423                 if (!(op->gtFlags & GTF_SIDE_EFFECT))
12424                 {
12425                     op = cons;
12426                     goto DONE_FOLD;
12427                 }
12428             }
12429             else
12430             {
12431                 /* The GTF_BOOLEAN flag is set for nodes that are part
12432                  * of a boolean expression, thus all their children
12433                  * are known to evaluate to only 0 or 1 */
12434
12435                 if (tree->gtFlags & GTF_BOOLEAN)
12436                 {
12437
12438                     /* The constant value must be 1
12439                      * AND with 1 stays the same */
12440                     assert(val == 1);
12441                     goto DONE_FOLD;
12442                 }
12443             }
12444             break;
12445
12446         case GT_OR:
12447             if (val == 0)
12448             {
12449                 goto DONE_FOLD;
12450             }
12451             else if (tree->gtFlags & GTF_BOOLEAN)
12452             {
12453                 /* The constant value must be 1 - OR with 1 is 1 */
12454
12455                 assert(val == 1);
12456
12457                 /* OR with one - return the 'one' node, but not if side effects */
12458
12459                 if (!(op->gtFlags & GTF_SIDE_EFFECT))
12460                 {
12461                     op = cons;
12462                     goto DONE_FOLD;
12463                 }
12464             }
12465             break;
12466
12467         case GT_LSH:
12468         case GT_RSH:
12469         case GT_RSZ:
12470         case GT_ROL:
12471         case GT_ROR:
12472             if (val == 0)
12473             {
12474                 if (op2 == cons)
12475                 {
12476                     goto DONE_FOLD;
12477                 }
12478                 else if (!(op->gtFlags & GTF_SIDE_EFFECT))
12479                 {
12480                     op = cons;
12481                     goto DONE_FOLD;
12482                 }
12483             }
12484             break;
12485
12486         case GT_QMARK:
12487         {
12488             assert(op1 == cons && op2 == op && op2->gtOper == GT_COLON);
12489             assert(op2->gtOp.gtOp1 && op2->gtOp.gtOp2);
12490
12491             assert(val == 0 || val == 1);
12492
12493             GenTree* opToDelete;
12494             if (val)
12495             {
12496                 op         = op2->AsColon()->ThenNode();
12497                 opToDelete = op2->AsColon()->ElseNode();
12498             }
12499             else
12500             {
12501                 op         = op2->AsColon()->ElseNode();
12502                 opToDelete = op2->AsColon()->ThenNode();
12503             }
12504
12505             // Clear colon flags only if the qmark itself is not conditionaly executed
12506             if ((tree->gtFlags & GTF_COLON_COND) == 0)
12507             {
12508                 fgWalkTreePre(&op, gtClearColonCond);
12509             }
12510         }
12511
12512             goto DONE_FOLD;
12513
12514         default:
12515             break;
12516     }
12517
12518     /* The node is not foldable */
12519
12520     return tree;
12521
12522 DONE_FOLD:
12523
12524     /* The node has beeen folded into 'op' */
12525
12526     // If there was an assigment update, we just morphed it into
12527     // a use, update the flags appropriately
12528     if (op->gtOper == GT_LCL_VAR)
12529     {
12530         assert(tree->OperIs(GT_ASG) || (op->gtFlags & (GTF_VAR_USEASG | GTF_VAR_DEF)) == 0);
12531
12532         op->gtFlags &= ~(GTF_VAR_USEASG | GTF_VAR_DEF);
12533     }
12534
12535     op->gtNext = tree->gtNext;
12536     op->gtPrev = tree->gtPrev;
12537
12538     return op;
12539 }
12540
12541 //------------------------------------------------------------------------
12542 // gtTryRemoveBoxUpstreamEffects: given an unused value type box,
12543 //    try and remove the upstream allocation and unnecessary parts of
12544 //    the copy.
12545 //
12546 // Arguments:
12547 //    op  - the box node to optimize
12548 //    options - controls whether and how trees are modified
12549 //        (see notes)
12550 //
12551 // Return Value:
12552 //    A tree representing the original value to box, if removal
12553 //    is successful/possible (but see note). nullptr if removal fails.
12554 //
12555 // Notes:
12556 //    Value typed box gets special treatment because it has associated
12557 //    side effects that can be removed if the box result is not used.
12558 //
12559 //    By default (options == BR_REMOVE_AND_NARROW) this method will
12560 //    try and remove unnecessary trees and will try and reduce remaning
12561 //    operations to the minimal set, possibly narrowing the width of
12562 //    loads from the box source if it is a struct.
12563 //
12564 //    To perform a trial removal, pass BR_DONT_REMOVE. This can be
12565 //    useful to determine if this optimization should only be
12566 //    performed if some other conditions hold true.
12567 //
12568 //    To remove but not alter the access to the box source, pass
12569 //    BR_REMOVE_BUT_NOT_NARROW.
12570 //
12571 //    To remove and return the tree for the type handle used for
12572 //    the boxed newobj, pass BR_REMOVE_BUT_NOT_NARROW_WANT_TYPE_HANDLE.
12573 //    This can be useful when the only part of the box that is "live"
12574 //    is its type.
12575 //
12576 //    If removal fails, is is possible that a subsequent pass may be
12577 //    able to optimize.  Blocking side effects may now be minimized
12578 //    (null or bounds checks might have been removed) or might be
12579 //    better known (inline return placeholder updated with the actual
12580 //    return expression). So the box is perhaps best left as is to
12581 //    help trigger this re-examination.
12582
12583 GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions options)
12584 {
12585     assert(op->IsBoxedValue());
12586
12587     // grab related parts for the optimization
12588     GenTreeBox* box      = op->AsBox();
12589     GenTree*    asgStmt  = box->gtAsgStmtWhenInlinedBoxValue;
12590     GenTree*    copyStmt = box->gtCopyStmtWhenInlinedBoxValue;
12591
12592     assert(asgStmt->gtOper == GT_STMT);
12593     assert(copyStmt->gtOper == GT_STMT);
12594
12595     JITDUMP("gtTryRemoveBoxUpstreamEffects: %s to %s of BOX (valuetype)"
12596             " [%06u] (assign/newobj [%06u] copy [%06u])\n",
12597             (options == BR_DONT_REMOVE) ? "checking if it is possible" : "attempting",
12598             (options == BR_MAKE_LOCAL_COPY) ? "make local unboxed version" : "remove side effects", dspTreeID(op),
12599             dspTreeID(asgStmt), dspTreeID(copyStmt));
12600
12601     // If we don't recognize the form of the assign, bail.
12602     GenTree* asg = asgStmt->gtStmt.gtStmtExpr;
12603     if (asg->gtOper != GT_ASG)
12604     {
12605         JITDUMP(" bailing; unexpected assignment op %s\n", GenTree::OpName(asg->gtOper));
12606         return nullptr;
12607     }
12608
12609     // If we're eventually going to return the type handle, remember it now.
12610     GenTree* boxTypeHandle = nullptr;
12611     if ((options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE) || (options == BR_DONT_REMOVE_WANT_TYPE_HANDLE))
12612     {
12613         GenTree*   asgSrc     = asg->gtOp.gtOp2;
12614         genTreeOps asgSrcOper = asgSrc->OperGet();
12615
12616         // Allocation may be via AllocObj or via helper call, depending
12617         // on when this is invoked and whether the jit is using AllocObj
12618         // for R2R allocations.
12619         if (asgSrcOper == GT_ALLOCOBJ)
12620         {
12621             GenTreeAllocObj* allocObj = asgSrc->AsAllocObj();
12622             boxTypeHandle             = allocObj->gtOp.gtOp1;
12623         }
12624         else if (asgSrcOper == GT_CALL)
12625         {
12626             GenTreeCall* newobjCall = asgSrc->AsCall();
12627             GenTree*     newobjArgs = newobjCall->gtCallArgs;
12628
12629             // In R2R expansions the handle may not be an explicit operand to the helper,
12630             // so we can't remove the box.
12631             if (newobjArgs == nullptr)
12632             {
12633                 assert(newobjCall->IsHelperCall(this, CORINFO_HELP_READYTORUN_NEW));
12634                 JITDUMP(" bailing; newobj via R2R helper\n");
12635                 return nullptr;
12636             }
12637
12638             boxTypeHandle = newobjArgs->AsArgList()->Current();
12639         }
12640         else
12641         {
12642             unreached();
12643         }
12644
12645         assert(boxTypeHandle != nullptr);
12646     }
12647
12648     // If we don't recognize the form of the copy, bail.
12649     GenTree* copy = copyStmt->gtStmt.gtStmtExpr;
12650     if (copy->gtOper != GT_ASG)
12651     {
12652         // GT_RET_EXPR is a tolerable temporary failure.
12653         // The jit will revisit this optimization after
12654         // inlining is done.
12655         if (copy->gtOper == GT_RET_EXPR)
12656         {
12657             JITDUMP(" bailing; must wait for replacement of copy %s\n", GenTree::OpName(copy->gtOper));
12658         }
12659         else
12660         {
12661             // Anything else is a missed case we should
12662             // figure out how to handle.  One known case
12663             // is GT_COMMAs enclosing the GT_ASG we are
12664             // looking for.
12665             JITDUMP(" bailing; unexpected copy op %s\n", GenTree::OpName(copy->gtOper));
12666         }
12667         return nullptr;
12668     }
12669
12670     // Handle case where we are optimizing the box into a local copy
12671     if (options == BR_MAKE_LOCAL_COPY)
12672     {
12673         // Drill into the box to get at the box temp local and the box type
12674         GenTree* boxTemp = box->BoxOp();
12675         assert(boxTemp->IsLocal());
12676         const unsigned boxTempLcl = boxTemp->AsLclVar()->GetLclNum();
12677         assert(lvaTable[boxTempLcl].lvType == TYP_REF);
12678         CORINFO_CLASS_HANDLE boxClass = lvaTable[boxTempLcl].lvClassHnd;
12679         assert(boxClass != nullptr);
12680
12681         // Verify that the copyDst has the expected shape
12682         // (blk|obj|ind (add (boxTempLcl, ptr-size)))
12683         //
12684         // The shape here is constrained to the patterns we produce
12685         // over in impImportAndPushBox for the inlined box case.
12686         GenTree* copyDst = copy->gtOp.gtOp1;
12687
12688         if (!copyDst->OperIs(GT_BLK, GT_IND, GT_OBJ))
12689         {
12690             JITDUMP("Unexpected copy dest operator %s\n", GenTree::OpName(copyDst->gtOper));
12691             return nullptr;
12692         }
12693
12694         GenTree* copyDstAddr = copyDst->gtOp.gtOp1;
12695         if (copyDstAddr->OperGet() != GT_ADD)
12696         {
12697             JITDUMP("Unexpected copy dest address tree\n");
12698             return nullptr;
12699         }
12700
12701         GenTree* copyDstAddrOp1 = copyDstAddr->gtOp.gtOp1;
12702         if ((copyDstAddrOp1->OperGet() != GT_LCL_VAR) || (copyDstAddrOp1->gtLclVarCommon.gtLclNum != boxTempLcl))
12703         {
12704             JITDUMP("Unexpected copy dest address 1st addend\n");
12705             return nullptr;
12706         }
12707
12708         GenTree* copyDstAddrOp2 = copyDstAddr->gtOp.gtOp2;
12709         if (!copyDstAddrOp2->IsIntegralConst(TARGET_POINTER_SIZE))
12710         {
12711             JITDUMP("Unexpected copy dest address 2nd addend\n");
12712             return nullptr;
12713         }
12714
12715         // Screening checks have all passed. Do the transformation.
12716         //
12717         // Retype the box temp to be a struct
12718         JITDUMP("Retyping box temp V%02u to struct %s\n", boxTempLcl, eeGetClassName(boxClass));
12719         lvaTable[boxTempLcl].lvType   = TYP_UNDEF;
12720         const bool isUnsafeValueClass = false;
12721         lvaSetStruct(boxTempLcl, boxClass, isUnsafeValueClass);
12722         var_types boxTempType = lvaTable[boxTempLcl].lvType;
12723
12724         // Remove the newobj and assigment to box temp
12725         JITDUMP("Bashing NEWOBJ [%06u] to NOP\n", dspTreeID(asg));
12726         asg->gtBashToNOP();
12727
12728         // Update the copy from the value to be boxed to the box temp
12729         GenTree* newDst     = gtNewOperNode(GT_ADDR, TYP_BYREF, gtNewLclvNode(boxTempLcl, boxTempType));
12730         copyDst->gtOp.gtOp1 = newDst;
12731
12732         // Return the address of the now-struct typed box temp
12733         GenTree* retValue = gtNewOperNode(GT_ADDR, TYP_BYREF, gtNewLclvNode(boxTempLcl, boxTempType));
12734
12735         return retValue;
12736     }
12737
12738     // If the copy is a struct copy, make sure we know how to isolate
12739     // any source side effects.
12740     GenTree* copySrc = copy->gtOp.gtOp2;
12741
12742     // If the copy source is from a pending inline, wait for it to resolve.
12743     if (copySrc->gtOper == GT_RET_EXPR)
12744     {
12745         JITDUMP(" bailing; must wait for replacement of copy source %s\n", GenTree::OpName(copySrc->gtOper));
12746         return nullptr;
12747     }
12748
12749     bool hasSrcSideEffect = false;
12750     bool isStructCopy     = false;
12751
12752     if (gtTreeHasSideEffects(copySrc, GTF_SIDE_EFFECT))
12753     {
12754         hasSrcSideEffect = true;
12755
12756         if (varTypeIsStruct(copySrc->gtType))
12757         {
12758             isStructCopy = true;
12759
12760             if ((copySrc->gtOper != GT_OBJ) && (copySrc->gtOper != GT_IND) && (copySrc->gtOper != GT_FIELD))
12761             {
12762                 // We don't know how to handle other cases, yet.
12763                 JITDUMP(" bailing; unexpected copy source struct op with side effect %s\n",
12764                         GenTree::OpName(copySrc->gtOper));
12765                 return nullptr;
12766             }
12767         }
12768     }
12769
12770     // If this was a trial removal, we're done.
12771     if (options == BR_DONT_REMOVE)
12772     {
12773         return copySrc;
12774     }
12775
12776     if (options == BR_DONT_REMOVE_WANT_TYPE_HANDLE)
12777     {
12778         return boxTypeHandle;
12779     }
12780
12781     // Otherwise, proceed with the optimization.
12782     //
12783     // Change the assignment expression to a NOP.
12784     JITDUMP("\nBashing NEWOBJ [%06u] to NOP\n", dspTreeID(asg));
12785     asg->gtBashToNOP();
12786
12787     // Change the copy expression so it preserves key
12788     // source side effects.
12789     JITDUMP("\nBashing COPY [%06u]", dspTreeID(copy));
12790
12791     if (!hasSrcSideEffect)
12792     {
12793         // If there were no copy source side effects just bash
12794         // the copy to a NOP.
12795         copy->gtBashToNOP();
12796         JITDUMP(" to NOP; no source side effects.\n");
12797     }
12798     else if (!isStructCopy)
12799     {
12800         // For scalar types, go ahead and produce the
12801         // value as the copy is fairly cheap and likely
12802         // the optimizer can trim things down to just the
12803         // minimal side effect parts.
12804         copyStmt->gtStmt.gtStmtExpr = copySrc;
12805         JITDUMP(" to scalar read via [%06u]\n", dspTreeID(copySrc));
12806     }
12807     else
12808     {
12809         // For struct types read the first byte of the
12810         // source struct; there's no need to read the
12811         // entire thing, and no place to put it.
12812         assert(copySrc->gtOper == GT_OBJ || copySrc->gtOper == GT_IND || copySrc->gtOper == GT_FIELD);
12813         copyStmt->gtStmt.gtStmtExpr = copySrc;
12814
12815         if (options == BR_REMOVE_AND_NARROW || options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE)
12816         {
12817             JITDUMP(" to read first byte of struct via modified [%06u]\n", dspTreeID(copySrc));
12818             copySrc->ChangeOper(GT_IND);
12819             copySrc->gtType = TYP_BYTE;
12820         }
12821         else
12822         {
12823             JITDUMP(" to read entire struct via modified [%06u]\n", dspTreeID(copySrc));
12824         }
12825     }
12826
12827     if (fgStmtListThreaded)
12828     {
12829         fgSetStmtSeq(asgStmt);
12830         fgSetStmtSeq(copyStmt);
12831     }
12832
12833     // Box effects were successfully optimized.
12834
12835     if (options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE)
12836     {
12837         return boxTypeHandle;
12838     }
12839     else
12840     {
12841         return copySrc;
12842     }
12843 }
12844
12845 //------------------------------------------------------------------------
12846 // gtOptimizeEnumHasFlag: given the operands for a call to Enum.HasFlag,
12847 //    try and optimize the call to a simple and/compare tree.
12848 //
12849 // Arguments:
12850 //    thisOp  - first argument to the call
12851 //    flagOp  - second argument to the call
12852 //
12853 // Return Value:
12854 //    A new cmp/amd tree if successful. nullptr on failure.
12855 //
12856 // Notes:
12857 //    If successful, may allocate new temps and modify connected
12858 //    statements.
12859
12860 GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp)
12861 {
12862     JITDUMP("Considering optimizing call to Enum.HasFlag....\n");
12863
12864     // Operands must be boxes
12865     if (!thisOp->IsBoxedValue() || !flagOp->IsBoxedValue())
12866     {
12867         JITDUMP("bailing, need both inputs to be BOXes\n");
12868         return nullptr;
12869     }
12870
12871     // Operands must have same type
12872     bool                 isExactThis   = false;
12873     bool                 isNonNullThis = false;
12874     CORINFO_CLASS_HANDLE thisHnd       = gtGetClassHandle(thisOp, &isExactThis, &isNonNullThis);
12875
12876     if (thisHnd == nullptr)
12877     {
12878         JITDUMP("bailing, can't find type for 'this' operand\n");
12879         return nullptr;
12880     }
12881
12882     // A boxed thisOp should have exact type and non-null instance
12883     assert(isExactThis);
12884     assert(isNonNullThis);
12885
12886     bool                 isExactFlag   = false;
12887     bool                 isNonNullFlag = false;
12888     CORINFO_CLASS_HANDLE flagHnd       = gtGetClassHandle(flagOp, &isExactFlag, &isNonNullFlag);
12889
12890     if (flagHnd == nullptr)
12891     {
12892         JITDUMP("bailing, can't find type for 'flag' operand\n");
12893         return nullptr;
12894     }
12895
12896     // A boxed flagOp should have exact type and non-null instance
12897     assert(isExactFlag);
12898     assert(isNonNullFlag);
12899
12900     if (flagHnd != thisHnd)
12901     {
12902         JITDUMP("bailing, operand types differ\n");
12903         return nullptr;
12904     }
12905
12906     // If we have a shared type instance we can't safely check type
12907     // equality, so bail.
12908     DWORD classAttribs = info.compCompHnd->getClassAttribs(thisHnd);
12909     if (classAttribs & CORINFO_FLG_SHAREDINST)
12910     {
12911         JITDUMP("bailing, have shared instance type\n");
12912         return nullptr;
12913     }
12914
12915     // Simulate removing the box for thisOP. We need to know that it can
12916     // be safely removed before we can optimize.
12917     GenTree* thisVal = gtTryRemoveBoxUpstreamEffects(thisOp, BR_DONT_REMOVE);
12918     if (thisVal == nullptr)
12919     {
12920         // Note we may fail here if the this operand comes from
12921         // a call. We should be able to retry this post-inlining.
12922         JITDUMP("bailing, can't undo box of 'this' operand\n");
12923         return nullptr;
12924     }
12925
12926     GenTree* flagVal = gtTryRemoveBoxUpstreamEffects(flagOp, BR_REMOVE_BUT_NOT_NARROW);
12927     if (flagVal == nullptr)
12928     {
12929         // Note we may fail here if the flag operand comes from
12930         // a call. We should be able to retry this post-inlining.
12931         JITDUMP("bailing, can't undo box of 'flag' operand\n");
12932         return nullptr;
12933     }
12934
12935     // Yes, both boxes can be cleaned up. Optimize.
12936     JITDUMP("Optimizing call to Enum.HasFlag\n");
12937
12938     // Undo the boxing of thisOp and prepare to operate directly
12939     // on the original enum values.
12940     thisVal = gtTryRemoveBoxUpstreamEffects(thisOp, BR_REMOVE_BUT_NOT_NARROW);
12941
12942     // Our trial removal above should guarantee successful removal here.
12943     assert(thisVal != nullptr);
12944
12945     // We should have a consistent view of the type
12946     var_types type = thisVal->TypeGet();
12947     assert(type == flagVal->TypeGet());
12948
12949     // The thisVal and flagVal trees come from earlier statements.
12950     //
12951     // Unless they are invariant values, we need to evaluate them both
12952     // to temps at those points to safely transmit the values here.
12953     //
12954     // Also we need to use the flag twice, so we need two trees for it.
12955     GenTree* thisValOpt     = nullptr;
12956     GenTree* flagValOpt     = nullptr;
12957     GenTree* flagValOptCopy = nullptr;
12958
12959     if (thisVal->IsIntegralConst())
12960     {
12961         thisValOpt = gtClone(thisVal);
12962         assert(thisValOpt != nullptr);
12963     }
12964     else
12965     {
12966         const unsigned thisTmp         = lvaGrabTemp(true DEBUGARG("Enum:HasFlag this temp"));
12967         GenTree*       thisAsg         = gtNewTempAssign(thisTmp, thisVal);
12968         GenTree*       thisAsgStmt     = thisOp->AsBox()->gtCopyStmtWhenInlinedBoxValue;
12969         thisAsgStmt->gtStmt.gtStmtExpr = thisAsg;
12970         thisValOpt                     = gtNewLclvNode(thisTmp, type);
12971     }
12972
12973     if (flagVal->IsIntegralConst())
12974     {
12975         flagValOpt = gtClone(flagVal);
12976         assert(flagValOpt != nullptr);
12977         flagValOptCopy = gtClone(flagVal);
12978         assert(flagValOptCopy != nullptr);
12979     }
12980     else
12981     {
12982         const unsigned flagTmp         = lvaGrabTemp(true DEBUGARG("Enum:HasFlag flag temp"));
12983         GenTree*       flagAsg         = gtNewTempAssign(flagTmp, flagVal);
12984         GenTree*       flagAsgStmt     = flagOp->AsBox()->gtCopyStmtWhenInlinedBoxValue;
12985         flagAsgStmt->gtStmt.gtStmtExpr = flagAsg;
12986         flagValOpt                     = gtNewLclvNode(flagTmp, type);
12987         flagValOptCopy                 = gtNewLclvNode(flagTmp, type);
12988     }
12989
12990     // Turn the call into (thisValTmp & flagTmp) == flagTmp.
12991     GenTree* andTree = gtNewOperNode(GT_AND, type, thisValOpt, flagValOpt);
12992     GenTree* cmpTree = gtNewOperNode(GT_EQ, TYP_INT, andTree, flagValOptCopy);
12993
12994     JITDUMP("Optimized call to Enum.HasFlag\n");
12995
12996     return cmpTree;
12997 }
12998
12999 /*****************************************************************************
13000  *
13001  *  Fold the given constant tree.
13002  */
13003
13004 #ifdef _PREFAST_
13005 #pragma warning(push)
13006 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
13007 #endif
13008 GenTree* Compiler::gtFoldExprConst(GenTree* tree)
13009 {
13010     unsigned kind = tree->OperKind();
13011
13012     SSIZE_T       i1, i2, itemp;
13013     INT64         lval1, lval2, ltemp;
13014     float         f1, f2;
13015     double        d1, d2;
13016     var_types     switchType;
13017     FieldSeqNode* fieldSeq = FieldSeqStore::NotAField(); // default unless we override it when folding
13018
13019     assert(kind & (GTK_UNOP | GTK_BINOP));
13020
13021     GenTree* op1 = tree->gtOp.gtOp1;
13022     GenTree* op2 = tree->gtGetOp2IfPresent();
13023
13024     if (!opts.OptEnabled(CLFLG_CONSTANTFOLD))
13025     {
13026         return tree;
13027     }
13028
13029     if (tree->OperGet() == GT_NOP)
13030     {
13031         return tree;
13032     }
13033
13034 #ifdef FEATURE_SIMD
13035     if (tree->OperGet() == GT_SIMD)
13036     {
13037         return tree;
13038     }
13039 #endif // FEATURE_SIMD
13040
13041     if (tree->gtOper == GT_ALLOCOBJ)
13042     {
13043         return tree;
13044     }
13045
13046     if (tree->gtOper == GT_RUNTIMELOOKUP)
13047     {
13048         return tree;
13049     }
13050
13051     if (kind & GTK_UNOP)
13052     {
13053         assert(op1->OperKind() & GTK_CONST);
13054
13055         switch (op1->gtType)
13056         {
13057             case TYP_INT:
13058
13059                 /* Fold constant INT unary operator */
13060
13061                 if (!op1->gtIntCon.ImmedValCanBeFolded(this, tree->OperGet()))
13062                 {
13063                     return tree;
13064                 }
13065
13066                 i1 = (int)op1->gtIntCon.gtIconVal;
13067
13068                 // If we fold a unary oper, then the folded constant
13069                 // is considered a ConstantIndexField if op1 was one
13070                 //
13071
13072                 if ((op1->gtIntCon.gtFieldSeq != nullptr) && op1->gtIntCon.gtFieldSeq->IsConstantIndexFieldSeq())
13073                 {
13074                     fieldSeq = op1->gtIntCon.gtFieldSeq;
13075                 }
13076
13077                 switch (tree->gtOper)
13078                 {
13079                     case GT_NOT:
13080                         i1 = ~i1;
13081                         break;
13082
13083                     case GT_NEG:
13084                         i1 = -i1;
13085                         break;
13086
13087                     case GT_BSWAP:
13088                         i1 = ((i1 >> 24) & 0xFF) | ((i1 >> 8) & 0xFF00) | ((i1 << 8) & 0xFF0000) |
13089                              ((i1 << 24) & 0xFF000000);
13090                         break;
13091
13092                     case GT_BSWAP16:
13093                         i1 = ((i1 >> 8) & 0xFF) | ((i1 << 8) & 0xFF00);
13094                         break;
13095
13096                     case GT_CAST:
13097                         // assert (genActualType(tree->CastToType()) == tree->gtType);
13098                         switch (tree->CastToType())
13099                         {
13100                             case TYP_BYTE:
13101                                 itemp = INT32(INT8(i1));
13102                                 goto CHK_OVF;
13103
13104                             case TYP_SHORT:
13105                                 itemp = INT32(INT16(i1));
13106                             CHK_OVF:
13107                                 if (tree->gtOverflow() && ((itemp != i1) || ((tree->gtFlags & GTF_UNSIGNED) && i1 < 0)))
13108                                 {
13109                                     goto INT_OVF;
13110                                 }
13111                                 i1 = itemp;
13112                                 goto CNS_INT;
13113
13114                             case TYP_USHORT:
13115                                 itemp = INT32(UINT16(i1));
13116                                 if (tree->gtOverflow())
13117                                 {
13118                                     if (itemp != i1)
13119                                     {
13120                                         goto INT_OVF;
13121                                     }
13122                                 }
13123                                 i1 = itemp;
13124                                 goto CNS_INT;
13125
13126                             case TYP_BOOL:
13127                             case TYP_UBYTE:
13128                                 itemp = INT32(UINT8(i1));
13129                                 if (tree->gtOverflow())
13130                                 {
13131                                     if (itemp != i1)
13132                                     {
13133                                         goto INT_OVF;
13134                                     }
13135                                 }
13136                                 i1 = itemp;
13137                                 goto CNS_INT;
13138
13139                             case TYP_UINT:
13140                                 if (!(tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && i1 < 0)
13141                                 {
13142                                     goto INT_OVF;
13143                                 }
13144                                 goto CNS_INT;
13145
13146                             case TYP_INT:
13147                                 if ((tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && i1 < 0)
13148                                 {
13149                                     goto INT_OVF;
13150                                 }
13151                                 goto CNS_INT;
13152
13153                             case TYP_ULONG:
13154                                 if (tree->IsUnsigned())
13155                                 {
13156                                     lval1 = UINT64(UINT32(i1));
13157                                 }
13158                                 else
13159                                 {
13160                                     if (tree->gtOverflow() && (i1 < 0))
13161                                     {
13162                                         goto LNG_OVF;
13163                                     }
13164                                     lval1 = UINT64(INT32(i1));
13165                                 }
13166                                 goto CNS_LONG;
13167
13168                             case TYP_LONG:
13169                                 if (tree->IsUnsigned())
13170                                 {
13171                                     lval1 = INT64(UINT32(i1));
13172                                 }
13173                                 else
13174                                 {
13175                                     lval1 = INT64(INT32(i1));
13176                                 }
13177                                 goto CNS_LONG;
13178
13179                             case TYP_FLOAT:
13180                                 if (tree->gtFlags & GTF_UNSIGNED)
13181                                 {
13182                                     f1 = forceCastToFloat(UINT32(i1));
13183                                 }
13184                                 else
13185                                 {
13186                                     f1 = forceCastToFloat(INT32(i1));
13187                                 }
13188                                 d1 = f1;
13189                                 goto CNS_DOUBLE;
13190
13191                             case TYP_DOUBLE:
13192                                 if (tree->gtFlags & GTF_UNSIGNED)
13193                                 {
13194                                     d1 = (double)UINT32(i1);
13195                                 }
13196                                 else
13197                                 {
13198                                     d1 = (double)INT32(i1);
13199                                 }
13200                                 goto CNS_DOUBLE;
13201
13202                             default:
13203                                 assert(!"BAD_TYP");
13204                                 break;
13205                         }
13206                         return tree;
13207
13208                     default:
13209                         return tree;
13210                 }
13211
13212                 goto CNS_INT;
13213
13214             case TYP_LONG:
13215
13216                 /* Fold constant LONG unary operator */
13217
13218                 if (!op1->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13219                 {
13220                     return tree;
13221                 }
13222
13223                 lval1 = op1->gtIntConCommon.LngValue();
13224
13225                 switch (tree->gtOper)
13226                 {
13227                     case GT_NOT:
13228                         lval1 = ~lval1;
13229                         break;
13230
13231                     case GT_NEG:
13232                         lval1 = -lval1;
13233                         break;
13234
13235                     case GT_BSWAP:
13236                         lval1 = ((lval1 >> 56) & 0xFF) | ((lval1 >> 40) & 0xFF00) | ((lval1 >> 24) & 0xFF0000) |
13237                                 ((lval1 >> 8) & 0xFF000000) | ((lval1 << 8) & 0xFF00000000) |
13238                                 ((lval1 << 24) & 0xFF0000000000) | ((lval1 << 40) & 0xFF000000000000) |
13239                                 ((lval1 << 56) & 0xFF00000000000000);
13240                         break;
13241
13242                     case GT_CAST:
13243                         assert(genActualType(tree->CastToType()) == tree->gtType);
13244                         switch (tree->CastToType())
13245                         {
13246                             case TYP_BYTE:
13247                                 i1 = INT32(INT8(lval1));
13248                                 goto CHECK_INT_OVERFLOW;
13249
13250                             case TYP_SHORT:
13251                                 i1 = INT32(INT16(lval1));
13252                                 goto CHECK_INT_OVERFLOW;
13253
13254                             case TYP_USHORT:
13255                                 i1 = INT32(UINT16(lval1));
13256                                 goto CHECK_UINT_OVERFLOW;
13257
13258                             case TYP_UBYTE:
13259                                 i1 = INT32(UINT8(lval1));
13260                                 goto CHECK_UINT_OVERFLOW;
13261
13262                             case TYP_INT:
13263                                 i1 = INT32(lval1);
13264
13265                             CHECK_INT_OVERFLOW:
13266                                 if (tree->gtOverflow())
13267                                 {
13268                                     if (i1 != lval1)
13269                                     {
13270                                         goto INT_OVF;
13271                                     }
13272                                     if ((tree->gtFlags & GTF_UNSIGNED) && i1 < 0)
13273                                     {
13274                                         goto INT_OVF;
13275                                     }
13276                                 }
13277                                 goto CNS_INT;
13278
13279                             case TYP_UINT:
13280                                 i1 = UINT32(lval1);
13281
13282                             CHECK_UINT_OVERFLOW:
13283                                 if (tree->gtOverflow() && UINT32(i1) != lval1)
13284                                 {
13285                                     goto INT_OVF;
13286                                 }
13287                                 goto CNS_INT;
13288
13289                             case TYP_ULONG:
13290                                 if (!(tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && lval1 < 0)
13291                                 {
13292                                     goto LNG_OVF;
13293                                 }
13294                                 goto CNS_LONG;
13295
13296                             case TYP_LONG:
13297                                 if ((tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && lval1 < 0)
13298                                 {
13299                                     goto LNG_OVF;
13300                                 }
13301                                 goto CNS_LONG;
13302
13303                             case TYP_FLOAT:
13304                             case TYP_DOUBLE:
13305                                 if ((tree->gtFlags & GTF_UNSIGNED) && lval1 < 0)
13306                                 {
13307                                     d1 = FloatingPointUtils::convertUInt64ToDouble((unsigned __int64)lval1);
13308                                 }
13309                                 else
13310                                 {
13311                                     d1 = (double)lval1;
13312                                 }
13313
13314                                 if (tree->CastToType() == TYP_FLOAT)
13315                                 {
13316                                     f1 = forceCastToFloat(d1); // truncate precision
13317                                     d1 = f1;
13318                                 }
13319                                 goto CNS_DOUBLE;
13320                             default:
13321                                 assert(!"BAD_TYP");
13322                                 break;
13323                         }
13324                         return tree;
13325
13326                     default:
13327                         return tree;
13328                 }
13329
13330                 goto CNS_LONG;
13331
13332             case TYP_FLOAT:
13333             case TYP_DOUBLE:
13334                 assert(op1->gtOper == GT_CNS_DBL);
13335
13336                 /* Fold constant DOUBLE unary operator */
13337
13338                 d1 = op1->gtDblCon.gtDconVal;
13339
13340                 switch (tree->gtOper)
13341                 {
13342                     case GT_NEG:
13343                         d1 = -d1;
13344                         break;
13345
13346                     case GT_CAST:
13347
13348                         if (tree->gtOverflowEx())
13349                         {
13350                             return tree;
13351                         }
13352
13353                         assert(genActualType(tree->CastToType()) == tree->gtType);
13354
13355                         if ((op1->gtType == TYP_FLOAT && !_finite(forceCastToFloat(d1))) ||
13356                             (op1->gtType == TYP_DOUBLE && !_finite(d1)))
13357                         {
13358                             // The floating point constant is not finite.  The ECMA spec says, in
13359                             // III 3.27, that "...if overflow occurs converting a floating point type
13360                             // to an integer, ..., the value returned is unspecified."  However, it would
13361                             // at least be desirable to have the same value returned for casting an overflowing
13362                             // constant to an int as would obtained by passing that constant as a parameter
13363                             // then casting that parameter to an int type.  We will assume that the C compiler's
13364                             // cast logic will yield the desired result (and trust testing to tell otherwise).
13365                             // Cross-compilation is an issue here; if that becomes an important scenario, we should
13366                             // capture the target-specific values of overflow casts to the various integral types as
13367                             // constants in a target-specific function.
13368                             CLANG_FORMAT_COMMENT_ANCHOR;
13369
13370                             // Don't fold conversions of +inf/-inf to integral value on all platforms
13371                             // as the value returned by JIT helper doesn't match with the C compiler's cast result.
13372                             // We want the behavior to be same with or without folding.
13373                             return tree;
13374                         }
13375
13376                         if (d1 <= -1.0 && varTypeIsUnsigned(tree->CastToType()))
13377                         {
13378                             // Don't fold conversions of these cases becasue the result is unspecified per ECMA spec
13379                             // and the native math doing the fold doesn't match the run-time computation on all
13380                             // platforms.
13381                             // We want the behavior to be same with or without folding.
13382                             return tree;
13383                         }
13384
13385                         switch (tree->CastToType())
13386                         {
13387                             case TYP_BYTE:
13388                                 i1 = INT32(INT8(d1));
13389                                 goto CNS_INT;
13390
13391                             case TYP_SHORT:
13392                                 i1 = INT32(INT16(d1));
13393                                 goto CNS_INT;
13394
13395                             case TYP_USHORT:
13396                                 i1 = INT32(UINT16(d1));
13397                                 goto CNS_INT;
13398
13399                             case TYP_UBYTE:
13400                                 i1 = INT32(UINT8(d1));
13401                                 goto CNS_INT;
13402
13403                             case TYP_INT:
13404                                 i1 = INT32(d1);
13405                                 goto CNS_INT;
13406
13407                             case TYP_UINT:
13408                                 i1 = forceCastToUInt32(d1);
13409                                 goto CNS_INT;
13410
13411                             case TYP_LONG:
13412                                 lval1 = INT64(d1);
13413                                 goto CNS_LONG;
13414
13415                             case TYP_ULONG:
13416                                 lval1 = FloatingPointUtils::convertDoubleToUInt64(d1);
13417                                 goto CNS_LONG;
13418
13419                             case TYP_FLOAT:
13420                                 d1 = forceCastToFloat(d1);
13421                                 goto CNS_DOUBLE;
13422
13423                             case TYP_DOUBLE:
13424                                 if (op1->gtType == TYP_FLOAT)
13425                                 {
13426                                     d1 = forceCastToFloat(d1); // truncate precision
13427                                 }
13428                                 goto CNS_DOUBLE; // redundant cast
13429
13430                             default:
13431                                 assert(!"BAD_TYP");
13432                                 break;
13433                         }
13434                         return tree;
13435
13436                     default:
13437                         return tree;
13438                 }
13439                 goto CNS_DOUBLE;
13440
13441             default:
13442                 /* not a foldable typ - e.g. RET const */
13443                 return tree;
13444         }
13445     }
13446
13447     /* We have a binary operator */
13448
13449     assert(kind & GTK_BINOP);
13450     assert(op2);
13451     assert(op1->OperKind() & GTK_CONST);
13452     assert(op2->OperKind() & GTK_CONST);
13453
13454     if (tree->gtOper == GT_COMMA)
13455     {
13456         return op2;
13457     }
13458
13459     if (tree->OperIsAnyList())
13460     {
13461         return tree;
13462     }
13463
13464     switchType = op1->gtType;
13465
13466     // Normally we will just switch on op1 types, but for the case where
13467     //  only op2 is a GC type and op1 is not a GC type, we use the op2 type.
13468     //  This makes us handle this as a case of folding for GC type.
13469     //
13470     if (varTypeIsGC(op2->gtType) && !varTypeIsGC(op1->gtType))
13471     {
13472         switchType = op2->gtType;
13473     }
13474
13475     switch (switchType)
13476     {
13477
13478         /*-------------------------------------------------------------------------
13479          * Fold constant REF of BYREF binary operator
13480          * These can only be comparisons or null pointers
13481          */
13482
13483         case TYP_REF:
13484
13485             /* String nodes are an RVA at this point */
13486
13487             if (op1->gtOper == GT_CNS_STR || op2->gtOper == GT_CNS_STR)
13488             {
13489                 return tree;
13490             }
13491
13492             __fallthrough;
13493
13494         case TYP_BYREF:
13495
13496             i1 = op1->gtIntConCommon.IconValue();
13497             i2 = op2->gtIntConCommon.IconValue();
13498
13499             switch (tree->gtOper)
13500             {
13501                 case GT_EQ:
13502                     i1 = (i1 == i2);
13503                     goto FOLD_COND;
13504
13505                 case GT_NE:
13506                     i1 = (i1 != i2);
13507                     goto FOLD_COND;
13508
13509                 case GT_ADD:
13510                     noway_assert(tree->gtType != TYP_REF);
13511                     // We only fold a GT_ADD that involves a null reference.
13512                     if (((op1->TypeGet() == TYP_REF) && (i1 == 0)) || ((op2->TypeGet() == TYP_REF) && (i2 == 0)))
13513                     {
13514 #ifdef DEBUG
13515                         if (verbose)
13516                         {
13517                             printf("\nFolding operator with constant nodes into a constant:\n");
13518                             gtDispTree(tree);
13519                         }
13520 #endif
13521                         // Fold into GT_IND of null byref
13522                         tree->ChangeOperConst(GT_CNS_INT);
13523                         tree->gtType              = TYP_BYREF;
13524                         tree->gtIntCon.gtIconVal  = 0;
13525                         tree->gtIntCon.gtFieldSeq = FieldSeqStore::NotAField();
13526                         if (vnStore != nullptr)
13527                         {
13528                             fgValueNumberTreeConst(tree);
13529                         }
13530 #ifdef DEBUG
13531                         if (verbose)
13532                         {
13533                             printf("\nFolded to null byref:\n");
13534                             gtDispTree(tree);
13535                         }
13536 #endif
13537                         goto DONE;
13538                     }
13539
13540                 default:
13541                     break;
13542             }
13543
13544             return tree;
13545
13546         /*-------------------------------------------------------------------------
13547          * Fold constant INT binary operator
13548          */
13549
13550         case TYP_INT:
13551
13552             if (tree->OperIsCompare() && (tree->gtType == TYP_BYTE))
13553             {
13554                 tree->gtType = TYP_INT;
13555             }
13556
13557             assert(tree->gtType == TYP_INT || varTypeIsGC(tree->TypeGet()) || tree->gtOper == GT_MKREFANY);
13558
13559             // No GC pointer types should be folded here...
13560             //
13561             assert(!varTypeIsGC(op1->gtType) && !varTypeIsGC(op2->gtType));
13562
13563             if (!op1->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13564             {
13565                 return tree;
13566             }
13567
13568             if (!op2->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13569             {
13570                 return tree;
13571             }
13572
13573             i1 = op1->gtIntConCommon.IconValue();
13574             i2 = op2->gtIntConCommon.IconValue();
13575
13576             switch (tree->gtOper)
13577             {
13578                 case GT_EQ:
13579                     i1 = (INT32(i1) == INT32(i2));
13580                     break;
13581                 case GT_NE:
13582                     i1 = (INT32(i1) != INT32(i2));
13583                     break;
13584
13585                 case GT_LT:
13586                     if (tree->gtFlags & GTF_UNSIGNED)
13587                     {
13588                         i1 = (UINT32(i1) < UINT32(i2));
13589                     }
13590                     else
13591                     {
13592                         i1 = (INT32(i1) < INT32(i2));
13593                     }
13594                     break;
13595
13596                 case GT_LE:
13597                     if (tree->gtFlags & GTF_UNSIGNED)
13598                     {
13599                         i1 = (UINT32(i1) <= UINT32(i2));
13600                     }
13601                     else
13602                     {
13603                         i1 = (INT32(i1) <= INT32(i2));
13604                     }
13605                     break;
13606
13607                 case GT_GE:
13608                     if (tree->gtFlags & GTF_UNSIGNED)
13609                     {
13610                         i1 = (UINT32(i1) >= UINT32(i2));
13611                     }
13612                     else
13613                     {
13614                         i1 = (INT32(i1) >= INT32(i2));
13615                     }
13616                     break;
13617
13618                 case GT_GT:
13619                     if (tree->gtFlags & GTF_UNSIGNED)
13620                     {
13621                         i1 = (UINT32(i1) > UINT32(i2));
13622                     }
13623                     else
13624                     {
13625                         i1 = (INT32(i1) > INT32(i2));
13626                     }
13627                     break;
13628
13629                 case GT_ADD:
13630                     itemp = i1 + i2;
13631                     if (tree->gtOverflow())
13632                     {
13633                         if (tree->gtFlags & GTF_UNSIGNED)
13634                         {
13635                             if (INT64(UINT32(itemp)) != INT64(UINT32(i1)) + INT64(UINT32(i2)))
13636                             {
13637                                 goto INT_OVF;
13638                             }
13639                         }
13640                         else
13641                         {
13642                             if (INT64(INT32(itemp)) != INT64(INT32(i1)) + INT64(INT32(i2)))
13643                             {
13644                                 goto INT_OVF;
13645                             }
13646                         }
13647                     }
13648                     i1       = itemp;
13649                     fieldSeq = GetFieldSeqStore()->Append(op1->gtIntCon.gtFieldSeq, op2->gtIntCon.gtFieldSeq);
13650                     break;
13651                 case GT_SUB:
13652                     itemp = i1 - i2;
13653                     if (tree->gtOverflow())
13654                     {
13655                         if (tree->gtFlags & GTF_UNSIGNED)
13656                         {
13657                             if (INT64(UINT32(itemp)) != ((INT64)((UINT32)i1) - (INT64)((UINT32)i2)))
13658                             {
13659                                 goto INT_OVF;
13660                             }
13661                         }
13662                         else
13663                         {
13664                             if (INT64(INT32(itemp)) != INT64(INT32(i1)) - INT64(INT32(i2)))
13665                             {
13666                                 goto INT_OVF;
13667                             }
13668                         }
13669                     }
13670                     i1 = itemp;
13671                     break;
13672                 case GT_MUL:
13673                     itemp = i1 * i2;
13674                     if (tree->gtOverflow())
13675                     {
13676                         if (tree->gtFlags & GTF_UNSIGNED)
13677                         {
13678                             if (INT64(UINT32(itemp)) != ((INT64)((UINT32)i1) * (INT64)((UINT32)i2)))
13679                             {
13680                                 goto INT_OVF;
13681                             }
13682                         }
13683                         else
13684                         {
13685                             if (INT64(INT32(itemp)) != INT64(INT32(i1)) * INT64(INT32(i2)))
13686                             {
13687                                 goto INT_OVF;
13688                             }
13689                         }
13690                     }
13691                     // For the very particular case of the "constant array index" pseudo-field, we
13692                     // assume that multiplication is by the field width, and preserves that field.
13693                     // This could obviously be made more robust by a more complicated set of annotations...
13694                     if ((op1->gtIntCon.gtFieldSeq != nullptr) && op1->gtIntCon.gtFieldSeq->IsConstantIndexFieldSeq())
13695                     {
13696                         assert(op2->gtIntCon.gtFieldSeq == FieldSeqStore::NotAField());
13697                         fieldSeq = op1->gtIntCon.gtFieldSeq;
13698                     }
13699                     else if ((op2->gtIntCon.gtFieldSeq != nullptr) &&
13700                              op2->gtIntCon.gtFieldSeq->IsConstantIndexFieldSeq())
13701                     {
13702                         assert(op1->gtIntCon.gtFieldSeq == FieldSeqStore::NotAField());
13703                         fieldSeq = op2->gtIntCon.gtFieldSeq;
13704                     }
13705                     i1 = itemp;
13706                     break;
13707
13708                 case GT_OR:
13709                     i1 |= i2;
13710                     break;
13711                 case GT_XOR:
13712                     i1 ^= i2;
13713                     break;
13714                 case GT_AND:
13715                     i1 &= i2;
13716                     break;
13717
13718                 case GT_LSH:
13719                     i1 <<= (i2 & 0x1f);
13720                     break;
13721                 case GT_RSH:
13722                     i1 >>= (i2 & 0x1f);
13723                     break;
13724                 case GT_RSZ:
13725                     /* logical shift -> make it unsigned to not propagate the sign bit */
13726                     i1 = UINT32(i1) >> (i2 & 0x1f);
13727                     break;
13728                 case GT_ROL:
13729                     i1 = (i1 << (i2 & 0x1f)) | (UINT32(i1) >> ((32 - i2) & 0x1f));
13730                     break;
13731                 case GT_ROR:
13732                     i1 = (i1 << ((32 - i2) & 0x1f)) | (UINT32(i1) >> (i2 & 0x1f));
13733                     break;
13734
13735                 /* DIV and MOD can generate an INT 0 - if division by 0
13736                  * or overflow - when dividing MIN by -1 */
13737
13738                 case GT_DIV:
13739                 case GT_MOD:
13740                 case GT_UDIV:
13741                 case GT_UMOD:
13742                     if (INT32(i2) == 0)
13743                     {
13744                         // Division by zero:
13745                         // We have to evaluate this expression and throw an exception
13746                         return tree;
13747                     }
13748                     else if ((INT32(i2) == -1) && (UINT32(i1) == 0x80000000))
13749                     {
13750                         // Overflow Division:
13751                         // We have to evaluate this expression and throw an exception
13752                         return tree;
13753                     }
13754
13755                     if (tree->gtOper == GT_DIV)
13756                     {
13757                         i1 = INT32(i1) / INT32(i2);
13758                     }
13759                     else if (tree->gtOper == GT_MOD)
13760                     {
13761                         i1 = INT32(i1) % INT32(i2);
13762                     }
13763                     else if (tree->gtOper == GT_UDIV)
13764                     {
13765                         i1 = UINT32(i1) / UINT32(i2);
13766                     }
13767                     else
13768                     {
13769                         assert(tree->gtOper == GT_UMOD);
13770                         i1 = UINT32(i1) % UINT32(i2);
13771                     }
13772                     break;
13773
13774                 default:
13775                     return tree;
13776             }
13777
13778         /* We get here after folding to a GT_CNS_INT type
13779          * change the node to the new type / value and make sure the node sizes are OK */
13780         CNS_INT:
13781         FOLD_COND:
13782
13783 #ifdef DEBUG
13784             if (verbose)
13785             {
13786                 printf("\nFolding operator with constant nodes into a constant:\n");
13787                 gtDispTree(tree);
13788             }
13789 #endif
13790
13791 #ifdef _TARGET_64BIT_
13792             // Some operations are performed as 64 bit instead of 32 bit so the upper 32 bits
13793             // need to be discarded. Since constant values are stored as ssize_t and the node
13794             // has TYP_INT the result needs to be sign extended rather than zero extended.
13795             i1 = INT32(i1);
13796 #endif // _TARGET_64BIT_
13797
13798             /* Also all conditional folding jumps here since the node hanging from
13799              * GT_JTRUE has to be a GT_CNS_INT - value 0 or 1 */
13800
13801             tree->ChangeOperConst(GT_CNS_INT);
13802             tree->gtType              = TYP_INT;
13803             tree->gtIntCon.gtIconVal  = i1;
13804             tree->gtIntCon.gtFieldSeq = fieldSeq;
13805             if (vnStore != nullptr)
13806             {
13807                 fgValueNumberTreeConst(tree);
13808             }
13809 #ifdef DEBUG
13810             if (verbose)
13811             {
13812                 printf("Bashed to int constant:\n");
13813                 gtDispTree(tree);
13814             }
13815 #endif
13816             goto DONE;
13817
13818         /* This operation is going to cause an overflow exception. Morph into
13819            an overflow helper. Put a dummy constant value for code generation.
13820
13821            We could remove all subsequent trees in the current basic block,
13822            unless this node is a child of GT_COLON
13823
13824            NOTE: Since the folded value is not constant we should not change the
13825                  "tree" node - otherwise we confuse the logic that checks if the folding
13826                  was successful - instead use one of the operands, e.g. op1
13827          */
13828
13829         LNG_OVF:
13830             // Don't fold overflow operations if not global morph phase.
13831             // The reason for this is that this optimization is replacing a gentree node
13832             // with another new gentree node. Say a GT_CALL(arglist) has one 'arg'
13833             // involving overflow arithmetic.  During assertion prop, it is possible
13834             // that the 'arg' could be constant folded and the result could lead to an
13835             // overflow.  In such a case 'arg' will get replaced with GT_COMMA node
13836             // but fgMorphArgs() - see the logic around "if(lateArgsComputed)" - doesn't
13837             // update args table. For this reason this optimization is enabled only
13838             // for global morphing phase.
13839             //
13840             // TODO-CQ: Once fgMorphArgs() is fixed this restriction could be removed.
13841             CLANG_FORMAT_COMMENT_ANCHOR;
13842
13843             if (!fgGlobalMorph)
13844             {
13845                 assert(tree->gtOverflow());
13846                 return tree;
13847             }
13848
13849             op1 = gtNewLconNode(0);
13850             if (vnStore != nullptr)
13851             {
13852                 op1->gtVNPair.SetBoth(vnStore->VNZeroForType(TYP_LONG));
13853             }
13854             goto OVF;
13855
13856         INT_OVF:
13857             // Don't fold overflow operations if not global morph phase.
13858             // The reason for this is that this optimization is replacing a gentree node
13859             // with another new gentree node. Say a GT_CALL(arglist) has one 'arg'
13860             // involving overflow arithmetic.  During assertion prop, it is possible
13861             // that the 'arg' could be constant folded and the result could lead to an
13862             // overflow.  In such a case 'arg' will get replaced with GT_COMMA node
13863             // but fgMorphArgs() - see the logic around "if(lateArgsComputed)" - doesn't
13864             // update args table. For this reason this optimization is enabled only
13865             // for global morphing phase.
13866             //
13867             // TODO-CQ: Once fgMorphArgs() is fixed this restriction could be removed.
13868
13869             if (!fgGlobalMorph)
13870             {
13871                 assert(tree->gtOverflow());
13872                 return tree;
13873             }
13874
13875             op1 = gtNewIconNode(0);
13876             if (vnStore != nullptr)
13877             {
13878                 op1->gtVNPair.SetBoth(vnStore->VNZeroForType(TYP_INT));
13879             }
13880             goto OVF;
13881
13882         OVF:
13883 #ifdef DEBUG
13884             if (verbose)
13885             {
13886                 printf("\nFolding binary operator with constant nodes into a comma throw:\n");
13887                 gtDispTree(tree);
13888             }
13889 #endif
13890             /* We will change the cast to a GT_COMMA and attach the exception helper as gtOp.gtOp1.
13891              * The constant expression zero becomes op2. */
13892
13893             assert(tree->gtOverflow());
13894             assert(tree->gtOper == GT_ADD || tree->gtOper == GT_SUB || tree->gtOper == GT_CAST ||
13895                    tree->gtOper == GT_MUL);
13896             assert(op1);
13897
13898             op2 = op1;
13899             op1 = gtNewHelperCallNode(CORINFO_HELP_OVERFLOW, TYP_VOID,
13900                                       gtNewArgList(gtNewIconNode(compCurBB->bbTryIndex)));
13901
13902             // op1 is a call to the JIT helper that throws an Overflow exception
13903             // attach the ExcSet for VNF_OverflowExc(Void) to this call
13904
13905             if (vnStore != nullptr)
13906             {
13907                 op1->gtVNPair =
13908                     vnStore->VNPWithExc(ValueNumPair(ValueNumStore::VNForVoid(), ValueNumStore::VNForVoid()),
13909                                         vnStore->VNPExcSetSingleton(
13910                                             vnStore->VNPairForFunc(TYP_REF, VNF_OverflowExc, vnStore->VNPForVoid())));
13911             }
13912
13913             tree = gtNewOperNode(GT_COMMA, tree->gtType, op1, op2);
13914
13915             return tree;
13916
13917         /*-------------------------------------------------------------------------
13918          * Fold constant LONG binary operator
13919          */
13920
13921         case TYP_LONG:
13922
13923             // No GC pointer types should be folded here...
13924             //
13925             assert(!varTypeIsGC(op1->gtType) && !varTypeIsGC(op2->gtType));
13926
13927             // op1 is known to be a TYP_LONG, op2 is normally a TYP_LONG, unless we have a shift operator in which case
13928             // it is a TYP_INT
13929             //
13930             assert((op2->gtType == TYP_LONG) || (op2->gtType == TYP_INT));
13931
13932             if (!op1->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13933             {
13934                 return tree;
13935             }
13936
13937             if (!op2->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13938             {
13939                 return tree;
13940             }
13941
13942             lval1 = op1->gtIntConCommon.LngValue();
13943
13944             // For the shift operators we can have a op2 that is a TYP_INT and thus will be GT_CNS_INT
13945             if (op2->OperGet() == GT_CNS_INT)
13946             {
13947                 lval2 = op2->gtIntConCommon.IconValue();
13948             }
13949             else
13950             {
13951                 lval2 = op2->gtIntConCommon.LngValue();
13952             }
13953
13954             switch (tree->gtOper)
13955             {
13956                 case GT_EQ:
13957                     i1 = (lval1 == lval2);
13958                     goto FOLD_COND;
13959                 case GT_NE:
13960                     i1 = (lval1 != lval2);
13961                     goto FOLD_COND;
13962
13963                 case GT_LT:
13964                     if (tree->gtFlags & GTF_UNSIGNED)
13965                     {
13966                         i1 = (UINT64(lval1) < UINT64(lval2));
13967                     }
13968                     else
13969                     {
13970                         i1 = (lval1 < lval2);
13971                     }
13972                     goto FOLD_COND;
13973
13974                 case GT_LE:
13975                     if (tree->gtFlags & GTF_UNSIGNED)
13976                     {
13977                         i1 = (UINT64(lval1) <= UINT64(lval2));
13978                     }
13979                     else
13980                     {
13981                         i1 = (lval1 <= lval2);
13982                     }
13983                     goto FOLD_COND;
13984
13985                 case GT_GE:
13986                     if (tree->gtFlags & GTF_UNSIGNED)
13987                     {
13988                         i1 = (UINT64(lval1) >= UINT64(lval2));
13989                     }
13990                     else
13991                     {
13992                         i1 = (lval1 >= lval2);
13993                     }
13994                     goto FOLD_COND;
13995
13996                 case GT_GT:
13997                     if (tree->gtFlags & GTF_UNSIGNED)
13998                     {
13999                         i1 = (UINT64(lval1) > UINT64(lval2));
14000                     }
14001                     else
14002                     {
14003                         i1 = (lval1 > lval2);
14004                     }
14005                     goto FOLD_COND;
14006
14007                 case GT_ADD:
14008                     ltemp = lval1 + lval2;
14009
14010                 LNG_ADD_CHKOVF:
14011                     /* For the SIGNED case - If there is one positive and one negative operand, there can be no overflow
14012                      * If both are positive, the result has to be positive, and similary for negatives.
14013                      *
14014                      * For the UNSIGNED case - If a UINT32 operand is bigger than the result then OVF */
14015
14016                     if (tree->gtOverflow())
14017                     {
14018                         if (tree->gtFlags & GTF_UNSIGNED)
14019                         {
14020                             if ((UINT64(lval1) > UINT64(ltemp)) || (UINT64(lval2) > UINT64(ltemp)))
14021                             {
14022                                 goto LNG_OVF;
14023                             }
14024                         }
14025                         else if (((lval1 < 0) == (lval2 < 0)) && ((lval1 < 0) != (ltemp < 0)))
14026                         {
14027                             goto LNG_OVF;
14028                         }
14029                     }
14030                     lval1 = ltemp;
14031                     break;
14032
14033                 case GT_SUB:
14034                     ltemp = lval1 - lval2;
14035                     if (tree->gtOverflow())
14036                     {
14037                         if (tree->gtFlags & GTF_UNSIGNED)
14038                         {
14039                             if (UINT64(lval2) > UINT64(lval1))
14040                             {
14041                                 goto LNG_OVF;
14042                             }
14043                         }
14044                         else
14045                         {
14046                             /* If both operands are +ve or both are -ve, there can be no
14047                                overflow. Else use the logic for : lval1 + (-lval2) */
14048
14049                             if ((lval1 < 0) != (lval2 < 0))
14050                             {
14051                                 if (lval2 == INT64_MIN)
14052                                 {
14053                                     goto LNG_OVF;
14054                                 }
14055                                 lval2 = -lval2;
14056                                 goto LNG_ADD_CHKOVF;
14057                             }
14058                         }
14059                     }
14060                     lval1 = ltemp;
14061                     break;
14062
14063                 case GT_MUL:
14064                     ltemp = lval1 * lval2;
14065
14066                     if (tree->gtOverflow() && lval2 != 0)
14067                     {
14068
14069                         if (tree->gtFlags & GTF_UNSIGNED)
14070                         {
14071                             UINT64 ultemp = ltemp;
14072                             UINT64 ulval1 = lval1;
14073                             UINT64 ulval2 = lval2;
14074                             if ((ultemp / ulval2) != ulval1)
14075                             {
14076                                 goto LNG_OVF;
14077                             }
14078                         }
14079                         else
14080                         {
14081                             // This does a multiply and then reverses it.  This test works great except for MIN_INT *
14082                             //-1.  In that case we mess up the sign on ltmp.  Make sure to double check the sign.
14083                             // if either is 0, then no overflow
14084                             if (lval1 != 0) // lval2 checked above.
14085                             {
14086                                 if (((lval1 < 0) == (lval2 < 0)) && (ltemp < 0))
14087                                 {
14088                                     goto LNG_OVF;
14089                                 }
14090                                 if (((lval1 < 0) != (lval2 < 0)) && (ltemp > 0))
14091                                 {
14092                                     goto LNG_OVF;
14093                                 }
14094
14095                                 // TODO-Amd64-Unix: Remove the code that disables optimizations for this method when the
14096                                 // clang
14097                                 // optimizer is fixed and/or the method implementation is refactored in a simpler code.
14098                                 // There is a bug in the clang-3.5 optimizer. The issue is that in release build the
14099                                 // optimizer is mistyping (or just wrongly decides to use 32 bit operation for a corner
14100                                 // case of MIN_LONG) the args of the (ltemp / lval2) to int (it does a 32 bit div
14101                                 // operation instead of 64 bit.). For the case of lval1 and lval2 equal to MIN_LONG
14102                                 // (0x8000000000000000) this results in raising a SIGFPE.
14103                                 // Optimizations disabled for now. See compiler.h.
14104                                 if ((ltemp / lval2) != lval1)
14105                                 {
14106                                     goto LNG_OVF;
14107                                 }
14108                             }
14109                         }
14110                     }
14111
14112                     lval1 = ltemp;
14113                     break;
14114
14115                 case GT_OR:
14116                     lval1 |= lval2;
14117                     break;
14118                 case GT_XOR:
14119                     lval1 ^= lval2;
14120                     break;
14121                 case GT_AND:
14122                     lval1 &= lval2;
14123                     break;
14124
14125                 case GT_LSH:
14126                     lval1 <<= (lval2 & 0x3f);
14127                     break;
14128                 case GT_RSH:
14129                     lval1 >>= (lval2 & 0x3f);
14130                     break;
14131                 case GT_RSZ:
14132                     /* logical shift -> make it unsigned to not propagate the sign bit */
14133                     lval1 = UINT64(lval1) >> (lval2 & 0x3f);
14134                     break;
14135                 case GT_ROL:
14136                     lval1 = (lval1 << (lval2 & 0x3f)) | (UINT64(lval1) >> ((64 - lval2) & 0x3f));
14137                     break;
14138                 case GT_ROR:
14139                     lval1 = (lval1 << ((64 - lval2) & 0x3f)) | (UINT64(lval1) >> (lval2 & 0x3f));
14140                     break;
14141
14142                 // Both DIV and IDIV on x86 raise an exception for min_int (and min_long) / -1.  So we preserve
14143                 // that behavior here.
14144                 case GT_DIV:
14145                     if (!lval2)
14146                     {
14147                         return tree;
14148                     }
14149
14150                     if (UINT64(lval1) == UI64(0x8000000000000000) && lval2 == INT64(-1))
14151                     {
14152                         return tree;
14153                     }
14154                     lval1 /= lval2;
14155                     break;
14156
14157                 case GT_MOD:
14158                     if (!lval2)
14159                     {
14160                         return tree;
14161                     }
14162                     if (UINT64(lval1) == UI64(0x8000000000000000) && lval2 == INT64(-1))
14163                     {
14164                         return tree;
14165                     }
14166                     lval1 %= lval2;
14167                     break;
14168
14169                 case GT_UDIV:
14170                     if (!lval2)
14171                     {
14172                         return tree;
14173                     }
14174                     if (UINT64(lval1) == UI64(0x8000000000000000) && lval2 == INT64(-1))
14175                     {
14176                         return tree;
14177                     }
14178                     lval1 = UINT64(lval1) / UINT64(lval2);
14179                     break;
14180
14181                 case GT_UMOD:
14182                     if (!lval2)
14183                     {
14184                         return tree;
14185                     }
14186                     if (UINT64(lval1) == UI64(0x8000000000000000) && lval2 == INT64(-1))
14187                     {
14188                         return tree;
14189                     }
14190                     lval1 = UINT64(lval1) % UINT64(lval2);
14191                     break;
14192                 default:
14193                     return tree;
14194             }
14195
14196         CNS_LONG:
14197
14198             if (fieldSeq != FieldSeqStore::NotAField())
14199             {
14200                 return tree;
14201             }
14202
14203 #ifdef DEBUG
14204             if (verbose)
14205             {
14206                 printf("\nFolding long operator with constant nodes into a constant:\n");
14207                 gtDispTree(tree);
14208             }
14209 #endif
14210             assert((GenTree::s_gtNodeSizes[GT_CNS_NATIVELONG] == TREE_NODE_SZ_SMALL) ||
14211                    (tree->gtDebugFlags & GTF_DEBUG_NODE_LARGE));
14212
14213             tree->ChangeOperConst(GT_CNS_NATIVELONG);
14214             tree->gtIntConCommon.SetLngValue(lval1);
14215             if (vnStore != nullptr)
14216             {
14217                 fgValueNumberTreeConst(tree);
14218             }
14219
14220 #ifdef DEBUG
14221             if (verbose)
14222             {
14223                 printf("Bashed to long constant:\n");
14224                 gtDispTree(tree);
14225             }
14226 #endif
14227             goto DONE;
14228
14229         /*-------------------------------------------------------------------------
14230          * Fold constant FLOAT or DOUBLE binary operator
14231          */
14232
14233         case TYP_FLOAT:
14234         case TYP_DOUBLE:
14235
14236             if (tree->gtOverflowEx())
14237             {
14238                 return tree;
14239             }
14240
14241             assert(op1->gtOper == GT_CNS_DBL);
14242             d1 = op1->gtDblCon.gtDconVal;
14243
14244             assert(varTypeIsFloating(op2->gtType));
14245             assert(op2->gtOper == GT_CNS_DBL);
14246             d2 = op2->gtDblCon.gtDconVal;
14247
14248             /* Special case - check if we have NaN operands.
14249              * For comparisons if not an unordered operation always return 0.
14250              * For unordered operations (i.e. the GTF_RELOP_NAN_UN flag is set)
14251              * the result is always true - return 1. */
14252
14253             if (_isnan(d1) || _isnan(d2))
14254             {
14255 #ifdef DEBUG
14256                 if (verbose)
14257                 {
14258                     printf("Double operator(s) is NaN\n");
14259                 }
14260 #endif
14261                 if (tree->OperKind() & GTK_RELOP)
14262                 {
14263                     if (tree->gtFlags & GTF_RELOP_NAN_UN)
14264                     {
14265                         /* Unordered comparison with NaN always succeeds */
14266                         i1 = 1;
14267                         goto FOLD_COND;
14268                     }
14269                     else
14270                     {
14271                         /* Normal comparison with NaN always fails */
14272                         i1 = 0;
14273                         goto FOLD_COND;
14274                     }
14275                 }
14276             }
14277
14278             switch (tree->gtOper)
14279             {
14280                 case GT_EQ:
14281                     i1 = (d1 == d2);
14282                     goto FOLD_COND;
14283                 case GT_NE:
14284                     i1 = (d1 != d2);
14285                     goto FOLD_COND;
14286
14287                 case GT_LT:
14288                     i1 = (d1 < d2);
14289                     goto FOLD_COND;
14290                 case GT_LE:
14291                     i1 = (d1 <= d2);
14292                     goto FOLD_COND;
14293                 case GT_GE:
14294                     i1 = (d1 >= d2);
14295                     goto FOLD_COND;
14296                 case GT_GT:
14297                     i1 = (d1 > d2);
14298                     goto FOLD_COND;
14299
14300                 // Floating point arithmetic should be done in declared
14301                 // precision while doing constant folding. For this reason though TYP_FLOAT
14302                 // constants are stored as double constants, while performing float arithmetic,
14303                 // double constants should be converted to float.  Here is an example case
14304                 // where performing arithmetic in double precision would lead to incorrect
14305                 // results.
14306                 //
14307                 // Example:
14308                 // float a = float.MaxValue;
14309                 // float b = a*a;   This will produce +inf in single precision and 1.1579207543382391e+077 in double
14310                 //                  precision.
14311                 // flaot c = b/b;   This will produce NaN in single precision and 1 in double precision.
14312                 case GT_ADD:
14313                     if (op1->TypeGet() == TYP_FLOAT)
14314                     {
14315                         f1 = forceCastToFloat(d1);
14316                         f2 = forceCastToFloat(d2);
14317                         d1 = forceCastToFloat(f1 + f2);
14318                     }
14319                     else
14320                     {
14321                         d1 += d2;
14322                     }
14323                     break;
14324
14325                 case GT_SUB:
14326                     if (op1->TypeGet() == TYP_FLOAT)
14327                     {
14328                         f1 = forceCastToFloat(d1);
14329                         f2 = forceCastToFloat(d2);
14330                         d1 = forceCastToFloat(f1 - f2);
14331                     }
14332                     else
14333                     {
14334                         d1 -= d2;
14335                     }
14336                     break;
14337
14338                 case GT_MUL:
14339                     if (op1->TypeGet() == TYP_FLOAT)
14340                     {
14341                         f1 = forceCastToFloat(d1);
14342                         f2 = forceCastToFloat(d2);
14343                         d1 = forceCastToFloat(f1 * f2);
14344                     }
14345                     else
14346                     {
14347                         d1 *= d2;
14348                     }
14349                     break;
14350
14351                 case GT_DIV:
14352                     if (!d2)
14353                     {
14354                         return tree;
14355                     }
14356                     if (op1->TypeGet() == TYP_FLOAT)
14357                     {
14358                         f1 = forceCastToFloat(d1);
14359                         f2 = forceCastToFloat(d2);
14360                         d1 = forceCastToFloat(f1 / f2);
14361                     }
14362                     else
14363                     {
14364                         d1 /= d2;
14365                     }
14366                     break;
14367
14368                 default:
14369                     return tree;
14370             }
14371
14372         CNS_DOUBLE:
14373
14374 #ifdef DEBUG
14375             if (verbose)
14376             {
14377                 printf("\nFolding fp operator with constant nodes into a fp constant:\n");
14378                 gtDispTree(tree);
14379             }
14380 #endif
14381
14382             assert((GenTree::s_gtNodeSizes[GT_CNS_DBL] == TREE_NODE_SZ_SMALL) ||
14383                    (tree->gtDebugFlags & GTF_DEBUG_NODE_LARGE));
14384
14385             tree->ChangeOperConst(GT_CNS_DBL);
14386             tree->gtDblCon.gtDconVal = d1;
14387             if (vnStore != nullptr)
14388             {
14389                 fgValueNumberTreeConst(tree);
14390             }
14391 #ifdef DEBUG
14392             if (verbose)
14393             {
14394                 printf("Bashed to fp constant:\n");
14395                 gtDispTree(tree);
14396             }
14397 #endif
14398             goto DONE;
14399
14400         default:
14401             /* not a foldable typ */
14402             return tree;
14403     }
14404
14405 //-------------------------------------------------------------------------
14406
14407 DONE:
14408
14409     /* Make sure no side effect flags are set on this constant node */
14410
14411     tree->gtFlags &= ~GTF_ALL_EFFECT;
14412
14413     return tree;
14414 }
14415 #ifdef _PREFAST_
14416 #pragma warning(pop)
14417 #endif
14418
14419 //------------------------------------------------------------------------
14420 // gtNewTempAssign: Create an assignment of the given value to a temp.
14421 //
14422 // Arguments:
14423 //    tmp         - local number for a compiler temp
14424 //    val         - value to assign to the temp
14425 //    pAfterStmt  - statement to insert any additional statements after
14426 //    ilOffset    - il offset for new statements
14427 //    block       - block to insert any additional statements in
14428 //
14429 // Return Value:
14430 //    Normally a new assignment node.
14431 //    However may return a nop node if val is simply a reference to the temp.
14432 //
14433 // Notes:
14434 //    Self-assignments may be represented via NOPs.
14435 //
14436 //    May update the type of the temp, if it was previously unknown.
14437 //
14438 //    May set compFloatingPointUsed.
14439
14440 GenTree* Compiler::gtNewTempAssign(
14441     unsigned tmp, GenTree* val, GenTree** pAfterStmt, IL_OFFSETX ilOffset, BasicBlock* block)
14442 {
14443     // Self-assignment is a nop.
14444     if (val->OperGet() == GT_LCL_VAR && val->gtLclVarCommon.gtLclNum == tmp)
14445     {
14446         return gtNewNothingNode();
14447     }
14448
14449     LclVarDsc* varDsc = lvaTable + tmp;
14450
14451     if (varDsc->TypeGet() == TYP_I_IMPL && val->TypeGet() == TYP_BYREF)
14452     {
14453         impBashVarAddrsToI(val);
14454     }
14455
14456     var_types valTyp = val->TypeGet();
14457     if (val->OperGet() == GT_LCL_VAR && lvaTable[val->gtLclVar.gtLclNum].lvNormalizeOnLoad())
14458     {
14459         valTyp      = lvaGetRealType(val->gtLclVar.gtLclNum);
14460         val->gtType = valTyp;
14461     }
14462     var_types dstTyp = varDsc->TypeGet();
14463
14464     /* If the variable's lvType is not yet set then set it here */
14465     if (dstTyp == TYP_UNDEF)
14466     {
14467         varDsc->lvType = dstTyp = genActualType(valTyp);
14468         if (varTypeIsGC(dstTyp))
14469         {
14470             varDsc->lvStructGcCount = 1;
14471         }
14472 #if FEATURE_SIMD
14473         else if (varTypeIsSIMD(dstTyp))
14474         {
14475             varDsc->lvSIMDType = 1;
14476         }
14477 #endif
14478     }
14479
14480 #ifdef DEBUG
14481     /* Make sure the actual types match               */
14482     if (genActualType(valTyp) != genActualType(dstTyp))
14483     {
14484         // Plus some other exceptions that are apparently legal:
14485         // 1) TYP_REF or BYREF = TYP_I_IMPL
14486         bool ok = false;
14487         if (varTypeIsGC(dstTyp) && (valTyp == TYP_I_IMPL))
14488         {
14489             ok = true;
14490         }
14491         // 2) TYP_DOUBLE = TYP_FLOAT or TYP_FLOAT = TYP_DOUBLE
14492         else if (varTypeIsFloating(dstTyp) && varTypeIsFloating(valTyp))
14493         {
14494             ok = true;
14495         }
14496
14497         if (!ok)
14498         {
14499             gtDispTree(val);
14500             assert(!"Incompatible types for gtNewTempAssign");
14501         }
14502     }
14503 #endif
14504
14505     // Floating Point assignments can be created during inlining
14506     // see "Zero init inlinee locals:" in fgInlinePrependStatements
14507     // thus we may need to set compFloatingPointUsed to true here.
14508     //
14509     if (varTypeIsFloating(dstTyp) && (compFloatingPointUsed == false))
14510     {
14511         compFloatingPointUsed = true;
14512     }
14513
14514     /* Create the assignment node */
14515
14516     GenTree* asg;
14517     GenTree* dest = gtNewLclvNode(tmp, dstTyp);
14518     dest->gtFlags |= GTF_VAR_DEF;
14519
14520     // With first-class structs, we should be propagating the class handle on all non-primitive
14521     // struct types. We don't have a convenient way to do that for all SIMD temps, since some
14522     // internal trees use SIMD types that are not used by the input IL. In this case, we allow
14523     // a null type handle and derive the necessary information about the type from its varType.
14524     CORINFO_CLASS_HANDLE structHnd = gtGetStructHandleIfPresent(val);
14525     if (varTypeIsStruct(valTyp) && ((structHnd != NO_CLASS_HANDLE) || (varTypeIsSIMD(valTyp))))
14526     {
14527         // The struct value may be be a child of a GT_COMMA.
14528         GenTree* valx = val->gtEffectiveVal(/*commaOnly*/ true);
14529
14530         if (structHnd != NO_CLASS_HANDLE)
14531         {
14532             lvaSetStruct(tmp, structHnd, false);
14533         }
14534         else
14535         {
14536             assert(valx->gtOper != GT_OBJ);
14537         }
14538         dest->gtFlags |= GTF_DONT_CSE;
14539         valx->gtFlags |= GTF_DONT_CSE;
14540         asg = impAssignStruct(dest, val, structHnd, (unsigned)CHECK_SPILL_NONE, pAfterStmt, ilOffset, block);
14541     }
14542     else
14543     {
14544         asg = gtNewAssignNode(dest, val);
14545     }
14546
14547     if (compRationalIRForm)
14548     {
14549         Rationalizer::RewriteAssignmentIntoStoreLcl(asg->AsOp());
14550     }
14551
14552     return asg;
14553 }
14554
14555 /*****************************************************************************
14556  *
14557  *  Create a helper call to access a COM field (iff 'assg' is non-zero this is
14558  *  an assignment and 'assg' is the new value).
14559  */
14560
14561 GenTree* Compiler::gtNewRefCOMfield(GenTree*                objPtr,
14562                                     CORINFO_RESOLVED_TOKEN* pResolvedToken,
14563                                     CORINFO_ACCESS_FLAGS    access,
14564                                     CORINFO_FIELD_INFO*     pFieldInfo,
14565                                     var_types               lclTyp,
14566                                     CORINFO_CLASS_HANDLE    structType,
14567                                     GenTree*                assg)
14568 {
14569     assert(pFieldInfo->fieldAccessor == CORINFO_FIELD_INSTANCE_HELPER ||
14570            pFieldInfo->fieldAccessor == CORINFO_FIELD_INSTANCE_ADDR_HELPER ||
14571            pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_ADDR_HELPER);
14572
14573     /* If we can't access it directly, we need to call a helper function */
14574     GenTreeArgList* args       = nullptr;
14575     var_types       helperType = TYP_BYREF;
14576
14577     if (pFieldInfo->fieldAccessor == CORINFO_FIELD_INSTANCE_HELPER)
14578     {
14579         if (access & CORINFO_ACCESS_SET)
14580         {
14581             assert(assg != nullptr);
14582             // helper needs pointer to struct, not struct itself
14583             if (pFieldInfo->helper == CORINFO_HELP_SETFIELDSTRUCT)
14584             {
14585                 assert(structType != nullptr);
14586                 assg = impGetStructAddr(assg, structType, (unsigned)CHECK_SPILL_ALL, true);
14587             }
14588             else if (lclTyp == TYP_DOUBLE && assg->TypeGet() == TYP_FLOAT)
14589             {
14590                 assg = gtNewCastNode(TYP_DOUBLE, assg, false, TYP_DOUBLE);
14591             }
14592             else if (lclTyp == TYP_FLOAT && assg->TypeGet() == TYP_DOUBLE)
14593             {
14594                 assg = gtNewCastNode(TYP_FLOAT, assg, false, TYP_FLOAT);
14595             }
14596
14597             args       = gtNewArgList(assg);
14598             helperType = TYP_VOID;
14599         }
14600         else if (access & CORINFO_ACCESS_GET)
14601         {
14602             helperType = lclTyp;
14603
14604             // The calling convention for the helper does not take into
14605             // account optimization of primitive structs.
14606             if ((pFieldInfo->helper == CORINFO_HELP_GETFIELDSTRUCT) && !varTypeIsStruct(lclTyp))
14607             {
14608                 helperType = TYP_STRUCT;
14609             }
14610         }
14611     }
14612
14613     if (pFieldInfo->helper == CORINFO_HELP_GETFIELDSTRUCT || pFieldInfo->helper == CORINFO_HELP_SETFIELDSTRUCT)
14614     {
14615         assert(pFieldInfo->structType != nullptr);
14616         args = gtNewListNode(gtNewIconEmbClsHndNode(pFieldInfo->structType), args);
14617     }
14618
14619     GenTree* fieldHnd = impTokenToHandle(pResolvedToken);
14620     if (fieldHnd == nullptr)
14621     { // compDonotInline()
14622         return nullptr;
14623     }
14624
14625     args = gtNewListNode(fieldHnd, args);
14626
14627     // If it's a static field, we shouldn't have an object node
14628     // If it's an instance field, we have an object node
14629     assert((pFieldInfo->fieldAccessor != CORINFO_FIELD_STATIC_ADDR_HELPER) ^ (objPtr == nullptr));
14630
14631     if (objPtr != nullptr)
14632     {
14633         args = gtNewListNode(objPtr, args);
14634     }
14635
14636     GenTreeCall* call = gtNewHelperCallNode(pFieldInfo->helper, genActualType(helperType), args);
14637
14638 #if FEATURE_MULTIREG_RET
14639     if (varTypeIsStruct(call))
14640     {
14641         // Initialize Return type descriptor of call node.
14642         ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
14643         retTypeDesc->InitializeStructReturnType(this, structType);
14644     }
14645 #endif // FEATURE_MULTIREG_RET
14646
14647     GenTree* result = call;
14648
14649     if (pFieldInfo->fieldAccessor == CORINFO_FIELD_INSTANCE_HELPER)
14650     {
14651         if (access & CORINFO_ACCESS_GET)
14652         {
14653             if (pFieldInfo->helper == CORINFO_HELP_GETFIELDSTRUCT)
14654             {
14655                 if (!varTypeIsStruct(lclTyp))
14656                 {
14657                     // get the result as primitive type
14658                     result = impGetStructAddr(result, structType, (unsigned)CHECK_SPILL_ALL, true);
14659                     result = gtNewOperNode(GT_IND, lclTyp, result);
14660                 }
14661             }
14662             else if (varTypeIsIntegral(lclTyp) && genTypeSize(lclTyp) < genTypeSize(TYP_INT))
14663             {
14664                 // The helper does not extend the small return types.
14665                 result = gtNewCastNode(genActualType(lclTyp), result, false, lclTyp);
14666             }
14667         }
14668     }
14669     else
14670     {
14671         // OK, now do the indirection
14672         if (access & CORINFO_ACCESS_GET)
14673         {
14674             if (varTypeIsStruct(lclTyp))
14675             {
14676                 result = gtNewObjNode(structType, result);
14677             }
14678             else
14679             {
14680                 result = gtNewOperNode(GT_IND, lclTyp, result);
14681             }
14682             result->gtFlags |= (GTF_EXCEPT | GTF_GLOB_REF);
14683         }
14684         else if (access & CORINFO_ACCESS_SET)
14685         {
14686             if (varTypeIsStruct(lclTyp))
14687             {
14688                 result = impAssignStructPtr(result, assg, structType, (unsigned)CHECK_SPILL_ALL);
14689             }
14690             else
14691             {
14692                 result = gtNewOperNode(GT_IND, lclTyp, result);
14693                 result->gtFlags |= (GTF_EXCEPT | GTF_GLOB_REF | GTF_IND_TGTANYWHERE);
14694                 result = gtNewAssignNode(result, assg);
14695             }
14696         }
14697     }
14698
14699     return result;
14700 }
14701
14702 /*****************************************************************************
14703  *
14704  *  Return true if the given node (excluding children trees) contains side effects.
14705  *  Note that it does not recurse, and children need to be handled separately.
14706  *  It may return false even if the node has GTF_SIDE_EFFECT (because of its children).
14707  *
14708  *  Similar to OperMayThrow() (but handles GT_CALLs specially), but considers
14709  *  assignments too.
14710  */
14711
14712 bool Compiler::gtNodeHasSideEffects(GenTree* tree, unsigned flags)
14713 {
14714     if (flags & GTF_ASG)
14715     {
14716         // TODO-Cleanup: This only checks for GT_ASG but according to OperRequiresAsgFlag there
14717         // are many more opers that are considered to have an assignment side effect: atomic ops
14718         // (GT_CMPXCHG & co.), GT_MEMORYBARRIER (not classified as an atomic op) and HW intrinsic
14719         // memory stores. Atomic ops have special handling in gtExtractSideEffList but the others
14720         // will simply be dropped is they are ever subject to an "extract side effects" operation.
14721         // It is possible that the reason no bugs have yet been observed in this area is that the
14722         // other nodes are likely to always be tree roots.
14723         if (tree->OperIs(GT_ASG))
14724         {
14725             return true;
14726         }
14727     }
14728
14729     // Are there only GTF_CALL side effects remaining? (and no other side effect kinds)
14730     if (flags & GTF_CALL)
14731     {
14732         if (tree->OperGet() == GT_CALL)
14733         {
14734             GenTreeCall* const call             = tree->AsCall();
14735             const bool         ignoreExceptions = (flags & GTF_EXCEPT) == 0;
14736             const bool         ignoreCctors     = (flags & GTF_IS_IN_CSE) != 0; // We can CSE helpers that run cctors.
14737             if (!call->HasSideEffects(this, ignoreExceptions, ignoreCctors))
14738             {
14739                 // If this call is otherwise side effect free, check its arguments.
14740                 for (GenTreeArgList* args = call->gtCallArgs; args != nullptr; args = args->Rest())
14741                 {
14742                     if (gtTreeHasSideEffects(args->Current(), flags))
14743                     {
14744                         return true;
14745                     }
14746                 }
14747                 // I'm a little worried that args that assign to temps that are late args will look like
14748                 // side effects...but better to be conservative for now.
14749                 for (GenTreeArgList* args = call->gtCallLateArgs; args != nullptr; args = args->Rest())
14750                 {
14751                     if (gtTreeHasSideEffects(args->Current(), flags))
14752                     {
14753                         return true;
14754                     }
14755                 }
14756
14757                 // Otherwise:
14758                 return false;
14759             }
14760
14761             // Otherwise the GT_CALL is considered to have side-effects.
14762             return true;
14763         }
14764     }
14765
14766     if (flags & GTF_EXCEPT)
14767     {
14768         if (tree->OperMayThrow(this))
14769         {
14770             return true;
14771         }
14772     }
14773
14774     // Expressions declared as CSE by (e.g.) hoisting code are considered to have relevant side
14775     // effects (if we care about GTF_MAKE_CSE).
14776     if ((flags & GTF_MAKE_CSE) && (tree->gtFlags & GTF_MAKE_CSE))
14777     {
14778         return true;
14779     }
14780
14781     return false;
14782 }
14783
14784 /*****************************************************************************
14785  * Returns true if the expr tree has any side effects.
14786  */
14787
14788 bool Compiler::gtTreeHasSideEffects(GenTree* tree, unsigned flags /* = GTF_SIDE_EFFECT*/)
14789 {
14790     // These are the side effect flags that we care about for this tree
14791     unsigned sideEffectFlags = tree->gtFlags & flags;
14792
14793     // Does this tree have any Side-effect flags set that we care about?
14794     if (sideEffectFlags == 0)
14795     {
14796         // no it doesn't..
14797         return false;
14798     }
14799
14800     if (sideEffectFlags == GTF_CALL)
14801     {
14802         if (tree->OperGet() == GT_CALL)
14803         {
14804             // Generally all trees that contain GT_CALL nodes are considered to have side-effects.
14805             //
14806             if (tree->gtCall.gtCallType == CT_HELPER)
14807             {
14808                 // If this node is a helper call we may not care about the side-effects.
14809                 // Note that gtNodeHasSideEffects checks the side effects of the helper itself
14810                 // as well as the side effects of its arguments.
14811                 return gtNodeHasSideEffects(tree, flags);
14812             }
14813         }
14814         else if (tree->OperGet() == GT_INTRINSIC)
14815         {
14816             if (gtNodeHasSideEffects(tree, flags))
14817             {
14818                 return true;
14819             }
14820
14821             if (gtNodeHasSideEffects(tree->gtOp.gtOp1, flags))
14822             {
14823                 return true;
14824             }
14825
14826             if ((tree->gtOp.gtOp2 != nullptr) && gtNodeHasSideEffects(tree->gtOp.gtOp2, flags))
14827             {
14828                 return true;
14829             }
14830
14831             return false;
14832         }
14833     }
14834
14835     return true;
14836 }
14837
14838 GenTree* Compiler::gtBuildCommaList(GenTree* list, GenTree* expr)
14839 {
14840     // 'list' starts off as null,
14841     //        and when it is null we haven't started the list yet.
14842     //
14843     if (list != nullptr)
14844     {
14845         // Create a GT_COMMA that appends 'expr' in front of the remaining set of expressions in (*list)
14846         GenTree* result = gtNewOperNode(GT_COMMA, TYP_VOID, expr, list);
14847
14848         // Set the flags in the comma node
14849         result->gtFlags |= (list->gtFlags & GTF_ALL_EFFECT);
14850         result->gtFlags |= (expr->gtFlags & GTF_ALL_EFFECT);
14851
14852         // 'list' and 'expr' should have valuenumbers defined for both or for neither one (unless we are remorphing,
14853         // in which case a prior transform involving either node may have discarded or otherwise invalidated the value
14854         // numbers).
14855         assert((list->gtVNPair.BothDefined() == expr->gtVNPair.BothDefined()) || !fgGlobalMorph);
14856
14857         // Set the ValueNumber 'gtVNPair' for the new GT_COMMA node
14858         //
14859         if (list->gtVNPair.BothDefined() && expr->gtVNPair.BothDefined())
14860         {
14861             // The result of a GT_COMMA node is op2, the normal value number is op2vnp
14862             // But we also need to include the union of side effects from op1 and op2.
14863             // we compute this value into exceptions_vnp.
14864             ValueNumPair op1vnp;
14865             ValueNumPair op1Xvnp = ValueNumStore::VNPForEmptyExcSet();
14866             ValueNumPair op2vnp;
14867             ValueNumPair op2Xvnp = ValueNumStore::VNPForEmptyExcSet();
14868
14869             vnStore->VNPUnpackExc(expr->gtVNPair, &op1vnp, &op1Xvnp);
14870             vnStore->VNPUnpackExc(list->gtVNPair, &op2vnp, &op2Xvnp);
14871
14872             ValueNumPair exceptions_vnp = ValueNumStore::VNPForEmptyExcSet();
14873
14874             exceptions_vnp = vnStore->VNPExcSetUnion(exceptions_vnp, op1Xvnp);
14875             exceptions_vnp = vnStore->VNPExcSetUnion(exceptions_vnp, op2Xvnp);
14876
14877             result->gtVNPair = vnStore->VNPWithExc(op2vnp, exceptions_vnp);
14878         }
14879
14880         return result;
14881     }
14882     else
14883     {
14884         // The 'expr' will start the list of expressions
14885         return expr;
14886     }
14887 }
14888
14889 //------------------------------------------------------------------------
14890 // gtExtractSideEffList: Extracts side effects from the given expression.
14891 //
14892 // Arguments:
14893 //    expr       - the expression tree to extract side effects from
14894 //    pList      - pointer to a (possibly null) GT_COMMA list that
14895 //                 will contain the extracted side effects
14896 //    flags      - side effect flags to be considered
14897 //    ignoreRoot - ignore side effects on the expression root node
14898 //
14899 // Notes:
14900 //    Side effects are prepended to the GT_COMMA list such that op1 of
14901 //    each comma node holds the side effect tree and op2 points to the
14902 //    next comma node. The original side effect execution order is preserved.
14903 //
14904 void Compiler::gtExtractSideEffList(GenTree*  expr,
14905                                     GenTree** pList,
14906                                     unsigned  flags /* = GTF_SIDE_EFFECT*/,
14907                                     bool      ignoreRoot /* = false */)
14908 {
14909     class SideEffectExtractor final : public GenTreeVisitor<SideEffectExtractor>
14910     {
14911     public:
14912         const unsigned       m_flags;
14913         ArrayStack<GenTree*> m_sideEffects;
14914
14915         enum
14916         {
14917             DoPreOrder        = true,
14918             UseExecutionOrder = true
14919         };
14920
14921         SideEffectExtractor(Compiler* compiler, unsigned flags)
14922             : GenTreeVisitor(compiler), m_flags(flags), m_sideEffects(compiler->getAllocator(CMK_SideEffects))
14923         {
14924         }
14925
14926         fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
14927         {
14928             GenTree* node = *use;
14929
14930             bool treeHasSideEffects = m_compiler->gtTreeHasSideEffects(node, m_flags);
14931
14932             if (treeHasSideEffects)
14933             {
14934                 if (m_compiler->gtNodeHasSideEffects(node, m_flags))
14935                 {
14936                     m_sideEffects.Push(node);
14937                     return Compiler::WALK_SKIP_SUBTREES;
14938                 }
14939
14940                 // TODO-Cleanup: These have GTF_ASG set but for some reason gtNodeHasSideEffects ignores
14941                 // them. See the related gtNodeHasSideEffects comment as well.
14942                 // Also, these nodes must always be preserved, no matter what side effect flags are passed
14943                 // in. But then it should never be the case that gtExtractSideEffList gets called without
14944                 // specifying GTF_ASG so there doesn't seem to be any reason to be inconsistent with
14945                 // gtNodeHasSideEffects and make this check unconditionally.
14946                 if (node->OperIsAtomicOp())
14947                 {
14948                     m_sideEffects.Push(node);
14949                     return Compiler::WALK_SKIP_SUBTREES;
14950                 }
14951
14952                 if ((m_flags & GTF_EXCEPT) != 0)
14953                 {
14954                     // Special case - GT_ADDR of GT_IND nodes of TYP_STRUCT have to be kept together.
14955                     if (node->OperIs(GT_ADDR) && node->gtGetOp1()->OperIsIndir() &&
14956                         (node->gtGetOp1()->TypeGet() == TYP_STRUCT))
14957                     {
14958 #ifdef DEBUG
14959                         if (m_compiler->verbose)
14960                         {
14961                             printf("Keep the GT_ADDR and GT_IND together:\n");
14962                         }
14963 #endif
14964                         m_sideEffects.Push(node);
14965                         return Compiler::WALK_SKIP_SUBTREES;
14966                     }
14967                 }
14968
14969                 // Generally all GT_CALL nodes are considered to have side-effects.
14970                 // So if we get here it must be a helper call that we decided it does
14971                 // not have side effects that we needed to keep.
14972                 assert(!node->OperIs(GT_CALL) || (node->AsCall()->gtCallType == CT_HELPER));
14973             }
14974
14975             if ((m_flags & GTF_IS_IN_CSE) != 0)
14976             {
14977                 // If we're doing CSE then we also need to unmark CSE nodes. This will fail for CSE defs,
14978                 // those need to be extracted as if they're side effects.
14979                 if (!UnmarkCSE(node))
14980                 {
14981                     m_sideEffects.Push(node);
14982                     return Compiler::WALK_SKIP_SUBTREES;
14983                 }
14984
14985                 // The existence of CSE defs and uses is not propagated up the tree like side
14986                 // effects are. We need to continue visiting the tree as if it has side effects.
14987                 treeHasSideEffects = true;
14988             }
14989
14990             return treeHasSideEffects ? Compiler::WALK_CONTINUE : Compiler::WALK_SKIP_SUBTREES;
14991         }
14992
14993     private:
14994         bool UnmarkCSE(GenTree* node)
14995         {
14996             assert(m_compiler->optValnumCSE_phase);
14997
14998             if (m_compiler->optUnmarkCSE(node))
14999             {
15000                 // The call to optUnmarkCSE(node) should have cleared any CSE info.
15001                 assert(!IS_CSE_INDEX(node->gtCSEnum));
15002                 return true;
15003             }
15004             else
15005             {
15006                 assert(IS_CSE_DEF(node->gtCSEnum));
15007 #ifdef DEBUG
15008                 if (m_compiler->verbose)
15009                 {
15010                     printf("Preserving the CSE def #%02d at ", GET_CSE_INDEX(node->gtCSEnum));
15011                     m_compiler->printTreeID(node);
15012                 }
15013 #endif
15014                 return false;
15015             }
15016         }
15017     };
15018
15019     assert(!expr->OperIs(GT_STMT));
15020
15021     SideEffectExtractor extractor(this, flags);
15022
15023     if (ignoreRoot)
15024     {
15025         for (GenTree* op : expr->Operands())
15026         {
15027             extractor.WalkTree(&op, nullptr);
15028         }
15029     }
15030     else
15031     {
15032         extractor.WalkTree(&expr, nullptr);
15033     }
15034
15035     GenTree* list = *pList;
15036
15037     // The extractor returns side effects in execution order but gtBuildCommaList prepends
15038     // to the comma-based side effect list so we have to build the list in reverse order.
15039     // This is also why the list cannot be built while traversing the tree.
15040     // The number of side effects is usually small (<= 4), less than the ArrayStack's
15041     // built-in size, so memory allocation is avoided.
15042     while (extractor.m_sideEffects.Height() > 0)
15043     {
15044         list = gtBuildCommaList(list, extractor.m_sideEffects.Pop());
15045     }
15046
15047     *pList = list;
15048 }
15049
15050 /*****************************************************************************
15051  *
15052  *  For debugging only - displays a tree node list and makes sure all the
15053  *  links are correctly set.
15054  */
15055
15056 #ifdef DEBUG
15057
15058 void dispNodeList(GenTree* list, bool verbose)
15059 {
15060     GenTree* last = nullptr;
15061     GenTree* next;
15062
15063     if (!list)
15064     {
15065         return;
15066     }
15067
15068     for (;;)
15069     {
15070         next = list->gtNext;
15071
15072         if (verbose)
15073         {
15074             printf("%08X -> %08X -> %08X\n", last, list, next);
15075         }
15076
15077         assert(!last || last->gtNext == list);
15078
15079         assert(next == nullptr || next->gtPrev == list);
15080
15081         if (!next)
15082         {
15083             break;
15084         }
15085
15086         last = list;
15087         list = next;
15088     }
15089     printf(""); // null string means flush
15090 }
15091
15092 /*****************************************************************************
15093  * Callback to assert that the nodes of a qmark-colon subtree are marked
15094  */
15095
15096 /* static */
15097 Compiler::fgWalkResult Compiler::gtAssertColonCond(GenTree** pTree, fgWalkData* data)
15098 {
15099     assert(data->pCallbackData == nullptr);
15100
15101     assert((*pTree)->gtFlags & GTF_COLON_COND);
15102
15103     return WALK_CONTINUE;
15104 }
15105 #endif // DEBUG
15106
15107 /*****************************************************************************
15108  * Callback to mark the nodes of a qmark-colon subtree that are conditionally
15109  * executed.
15110  */
15111
15112 /* static */
15113 Compiler::fgWalkResult Compiler::gtMarkColonCond(GenTree** pTree, fgWalkData* data)
15114 {
15115     assert(data->pCallbackData == nullptr);
15116
15117     (*pTree)->gtFlags |= GTF_COLON_COND;
15118
15119     return WALK_CONTINUE;
15120 }
15121
15122 /*****************************************************************************
15123  * Callback to clear the conditionally executed flags of nodes that no longer
15124    will be conditionally executed. Note that when we find another colon we must
15125    stop, as the nodes below this one WILL be conditionally executed. This callback
15126    is called when folding a qmark condition (ie the condition is constant).
15127  */
15128
15129 /* static */
15130 Compiler::fgWalkResult Compiler::gtClearColonCond(GenTree** pTree, fgWalkData* data)
15131 {
15132     GenTree* tree = *pTree;
15133
15134     assert(data->pCallbackData == nullptr);
15135
15136     if (tree->OperGet() == GT_COLON)
15137     {
15138         // Nodes below this will be conditionally executed.
15139         return WALK_SKIP_SUBTREES;
15140     }
15141
15142     tree->gtFlags &= ~GTF_COLON_COND;
15143     return WALK_CONTINUE;
15144 }
15145
15146 struct FindLinkData
15147 {
15148     GenTree*  nodeToFind;
15149     GenTree** result;
15150 };
15151
15152 /*****************************************************************************
15153  *
15154  *  Callback used by the tree walker to implement fgFindLink()
15155  */
15156 static Compiler::fgWalkResult gtFindLinkCB(GenTree** pTree, Compiler::fgWalkData* cbData)
15157 {
15158     FindLinkData* data = (FindLinkData*)cbData->pCallbackData;
15159     if (*pTree == data->nodeToFind)
15160     {
15161         data->result = pTree;
15162         return Compiler::WALK_ABORT;
15163     }
15164
15165     return Compiler::WALK_CONTINUE;
15166 }
15167
15168 GenTree** Compiler::gtFindLink(GenTree* stmt, GenTree* node)
15169 {
15170     assert(stmt->gtOper == GT_STMT);
15171
15172     FindLinkData data = {node, nullptr};
15173
15174     fgWalkResult result = fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, gtFindLinkCB, &data);
15175
15176     if (result == WALK_ABORT)
15177     {
15178         assert(data.nodeToFind == *data.result);
15179         return data.result;
15180     }
15181     else
15182     {
15183         return nullptr;
15184     }
15185 }
15186
15187 /*****************************************************************************
15188  *
15189  *  Callback that checks if a tree node has oper type GT_CATCH_ARG
15190  */
15191
15192 static Compiler::fgWalkResult gtFindCatchArg(GenTree** pTree, Compiler::fgWalkData* /* data */)
15193 {
15194     return ((*pTree)->OperGet() == GT_CATCH_ARG) ? Compiler::WALK_ABORT : Compiler::WALK_CONTINUE;
15195 }
15196
15197 /*****************************************************************************/
15198 bool Compiler::gtHasCatchArg(GenTree* tree)
15199 {
15200     if (((tree->gtFlags & GTF_ORDER_SIDEEFF) != 0) && (fgWalkTreePre(&tree, gtFindCatchArg) == WALK_ABORT))
15201     {
15202         return true;
15203     }
15204     return false;
15205 }
15206
15207 //------------------------------------------------------------------------
15208 // gtHasCallOnStack:
15209 //
15210 // Arguments:
15211 //    parentStack: a context (stack of parent nodes)
15212 //
15213 // Return Value:
15214 //     returns true if any of the parent nodes are a GT_CALL
15215 //
15216 // Assumptions:
15217 //    We have a stack of parent nodes. This generally requires that
15218 //    we are performing a recursive tree walk using struct fgWalkData
15219 //
15220 //------------------------------------------------------------------------
15221 /* static */ bool Compiler::gtHasCallOnStack(GenTreeStack* parentStack)
15222 {
15223     for (int i = 0; i < parentStack->Height(); i++)
15224     {
15225         GenTree* node = parentStack->Index(i);
15226         if (node->OperGet() == GT_CALL)
15227         {
15228             return true;
15229         }
15230     }
15231     return false;
15232 }
15233
15234 //------------------------------------------------------------------------
15235 // gtGetTypeProducerKind: determine if a tree produces a runtime type, and
15236 //    if so, how.
15237 //
15238 // Arguments:
15239 //    tree - tree to examine
15240 //
15241 // Return Value:
15242 //    TypeProducerKind for the tree.
15243 //
15244 // Notes:
15245 //    Checks to see if this tree returns a RuntimeType value, and if so,
15246 //    how that value is determined.
15247 //
15248 //    Currently handles these cases
15249 //    1) The result of Object::GetType
15250 //    2) The result of typeof(...)
15251 //    3) A null reference
15252 //    4) Tree is otherwise known to have type RuntimeType
15253 //
15254 //    The null reference case is surprisingly common because operator
15255 //    overloading turns the otherwise innocuous
15256 //
15257 //        Type t = ....;
15258 //        if (t == null)
15259 //
15260 //    into a method call.
15261
15262 Compiler::TypeProducerKind Compiler::gtGetTypeProducerKind(GenTree* tree)
15263 {
15264     if (tree->gtOper == GT_CALL)
15265     {
15266         if (tree->gtCall.gtCallType == CT_HELPER)
15267         {
15268             if (gtIsTypeHandleToRuntimeTypeHelper(tree->AsCall()))
15269             {
15270                 return TPK_Handle;
15271             }
15272         }
15273         else if (tree->gtCall.gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC)
15274         {
15275             if (info.compCompHnd->getIntrinsicID(tree->gtCall.gtCallMethHnd) == CORINFO_INTRINSIC_Object_GetType)
15276             {
15277                 return TPK_GetType;
15278             }
15279         }
15280     }
15281     else if ((tree->gtOper == GT_INTRINSIC) && (tree->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType))
15282     {
15283         return TPK_GetType;
15284     }
15285     else if ((tree->gtOper == GT_CNS_INT) && (tree->gtIntCon.gtIconVal == 0))
15286     {
15287         return TPK_Null;
15288     }
15289     else
15290     {
15291         bool                 isExact   = false;
15292         bool                 isNonNull = false;
15293         CORINFO_CLASS_HANDLE clsHnd    = gtGetClassHandle(tree, &isExact, &isNonNull);
15294
15295         if (clsHnd != NO_CLASS_HANDLE && clsHnd == info.compCompHnd->getBuiltinClass(CLASSID_RUNTIME_TYPE))
15296         {
15297             return TPK_Other;
15298         }
15299     }
15300     return TPK_Unknown;
15301 }
15302
15303 //------------------------------------------------------------------------
15304 // gtIsTypeHandleToRuntimeTypeHelperCall -- see if tree is constructing
15305 //    a RuntimeType from a handle
15306 //
15307 // Arguments:
15308 //    tree - tree to examine
15309 //
15310 // Return Value:
15311 //    True if so
15312
15313 bool Compiler::gtIsTypeHandleToRuntimeTypeHelper(GenTreeCall* call)
15314 {
15315     return call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE) ||
15316            call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL);
15317 }
15318
15319 //------------------------------------------------------------------------
15320 // gtIsTypeHandleToRuntimeTypeHandleHelperCall -- see if tree is constructing
15321 //    a RuntimeTypeHandle from a handle
15322 //
15323 // Arguments:
15324 //    tree - tree to examine
15325 //    pHelper - optional pointer to a variable that receives the type of the helper
15326 //
15327 // Return Value:
15328 //    True if so
15329
15330 bool Compiler::gtIsTypeHandleToRuntimeTypeHandleHelper(GenTreeCall* call, CorInfoHelpFunc* pHelper)
15331 {
15332     CorInfoHelpFunc helper = CORINFO_HELP_UNDEF;
15333
15334     if (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE))
15335     {
15336         helper = CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE;
15337     }
15338     else if (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL))
15339     {
15340         helper = CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL;
15341     }
15342
15343     if (pHelper != nullptr)
15344     {
15345         *pHelper = helper;
15346     }
15347
15348     return helper != CORINFO_HELP_UNDEF;
15349 }
15350
15351 bool Compiler::gtIsActiveCSE_Candidate(GenTree* tree)
15352 {
15353     return (optValnumCSE_phase && IS_CSE_INDEX(tree->gtCSEnum));
15354 }
15355
15356 /*****************************************************************************/
15357
15358 struct ComplexityStruct
15359 {
15360     unsigned m_numNodes;
15361     unsigned m_nodeLimit;
15362     ComplexityStruct(unsigned nodeLimit) : m_numNodes(0), m_nodeLimit(nodeLimit)
15363     {
15364     }
15365 };
15366
15367 static Compiler::fgWalkResult ComplexityExceedsWalker(GenTree** pTree, Compiler::fgWalkData* data)
15368 {
15369     ComplexityStruct* pComplexity = (ComplexityStruct*)data->pCallbackData;
15370     if (++pComplexity->m_numNodes > pComplexity->m_nodeLimit)
15371     {
15372         return Compiler::WALK_ABORT;
15373     }
15374     else
15375     {
15376         return Compiler::WALK_CONTINUE;
15377     }
15378 }
15379
15380 bool Compiler::gtComplexityExceeds(GenTree** tree, unsigned limit)
15381 {
15382     ComplexityStruct complexity(limit);
15383     if (fgWalkTreePre(tree, &ComplexityExceedsWalker, &complexity) == WALK_ABORT)
15384     {
15385         return true;
15386     }
15387     else
15388     {
15389         return false;
15390     }
15391 }
15392
15393 bool GenTree::IsPhiNode()
15394 {
15395     return (OperGet() == GT_PHI_ARG) || (OperGet() == GT_PHI) || IsPhiDefn();
15396 }
15397
15398 bool GenTree::IsPhiDefn()
15399 {
15400     bool res = ((OperGet() == GT_ASG) && (gtOp.gtOp2 != nullptr) && (gtOp.gtOp2->OperGet() == GT_PHI)) ||
15401                ((OperGet() == GT_STORE_LCL_VAR) && (gtOp.gtOp1 != nullptr) && (gtOp.gtOp1->OperGet() == GT_PHI));
15402     assert(!res || OperGet() == GT_STORE_LCL_VAR || gtOp.gtOp1->OperGet() == GT_LCL_VAR);
15403     return res;
15404 }
15405
15406 bool GenTree::IsPhiDefnStmt()
15407 {
15408     if (OperGet() != GT_STMT)
15409     {
15410         return false;
15411     }
15412     GenTree* asg = gtStmt.gtStmtExpr;
15413     return asg->IsPhiDefn();
15414 }
15415
15416 // IsPartialLclFld: Check for a GT_LCL_FLD whose type is a different size than the lclVar.
15417 //
15418 // Arguments:
15419 //    comp      - the Compiler object.
15420 //
15421 // Return Value:
15422 //    Returns "true" iff 'this' is a GT_LCL_FLD or GT_STORE_LCL_FLD on which the type
15423 //    is not the same size as the type of the GT_LCL_VAR
15424
15425 bool GenTree::IsPartialLclFld(Compiler* comp)
15426 {
15427     return ((gtOper == GT_LCL_FLD) &&
15428             (comp->lvaTable[this->gtLclVarCommon.gtLclNum].lvExactSize != genTypeSize(gtType)));
15429 }
15430
15431 bool GenTree::DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire)
15432 {
15433     GenTreeBlk* blkNode = nullptr;
15434     if (OperIs(GT_ASG))
15435     {
15436         if (gtOp.gtOp1->IsLocal())
15437         {
15438             GenTreeLclVarCommon* lclVarTree = gtOp.gtOp1->AsLclVarCommon();
15439             *pLclVarTree                    = lclVarTree;
15440             if (pIsEntire != nullptr)
15441             {
15442                 if (lclVarTree->IsPartialLclFld(comp))
15443                 {
15444                     *pIsEntire = false;
15445                 }
15446                 else
15447                 {
15448                     *pIsEntire = true;
15449                 }
15450             }
15451             return true;
15452         }
15453         else if (gtOp.gtOp1->OperGet() == GT_IND)
15454         {
15455             GenTree* indArg = gtOp.gtOp1->gtOp.gtOp1;
15456             return indArg->DefinesLocalAddr(comp, genTypeSize(gtOp.gtOp1->TypeGet()), pLclVarTree, pIsEntire);
15457         }
15458         else if (gtOp.gtOp1->OperIsBlk())
15459         {
15460             blkNode = gtOp.gtOp1->AsBlk();
15461         }
15462     }
15463     else if (OperIsBlk())
15464     {
15465         blkNode = this->AsBlk();
15466     }
15467     if (blkNode != nullptr)
15468     {
15469         GenTree* destAddr = blkNode->Addr();
15470         unsigned width    = blkNode->gtBlkSize;
15471         // Do we care about whether this assigns the entire variable?
15472         if (pIsEntire != nullptr && width == 0)
15473         {
15474             assert(blkNode->gtOper == GT_DYN_BLK);
15475             GenTree* blockWidth = blkNode->AsDynBlk()->gtDynamicSize;
15476             if (blockWidth->IsCnsIntOrI())
15477             {
15478                 if (blockWidth->IsIconHandle())
15479                 {
15480                     // If it's a handle, it must be a class handle.  We only create such block operations
15481                     // for initialization of struct types, so the type of the argument(s) will match this
15482                     // type, by construction, and be "entire".
15483                     assert(blockWidth->IsIconHandle(GTF_ICON_CLASS_HDL));
15484                     width = comp->info.compCompHnd->getClassSize(
15485                         CORINFO_CLASS_HANDLE(blockWidth->gtIntConCommon.IconValue()));
15486                 }
15487                 else
15488                 {
15489                     ssize_t swidth = blockWidth->AsIntConCommon()->IconValue();
15490                     assert(swidth >= 0);
15491                     // cpblk of size zero exists in the wild (in yacc-generated code in SQL) and is valid IL.
15492                     if (swidth == 0)
15493                     {
15494                         return false;
15495                     }
15496                     width = unsigned(swidth);
15497                 }
15498             }
15499         }
15500         return destAddr->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire);
15501     }
15502     // Otherwise...
15503     return false;
15504 }
15505
15506 // Returns true if this GenTree defines a result which is based on the address of a local.
15507 bool GenTree::DefinesLocalAddr(Compiler* comp, unsigned width, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire)
15508 {
15509     if (OperGet() == GT_ADDR || OperGet() == GT_LCL_VAR_ADDR)
15510     {
15511         GenTree* addrArg = this;
15512         if (OperGet() == GT_ADDR)
15513         {
15514             addrArg = gtOp.gtOp1;
15515         }
15516
15517         if (addrArg->IsLocal() || addrArg->OperIsLocalAddr())
15518         {
15519             GenTreeLclVarCommon* addrArgLcl = addrArg->AsLclVarCommon();
15520             *pLclVarTree                    = addrArgLcl;
15521             if (pIsEntire != nullptr)
15522             {
15523                 unsigned lclOffset = 0;
15524                 if (addrArg->OperIsLocalField())
15525                 {
15526                     lclOffset = addrArg->gtLclFld.gtLclOffs;
15527                 }
15528
15529                 if (lclOffset != 0)
15530                 {
15531                     // We aren't updating the bytes at [0..lclOffset-1] so *pIsEntire should be set to false
15532                     *pIsEntire = false;
15533                 }
15534                 else
15535                 {
15536                     unsigned lclNum   = addrArgLcl->GetLclNum();
15537                     unsigned varWidth = comp->lvaLclExactSize(lclNum);
15538                     if (comp->lvaTable[lclNum].lvNormalizeOnStore())
15539                     {
15540                         // It's normalize on store, so use the full storage width -- writing to low bytes won't
15541                         // necessarily yield a normalized value.
15542                         varWidth = genTypeStSz(var_types(comp->lvaTable[lclNum].lvType)) * sizeof(int);
15543                     }
15544                     *pIsEntire = (varWidth == width);
15545                 }
15546             }
15547             return true;
15548         }
15549         else if (addrArg->OperGet() == GT_IND)
15550         {
15551             // A GT_ADDR of a GT_IND can both be optimized away, recurse using the child of the GT_IND
15552             return addrArg->gtOp.gtOp1->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire);
15553         }
15554     }
15555     else if (OperGet() == GT_ADD)
15556     {
15557         if (gtOp.gtOp1->IsCnsIntOrI())
15558         {
15559             // If we just adding a zero then we allow an IsEntire match against width
15560             //  otherwise we change width to zero to disallow an IsEntire Match
15561             return gtOp.gtOp2->DefinesLocalAddr(comp, gtOp.gtOp1->IsIntegralConst(0) ? width : 0, pLclVarTree,
15562                                                 pIsEntire);
15563         }
15564         else if (gtOp.gtOp2->IsCnsIntOrI())
15565         {
15566             // If we just adding a zero then we allow an IsEntire match against width
15567             //  otherwise we change width to zero to disallow an IsEntire Match
15568             return gtOp.gtOp1->DefinesLocalAddr(comp, gtOp.gtOp2->IsIntegralConst(0) ? width : 0, pLclVarTree,
15569                                                 pIsEntire);
15570         }
15571     }
15572     // Post rationalization we could have GT_IND(GT_LEA(..)) trees.
15573     else if (OperGet() == GT_LEA)
15574     {
15575         // This method gets invoked during liveness computation and therefore it is critical
15576         // that we don't miss 'use' of any local.  The below logic is making the assumption
15577         // that in case of LEA(base, index, offset) - only base can be a GT_LCL_VAR_ADDR
15578         // and index is not.
15579         CLANG_FORMAT_COMMENT_ANCHOR;
15580
15581 #ifdef DEBUG
15582         GenTree* index = gtOp.gtOp2;
15583         if (index != nullptr)
15584         {
15585             assert(!index->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire));
15586         }
15587 #endif // DEBUG
15588
15589         // base
15590         GenTree* base = gtOp.gtOp1;
15591         if (base != nullptr)
15592         {
15593             // Lea could have an Indir as its base.
15594             if (base->OperGet() == GT_IND)
15595             {
15596                 base = base->gtOp.gtOp1->gtEffectiveVal(/*commas only*/ true);
15597             }
15598             return base->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire);
15599         }
15600     }
15601     // Otherwise...
15602     return false;
15603 }
15604
15605 //------------------------------------------------------------------------
15606 // IsLocalExpr: Determine if this is a LclVarCommon node and return some
15607 //              additional info about it in the two out parameters.
15608 //
15609 // Arguments:
15610 //    comp        - The Compiler instance
15611 //    pLclVarTree - An "out" argument that returns the local tree as a
15612 //                  LclVarCommon, if it is indeed local.
15613 //    pFldSeq     - An "out" argument that returns the value numbering field
15614 //                  sequence for the node, if any.
15615 //
15616 // Return Value:
15617 //    Returns true, and sets the out arguments accordingly, if this is
15618 //    a LclVarCommon node.
15619
15620 bool GenTree::IsLocalExpr(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, FieldSeqNode** pFldSeq)
15621 {
15622     if (IsLocal()) // Note that this covers "GT_LCL_FLD."
15623     {
15624         *pLclVarTree = AsLclVarCommon();
15625         if (OperGet() == GT_LCL_FLD)
15626         {
15627             // Otherwise, prepend this field to whatever we've already accumulated outside in.
15628             *pFldSeq = comp->GetFieldSeqStore()->Append(AsLclFld()->gtFieldSeq, *pFldSeq);
15629         }
15630         return true;
15631     }
15632     else
15633     {
15634         return false;
15635     }
15636 }
15637
15638 // If this tree evaluates some sum of a local address and some constants,
15639 // return the node for the local being addressed
15640
15641 GenTreeLclVarCommon* GenTree::IsLocalAddrExpr()
15642 {
15643     if (OperGet() == GT_ADDR)
15644     {
15645         return gtOp.gtOp1->IsLocal() ? gtOp.gtOp1->AsLclVarCommon() : nullptr;
15646     }
15647     else if (OperIsLocalAddr())
15648     {
15649         return this->AsLclVarCommon();
15650     }
15651     else if (OperGet() == GT_ADD)
15652     {
15653         if (gtOp.gtOp1->OperGet() == GT_CNS_INT)
15654         {
15655             return gtOp.gtOp2->IsLocalAddrExpr();
15656         }
15657         else if (gtOp.gtOp2->OperGet() == GT_CNS_INT)
15658         {
15659             return gtOp.gtOp1->IsLocalAddrExpr();
15660         }
15661     }
15662     // Otherwise...
15663     return nullptr;
15664 }
15665
15666 bool GenTree::IsLocalAddrExpr(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, FieldSeqNode** pFldSeq)
15667 {
15668     if (OperGet() == GT_ADDR)
15669     {
15670         assert(!comp->compRationalIRForm);
15671         GenTree* addrArg = gtOp.gtOp1;
15672         if (addrArg->IsLocal()) // Note that this covers "GT_LCL_FLD."
15673         {
15674             *pLclVarTree = addrArg->AsLclVarCommon();
15675             if (addrArg->OperGet() == GT_LCL_FLD)
15676             {
15677                 // Otherwise, prepend this field to whatever we've already accumulated outside in.
15678                 *pFldSeq = comp->GetFieldSeqStore()->Append(addrArg->AsLclFld()->gtFieldSeq, *pFldSeq);
15679             }
15680             return true;
15681         }
15682         else
15683         {
15684             return false;
15685         }
15686     }
15687     else if (OperIsLocalAddr())
15688     {
15689         *pLclVarTree = this->AsLclVarCommon();
15690         if (this->OperGet() == GT_LCL_FLD_ADDR)
15691         {
15692             *pFldSeq = comp->GetFieldSeqStore()->Append(this->AsLclFld()->gtFieldSeq, *pFldSeq);
15693         }
15694         return true;
15695     }
15696     else if (OperGet() == GT_ADD)
15697     {
15698         if (gtOp.gtOp1->OperGet() == GT_CNS_INT)
15699         {
15700             if (gtOp.gtOp1->AsIntCon()->gtFieldSeq == nullptr)
15701             {
15702                 return false;
15703             }
15704             // Otherwise, prepend this field to whatever we've already accumulated outside in.
15705             *pFldSeq = comp->GetFieldSeqStore()->Append(gtOp.gtOp1->AsIntCon()->gtFieldSeq, *pFldSeq);
15706             return gtOp.gtOp2->IsLocalAddrExpr(comp, pLclVarTree, pFldSeq);
15707         }
15708         else if (gtOp.gtOp2->OperGet() == GT_CNS_INT)
15709         {
15710             if (gtOp.gtOp2->AsIntCon()->gtFieldSeq == nullptr)
15711             {
15712                 return false;
15713             }
15714             // Otherwise, prepend this field to whatever we've already accumulated outside in.
15715             *pFldSeq = comp->GetFieldSeqStore()->Append(gtOp.gtOp2->AsIntCon()->gtFieldSeq, *pFldSeq);
15716             return gtOp.gtOp1->IsLocalAddrExpr(comp, pLclVarTree, pFldSeq);
15717         }
15718     }
15719     // Otherwise...
15720     return false;
15721 }
15722
15723 //------------------------------------------------------------------------
15724 // IsLclVarUpdateTree: Determine whether this is an assignment tree of the
15725 //                     form Vn = Vn 'oper' 'otherTree' where Vn is a lclVar
15726 //
15727 // Arguments:
15728 //    pOtherTree - An "out" argument in which 'otherTree' will be returned.
15729 //    pOper      - An "out" argument in which 'oper' will be returned.
15730 //
15731 // Return Value:
15732 //    If the tree is of the above form, the lclNum of the variable being
15733 //    updated is returned, and 'pOtherTree' and 'pOper' are set.
15734 //    Otherwise, returns BAD_VAR_NUM.
15735 //
15736 // Notes:
15737 //    'otherTree' can have any shape.
15738 //     We avoid worrying about whether the op is commutative by only considering the
15739 //     first operand of the rhs. It is expected that most trees of this form will
15740 //     already have the lclVar on the lhs.
15741 //     TODO-CQ: Evaluate whether there are missed opportunities due to this, or
15742 //     whether gtSetEvalOrder will already have put the lclVar on the lhs in
15743 //     the cases of interest.
15744
15745 unsigned GenTree::IsLclVarUpdateTree(GenTree** pOtherTree, genTreeOps* pOper)
15746 {
15747     unsigned lclNum = BAD_VAR_NUM;
15748     if (OperIs(GT_ASG))
15749     {
15750         GenTree* lhs = gtOp.gtOp1;
15751         if (lhs->OperGet() == GT_LCL_VAR)
15752         {
15753             unsigned lhsLclNum = lhs->AsLclVarCommon()->gtLclNum;
15754             GenTree* rhs       = gtOp.gtOp2;
15755             if (rhs->OperIsBinary() && (rhs->gtOp.gtOp1->gtOper == GT_LCL_VAR) &&
15756                 (rhs->gtOp.gtOp1->AsLclVarCommon()->gtLclNum == lhsLclNum))
15757             {
15758                 lclNum      = lhsLclNum;
15759                 *pOtherTree = rhs->gtOp.gtOp2;
15760                 *pOper      = rhs->gtOper;
15761             }
15762         }
15763     }
15764     return lclNum;
15765 }
15766
15767 //------------------------------------------------------------------------
15768 // canBeContained: check whether this tree node may be a subcomponent of its parent for purposes
15769 //                 of code generation.
15770 //
15771 // Return value: returns true if it is possible to contain this node and false otherwise.
15772 bool GenTree::canBeContained() const
15773 {
15774     assert(IsLIR());
15775
15776     if (gtHasReg())
15777     {
15778         return false;
15779     }
15780
15781     // It is not possible for nodes that do not produce values or that are not containable values
15782     // to be contained.
15783     if (((OperKind() & (GTK_NOVALUE | GTK_NOCONTAIN)) != 0) || (OperIsHWIntrinsic() && !isContainableHWIntrinsic()))
15784     {
15785         return false;
15786     }
15787
15788     return true;
15789 }
15790
15791 //------------------------------------------------------------------------
15792 // isContained: check whether this tree node is a subcomponent of its parent for codegen purposes
15793 //
15794 // Return Value:
15795 //    Returns true if there is no code generated explicitly for this node.
15796 //    Essentially, it will be rolled into the code generation for the parent.
15797 //
15798 // Assumptions:
15799 //    This method relies upon the value of the GTF_CONTAINED flag.
15800 //    Therefore this method is only valid after Lowering.
15801 //    Also note that register allocation or other subsequent phases may cause
15802 //    nodes to become contained (or not) and therefore this property may change.
15803 //
15804 bool GenTree::isContained() const
15805 {
15806     assert(IsLIR());
15807     const bool isMarkedContained = ((gtFlags & GTF_CONTAINED) != 0);
15808
15809 #ifdef DEBUG
15810     if (!canBeContained())
15811     {
15812         assert(!isMarkedContained);
15813     }
15814
15815     // these actually produce a register (the flags reg, we just don't model it)
15816     // and are a separate instruction from the branch that consumes the result.
15817     // They can only produce a result if the child is a SIMD equality comparison.
15818     else if (OperKind() & GTK_RELOP)
15819     {
15820         // We have to cast away const-ness since AsOp() method is non-const.
15821         GenTree* childNode = const_cast<GenTree*>(this)->AsOp()->gtOp1;
15822         assert((isMarkedContained == false) || childNode->IsSIMDEqualityOrInequality());
15823     }
15824
15825     // these either produce a result in register or set flags reg.
15826     else if (IsSIMDEqualityOrInequality())
15827     {
15828         assert(!isMarkedContained);
15829     }
15830
15831     // if it's contained it can't be unused.
15832     if (isMarkedContained)
15833     {
15834         assert(!IsUnusedValue());
15835     }
15836 #endif // DEBUG
15837     return isMarkedContained;
15838 }
15839
15840 // return true if node is contained and an indir
15841 bool GenTree::isContainedIndir() const
15842 {
15843     return isIndir() && isContained();
15844 }
15845
15846 bool GenTree::isIndirAddrMode()
15847 {
15848     return isIndir() && AsIndir()->Addr()->OperIsAddrMode() && AsIndir()->Addr()->isContained();
15849 }
15850
15851 bool GenTree::isIndir() const
15852 {
15853     return OperGet() == GT_IND || OperGet() == GT_STOREIND;
15854 }
15855
15856 bool GenTreeIndir::HasBase()
15857 {
15858     return Base() != nullptr;
15859 }
15860
15861 bool GenTreeIndir::HasIndex()
15862 {
15863     return Index() != nullptr;
15864 }
15865
15866 GenTree* GenTreeIndir::Base()
15867 {
15868     GenTree* addr = Addr();
15869
15870     if (isIndirAddrMode())
15871     {
15872         GenTree* result = addr->AsAddrMode()->Base();
15873         if (result != nullptr)
15874         {
15875             result = result->gtEffectiveVal();
15876         }
15877         return result;
15878     }
15879     else
15880     {
15881         return addr; // TODO: why do we return 'addr' here, but we return 'nullptr' in the equivalent Index() case?
15882     }
15883 }
15884
15885 GenTree* GenTreeIndir::Index()
15886 {
15887     if (isIndirAddrMode())
15888     {
15889         GenTree* result = Addr()->AsAddrMode()->Index();
15890         if (result != nullptr)
15891         {
15892             result = result->gtEffectiveVal();
15893         }
15894         return result;
15895     }
15896     else
15897     {
15898         return nullptr;
15899     }
15900 }
15901
15902 unsigned GenTreeIndir::Scale()
15903 {
15904     if (HasIndex())
15905     {
15906         return Addr()->AsAddrMode()->gtScale;
15907     }
15908     else
15909     {
15910         return 1;
15911     }
15912 }
15913
15914 ssize_t GenTreeIndir::Offset()
15915 {
15916     if (isIndirAddrMode())
15917     {
15918         return Addr()->AsAddrMode()->Offset();
15919     }
15920     else if (Addr()->gtOper == GT_CLS_VAR_ADDR)
15921     {
15922         return static_cast<ssize_t>(reinterpret_cast<intptr_t>(Addr()->gtClsVar.gtClsVarHnd));
15923     }
15924     else if (Addr()->IsCnsIntOrI() && Addr()->isContained())
15925     {
15926         return Addr()->AsIntConCommon()->IconValue();
15927     }
15928     else
15929     {
15930         return 0;
15931     }
15932 }
15933
15934 //------------------------------------------------------------------------
15935 // GenTreeIntConCommon::ImmedValNeedsReloc: does this immediate value needs recording a relocation with the VM?
15936 //
15937 // Arguments:
15938 //    comp - Compiler instance
15939 //
15940 // Return Value:
15941 //    True if this immediate value requires us to record a relocation for it; false otherwise.
15942
15943 bool GenTreeIntConCommon::ImmedValNeedsReloc(Compiler* comp)
15944 {
15945     return comp->opts.compReloc && (gtOper == GT_CNS_INT) && IsIconHandle();
15946 }
15947
15948 //------------------------------------------------------------------------
15949 // ImmedValCanBeFolded: can this immediate value be folded for op?
15950 //
15951 // Arguments:
15952 //    comp - Compiler instance
15953 //    op - Tree operator
15954 //
15955 // Return Value:
15956 //    True if this immediate value can be folded for op; false otherwise.
15957
15958 bool GenTreeIntConCommon::ImmedValCanBeFolded(Compiler* comp, genTreeOps op)
15959 {
15960     // In general, immediate values that need relocations can't be folded.
15961     // There are cases where we do want to allow folding of handle comparisons
15962     // (e.g., typeof(T) == typeof(int)).
15963     return !ImmedValNeedsReloc(comp) || (op == GT_EQ) || (op == GT_NE);
15964 }
15965
15966 #ifdef _TARGET_AMD64_
15967 // Returns true if this absolute address fits within the base of an addr mode.
15968 // On Amd64 this effectively means, whether an absolute indirect address can
15969 // be encoded as 32-bit offset relative to IP or zero.
15970 bool GenTreeIntConCommon::FitsInAddrBase(Compiler* comp)
15971 {
15972 #ifdef DEBUG
15973     // Early out if PC-rel encoding of absolute addr is disabled.
15974     if (!comp->opts.compEnablePCRelAddr)
15975     {
15976         return false;
15977     }
15978 #endif
15979
15980     if (comp->opts.compReloc)
15981     {
15982         // During Ngen JIT is always asked to generate relocatable code.
15983         // Hence JIT will try to encode only icon handles as pc-relative offsets.
15984         return IsIconHandle() && (IMAGE_REL_BASED_REL32 == comp->eeGetRelocTypeHint((void*)IconValue()));
15985     }
15986     else
15987     {
15988         // During Jitting, we are allowed to generate non-relocatable code.
15989         // On Amd64 we can encode an absolute indirect addr as an offset relative to zero or RIP.
15990         // An absolute indir addr that can fit within 32-bits can ben encoded as an offset relative
15991         // to zero. All other absolute indir addr could be attempted to be encoded as RIP relative
15992         // based on reloc hint provided by VM.  RIP relative encoding is preferred over relative
15993         // to zero, because the former is one byte smaller than the latter.  For this reason
15994         // we check for reloc hint first and then whether addr fits in 32-bits next.
15995         //
15996         // VM starts off with an initial state to allow both data and code address to be encoded as
15997         // pc-relative offsets.  Hence JIT will attempt to encode all absolute addresses as pc-relative
15998         // offsets.  It is possible while jitting a method, an address could not be encoded as a
15999         // pc-relative offset.  In that case VM will note the overflow and will trigger re-jitting
16000         // of the method with reloc hints turned off for all future methods. Second time around
16001         // jitting will succeed since JIT will not attempt to encode data addresses as pc-relative
16002         // offsets.  Note that JIT will always attempt to relocate code addresses (.e.g call addr).
16003         // After an overflow, VM will assume any relocation recorded is for a code address and will
16004         // emit jump thunk if it cannot be encoded as pc-relative offset.
16005         return (IMAGE_REL_BASED_REL32 == comp->eeGetRelocTypeHint((void*)IconValue())) || FitsInI32();
16006     }
16007 }
16008
16009 // Returns true if this icon value is encoded as addr needs recording a relocation with VM
16010 bool GenTreeIntConCommon::AddrNeedsReloc(Compiler* comp)
16011 {
16012     if (comp->opts.compReloc)
16013     {
16014         // During Ngen JIT is always asked to generate relocatable code.
16015         // Hence JIT will try to encode only icon handles as pc-relative offsets.
16016         return IsIconHandle() && (IMAGE_REL_BASED_REL32 == comp->eeGetRelocTypeHint((void*)IconValue()));
16017     }
16018     else
16019     {
16020         return IMAGE_REL_BASED_REL32 == comp->eeGetRelocTypeHint((void*)IconValue());
16021     }
16022 }
16023
16024 #elif defined(_TARGET_X86_)
16025 // Returns true if this absolute address fits within the base of an addr mode.
16026 // On x86 all addresses are 4-bytes and can be directly encoded in an addr mode.
16027 bool GenTreeIntConCommon::FitsInAddrBase(Compiler* comp)
16028 {
16029 #ifdef DEBUG
16030     // Early out if PC-rel encoding of absolute addr is disabled.
16031     if (!comp->opts.compEnablePCRelAddr)
16032     {
16033         return false;
16034     }
16035 #endif
16036
16037     return IsCnsIntOrI();
16038 }
16039
16040 // Returns true if this icon value is encoded as addr needs recording a relocation with VM
16041 bool GenTreeIntConCommon::AddrNeedsReloc(Compiler* comp)
16042 {
16043     // If generating relocatable code, icons should be reported for recording relocatons.
16044     return comp->opts.compReloc && IsIconHandle();
16045 }
16046 #endif //_TARGET_X86_
16047
16048 bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, FieldSeqNode** pFldSeq)
16049 {
16050     FieldSeqNode* newFldSeq    = nullptr;
16051     GenTree*      baseAddr     = nullptr;
16052     bool          mustBeStatic = false;
16053
16054     FieldSeqNode* statStructFldSeq = nullptr;
16055     if (TypeGet() == TYP_REF)
16056     {
16057         // Recognize struct static field patterns...
16058         if (OperGet() == GT_IND)
16059         {
16060             GenTree*       addr = gtOp.gtOp1;
16061             GenTreeIntCon* icon = nullptr;
16062             if (addr->OperGet() == GT_CNS_INT)
16063             {
16064                 icon = addr->AsIntCon();
16065             }
16066             else if (addr->OperGet() == GT_ADD)
16067             {
16068                 // op1 should never be a field sequence (or any other kind of handle)
16069                 assert((addr->gtOp.gtOp1->gtOper != GT_CNS_INT) || !addr->gtOp.gtOp1->IsIconHandle());
16070                 if (addr->gtOp.gtOp2->OperGet() == GT_CNS_INT)
16071                 {
16072                     icon = addr->gtOp.gtOp2->AsIntCon();
16073                 }
16074             }
16075             if (icon != nullptr && !icon->IsIconHandle(GTF_ICON_STR_HDL) // String handles are a source of TYP_REFs.
16076                 && icon->gtFieldSeq != nullptr &&
16077                 icon->gtFieldSeq->m_next == nullptr // A static field should be a singleton
16078                 // TODO-Review: A pseudoField here indicates an issue - this requires investigation
16079                 // See test case src\ddsuites\src\clr\x86\CoreMangLib\Dev\Globalization\CalendarRegressions.exe
16080                 && !(FieldSeqStore::IsPseudoField(icon->gtFieldSeq->m_fieldHnd)) &&
16081                 icon->gtFieldSeq != FieldSeqStore::NotAField()) // Ignore non-fields.
16082             {
16083                 statStructFldSeq = icon->gtFieldSeq;
16084             }
16085             else
16086             {
16087                 addr = addr->gtEffectiveVal();
16088
16089                 // Perhaps it's a direct indirection of a helper call or a cse with a zero offset annotation.
16090                 if ((addr->OperGet() == GT_CALL) || (addr->OperGet() == GT_LCL_VAR))
16091                 {
16092                     FieldSeqNode* zeroFieldSeq = nullptr;
16093                     if (comp->GetZeroOffsetFieldMap()->Lookup(addr, &zeroFieldSeq))
16094                     {
16095                         if (zeroFieldSeq->m_next == nullptr)
16096                         {
16097                             statStructFldSeq = zeroFieldSeq;
16098                         }
16099                     }
16100                 }
16101             }
16102         }
16103         else if (OperGet() == GT_CLS_VAR)
16104         {
16105             GenTreeClsVar* clsVar = AsClsVar();
16106             if (clsVar->gtFieldSeq != nullptr && clsVar->gtFieldSeq->m_next == nullptr)
16107             {
16108                 statStructFldSeq = clsVar->gtFieldSeq;
16109             }
16110         }
16111         else if (OperIsLocal())
16112         {
16113             // If we have a GT_LCL_VAR, it can be result of a CSE substitution
16114             // If it is then the CSE assignment will have a ValueNum that
16115             // describes the RHS of the CSE assignment.
16116             //
16117             // The CSE could be a pointer to a boxed struct
16118             //
16119             GenTreeLclVarCommon* lclVar = AsLclVarCommon();
16120             ValueNum             vn     = gtVNPair.GetLiberal();
16121             if (vn != ValueNumStore::NoVN)
16122             {
16123                 // Is the ValueNum a MapSelect involving a SharedStatic helper?
16124                 VNFuncApp funcApp1;
16125                 if (comp->vnStore->GetVNFunc(vn, &funcApp1) && (funcApp1.m_func == VNF_MapSelect) &&
16126                     (comp->vnStore->IsSharedStatic(funcApp1.m_args[1])))
16127                 {
16128                     ValueNum mapVN = funcApp1.m_args[0];
16129                     // Is this new 'mapVN' ValueNum, a MapSelect involving a handle?
16130                     VNFuncApp funcApp2;
16131                     if (comp->vnStore->GetVNFunc(mapVN, &funcApp2) && (funcApp2.m_func == VNF_MapSelect) &&
16132                         (comp->vnStore->IsVNHandle(funcApp2.m_args[1])))
16133                     {
16134                         ValueNum fldHndVN = funcApp2.m_args[1];
16135                         // Is this new 'fldHndVN' VNhandle a FieldHandle?
16136                         unsigned flags = comp->vnStore->GetHandleFlags(fldHndVN);
16137                         if (flags == GTF_ICON_FIELD_HDL)
16138                         {
16139                             CORINFO_FIELD_HANDLE fieldHnd =
16140                                 CORINFO_FIELD_HANDLE(comp->vnStore->ConstantValue<ssize_t>(fldHndVN));
16141
16142                             // Record this field sequence in 'statStructFldSeq' as it is likely to be a Boxed Struct
16143                             // field access.
16144                             statStructFldSeq = comp->GetFieldSeqStore()->CreateSingleton(fieldHnd);
16145                         }
16146                     }
16147                 }
16148             }
16149         }
16150
16151         if (statStructFldSeq != nullptr)
16152         {
16153             assert(statStructFldSeq->m_next == nullptr);
16154             // Is this a pointer to a boxed struct?
16155             if (comp->gtIsStaticFieldPtrToBoxedStruct(TYP_REF, statStructFldSeq->m_fieldHnd))
16156             {
16157                 *pFldSeq = comp->GetFieldSeqStore()->Append(statStructFldSeq, *pFldSeq);
16158                 *pObj    = nullptr;
16159                 *pStatic = this;
16160                 return true;
16161             }
16162         }
16163
16164         // Otherwise...
16165         *pObj    = this;
16166         *pStatic = nullptr;
16167         return true;
16168     }
16169     else if (OperGet() == GT_ADD)
16170     {
16171         // If one operator is a field sequence/handle, the other operator must not also be a field sequence/handle.
16172         if ((gtOp.gtOp1->OperGet() == GT_CNS_INT) && gtOp.gtOp1->IsIconHandle())
16173         {
16174             assert((gtOp.gtOp2->gtOper != GT_CNS_INT) || !gtOp.gtOp2->IsIconHandle());
16175             newFldSeq = gtOp.gtOp1->AsIntCon()->gtFieldSeq;
16176             baseAddr  = gtOp.gtOp2;
16177         }
16178         else if (gtOp.gtOp2->OperGet() == GT_CNS_INT)
16179         {
16180             assert((gtOp.gtOp1->gtOper != GT_CNS_INT) || !gtOp.gtOp1->IsIconHandle());
16181             newFldSeq = gtOp.gtOp2->AsIntCon()->gtFieldSeq;
16182             baseAddr  = gtOp.gtOp1;
16183         }
16184     }
16185     else
16186     {
16187         // Check if "this" has a zero-offset annotation.
16188         if (!comp->GetZeroOffsetFieldMap()->Lookup(this, &newFldSeq))
16189         {
16190             // If not, this is not a field address.
16191             return false;
16192         }
16193         else
16194         {
16195             baseAddr     = this;
16196             mustBeStatic = true;
16197         }
16198     }
16199
16200     // If not we don't have a field seq, it's not a field address.
16201     if (newFldSeq == nullptr || newFldSeq == FieldSeqStore::NotAField())
16202     {
16203         return false;
16204     }
16205
16206     // Prepend this field to whatever we've already accumulated (outside-in).
16207     *pFldSeq = comp->GetFieldSeqStore()->Append(newFldSeq, *pFldSeq);
16208
16209     // Is it a static or instance field?
16210     if (!FieldSeqStore::IsPseudoField(newFldSeq->m_fieldHnd) &&
16211         comp->info.compCompHnd->isFieldStatic(newFldSeq->m_fieldHnd))
16212     {
16213         // It is a static field.  We're done.
16214         *pObj    = nullptr;
16215         *pStatic = baseAddr;
16216         return true;
16217     }
16218     else if ((baseAddr != nullptr) && !mustBeStatic)
16219     {
16220         // It's an instance field...but it must be for a struct field, since we've not yet encountered
16221         // a "TYP_REF" address.  Analyze the reset of the address.
16222         return baseAddr->gtEffectiveVal()->IsFieldAddr(comp, pObj, pStatic, pFldSeq);
16223     }
16224
16225     // Otherwise...
16226     return false;
16227 }
16228
16229 bool Compiler::gtIsStaticFieldPtrToBoxedStruct(var_types fieldNodeType, CORINFO_FIELD_HANDLE fldHnd)
16230 {
16231     if (fieldNodeType != TYP_REF)
16232     {
16233         return false;
16234     }
16235     noway_assert(fldHnd != nullptr);
16236     CorInfoType cit      = info.compCompHnd->getFieldType(fldHnd);
16237     var_types   fieldTyp = JITtype2varType(cit);
16238     return fieldTyp != TYP_REF;
16239 }
16240
16241 #ifdef FEATURE_SIMD
16242 //------------------------------------------------------------------------
16243 // gtGetSIMDZero: Get a zero value of the appropriate SIMD type.
16244 //
16245 // Arguments:
16246 //    var_types - The simdType
16247 //    baseType  - The base type we need
16248 //    simdHandle - The handle for the SIMD type
16249 //
16250 // Return Value:
16251 //    A node generating the appropriate Zero, if we are able to discern it,
16252 //    otherwise null (note that this shouldn't happen, but callers should
16253 //    be tolerant of this case).
16254
16255 GenTree* Compiler::gtGetSIMDZero(var_types simdType, var_types baseType, CORINFO_CLASS_HANDLE simdHandle)
16256 {
16257     bool found    = false;
16258     bool isHWSIMD = true;
16259     noway_assert(m_simdHandleCache != nullptr);
16260
16261     // First, determine whether this is Vector<T>.
16262     if (simdType == getSIMDVectorType())
16263     {
16264         switch (baseType)
16265         {
16266             case TYP_FLOAT:
16267                 found = (simdHandle == m_simdHandleCache->SIMDFloatHandle);
16268                 break;
16269             case TYP_DOUBLE:
16270                 found = (simdHandle == m_simdHandleCache->SIMDDoubleHandle);
16271                 break;
16272             case TYP_INT:
16273                 found = (simdHandle == m_simdHandleCache->SIMDIntHandle);
16274                 break;
16275             case TYP_USHORT:
16276                 found = (simdHandle == m_simdHandleCache->SIMDUShortHandle);
16277                 break;
16278             case TYP_UBYTE:
16279                 found = (simdHandle == m_simdHandleCache->SIMDUByteHandle);
16280                 break;
16281             case TYP_SHORT:
16282                 found = (simdHandle == m_simdHandleCache->SIMDShortHandle);
16283                 break;
16284             case TYP_BYTE:
16285                 found = (simdHandle == m_simdHandleCache->SIMDByteHandle);
16286                 break;
16287             case TYP_LONG:
16288                 found = (simdHandle == m_simdHandleCache->SIMDLongHandle);
16289                 break;
16290             case TYP_UINT:
16291                 found = (simdHandle == m_simdHandleCache->SIMDUIntHandle);
16292                 break;
16293             case TYP_ULONG:
16294                 found = (simdHandle == m_simdHandleCache->SIMDULongHandle);
16295                 break;
16296             default:
16297                 break;
16298         }
16299         if (found)
16300         {
16301             isHWSIMD = false;
16302         }
16303     }
16304
16305     if (!found)
16306     {
16307         // We must still have isHWSIMD set to true, and the only non-HW types left are the fixed types.
16308         switch (simdType)
16309         {
16310             case TYP_SIMD8:
16311                 switch (baseType)
16312                 {
16313                     case TYP_FLOAT:
16314                         if (simdHandle == m_simdHandleCache->SIMDVector2Handle)
16315                         {
16316                             isHWSIMD = false;
16317                         }
16318 #if defined(_TARGET_ARM64_) && defined(FEATURE_HW_INTRINSICS)
16319                         else
16320                         {
16321                             assert(simdHandle == m_simdHandleCache->Vector64FloatHandle);
16322                         }
16323                         break;
16324                     case TYP_INT:
16325                         assert(simdHandle == m_simdHandleCache->Vector64IntHandle);
16326                         break;
16327                     case TYP_USHORT:
16328                         assert(simdHandle == m_simdHandleCache->Vector64UShortHandle);
16329                         break;
16330                     case TYP_UBYTE:
16331                         assert(simdHandle == m_simdHandleCache->Vector64UByteHandle);
16332                         break;
16333                     case TYP_SHORT:
16334                         assert(simdHandle == m_simdHandleCache->Vector64ShortHandle);
16335                         break;
16336                     case TYP_BYTE:
16337                         assert(simdHandle == m_simdHandleCache->Vector64ByteHandle);
16338                         break;
16339                     case TYP_UINT:
16340                         assert(simdHandle == m_simdHandleCache->Vector64UIntHandle);
16341                         break;
16342 #endif // defined(_TARGET_ARM64_) && defined(FEATURE_HW_INTRINSICS)
16343                     default:
16344                         break;
16345                 }
16346                 break;
16347
16348             case TYP_SIMD12:
16349                 assert((baseType == TYP_FLOAT) && (simdHandle == m_simdHandleCache->SIMDVector3Handle));
16350                 isHWSIMD = false;
16351                 break;
16352
16353             case TYP_SIMD16:
16354                 switch (baseType)
16355                 {
16356                     case TYP_FLOAT:
16357                         if (simdHandle == m_simdHandleCache->SIMDVector4Handle)
16358                         {
16359                             isHWSIMD = false;
16360                         }
16361 #if defined(FEATURE_HW_INTRINSICS)
16362                         else
16363                         {
16364                             assert(simdHandle == m_simdHandleCache->Vector128FloatHandle);
16365                         }
16366                         break;
16367                     case TYP_DOUBLE:
16368                         assert(simdHandle == m_simdHandleCache->Vector128DoubleHandle);
16369                         break;
16370                     case TYP_INT:
16371                         assert(simdHandle == m_simdHandleCache->Vector128IntHandle);
16372                         break;
16373                     case TYP_USHORT:
16374                         assert(simdHandle == m_simdHandleCache->Vector128UShortHandle);
16375                         break;
16376                     case TYP_UBYTE:
16377                         assert(simdHandle == m_simdHandleCache->Vector128UByteHandle);
16378                         break;
16379                     case TYP_SHORT:
16380                         assert(simdHandle == m_simdHandleCache->Vector128ShortHandle);
16381                         break;
16382                     case TYP_BYTE:
16383                         assert(simdHandle == m_simdHandleCache->Vector128ByteHandle);
16384                         break;
16385                     case TYP_LONG:
16386                         assert(simdHandle == m_simdHandleCache->Vector128LongHandle);
16387                         break;
16388                     case TYP_UINT:
16389                         assert(simdHandle == m_simdHandleCache->Vector128UIntHandle);
16390                         break;
16391                     case TYP_ULONG:
16392                         assert(simdHandle == m_simdHandleCache->Vector128ULongHandle);
16393                         break;
16394 #endif // defined(FEATURE_HW_INTRINSICS)
16395
16396                     default:
16397                         break;
16398                 }
16399                 break;
16400
16401 #if defined(_TARGET_XARCH4_) && defined(FEATURE_HW_INTRINSICS)
16402             case TYP_SIMD32:
16403                 switch (baseType)
16404                 {
16405                     case TYP_FLOAT:
16406                         assert(simdHandle == m_simdHandleCache->Vector256FloatHandle);
16407                         break;
16408                     case TYP_DOUBLE:
16409                         assert(simdHandle == m_simdHandleCache->Vector256DoubleHandle);
16410                         break;
16411                     case TYP_INT:
16412                         assert(simdHandle == m_simdHandleCache->Vector256IntHandle);
16413                         break;
16414                     case TYP_USHORT:
16415                         assert(simdHandle == m_simdHandleCache->Vector256UShortHandle);
16416                         break;
16417                     case TYP_UBYTE:
16418                         assert(simdHandle == m_simdHandleCache->Vector256UByteHandle);
16419                         break;
16420                     case TYP_SHORT:
16421                         assert(simdHandle == m_simdHandleCache->Vector256ShortHandle);
16422                         break;
16423                     case TYP_BYTE:
16424                         assert(simdHandle == m_simdHandleCache->Vector256ByteHandle);
16425                         break;
16426                     case TYP_LONG:
16427                         assert(simdHandle == m_simdHandleCache->Vector256LongHandle);
16428                         break;
16429                     case TYP_UINT:
16430                         assert(simdHandle == m_simdHandleCache->Vector256UIntHandle);
16431                         break;
16432                     case TYP_ULONG:
16433                         assert(simdHandle == m_simdHandleCache->Vector256ULongHandle);
16434                         break;
16435                     default:
16436                         break;
16437                 }
16438                 break;
16439 #endif // _TARGET_XARCH_ && FEATURE_HW_INTRINSICS
16440             default:
16441                 break;
16442         }
16443     }
16444
16445     unsigned size = genTypeSize(simdType);
16446     if (isHWSIMD)
16447     {
16448 #if defined(_TARGET_XARCH_) && defined(FEATURE_HW_INTRINSICS)
16449         switch (simdType)
16450         {
16451             case TYP_SIMD16:
16452                 return gtNewSimdHWIntrinsicNode(simdType, NI_Base_Vector128_Zero, baseType, size);
16453             case TYP_SIMD32:
16454                 return gtNewSimdHWIntrinsicNode(simdType, NI_Base_Vector256_Zero, baseType, size);
16455             default:
16456                 break;
16457         }
16458 #endif // _TARGET_XARCH_ && FEATURE_HW_INTRINSICS
16459         JITDUMP("Coudn't find the matching SIMD type for %s<%s> in gtGetSIMDZero\n", varTypeName(simdType),
16460                 varTypeName(baseType));
16461     }
16462     else
16463     {
16464         return gtNewSIMDVectorZero(simdType, baseType, size);
16465     }
16466     return nullptr;
16467 }
16468 #endif // FEATURE_SIMD
16469
16470 CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree)
16471 {
16472     CORINFO_CLASS_HANDLE structHnd = NO_CLASS_HANDLE;
16473     tree                           = tree->gtEffectiveVal();
16474     if (varTypeIsStruct(tree->gtType))
16475     {
16476         switch (tree->gtOper)
16477         {
16478             default:
16479                 break;
16480             case GT_MKREFANY:
16481                 structHnd = impGetRefAnyClass();
16482                 break;
16483             case GT_OBJ:
16484                 structHnd = tree->gtObj.gtClass;
16485                 break;
16486             case GT_CALL:
16487                 structHnd = tree->gtCall.gtRetClsHnd;
16488                 break;
16489             case GT_RET_EXPR:
16490                 structHnd = tree->gtRetExpr.gtRetClsHnd;
16491                 break;
16492             case GT_ARGPLACE:
16493                 structHnd = tree->gtArgPlace.gtArgPlaceClsHnd;
16494                 break;
16495             case GT_INDEX:
16496                 structHnd = tree->gtIndex.gtStructElemClass;
16497                 break;
16498             case GT_INDEX_ADDR:
16499                 structHnd = tree->AsIndexAddr()->gtStructElemClass;
16500                 break;
16501             case GT_FIELD:
16502                 info.compCompHnd->getFieldType(tree->gtField.gtFldHnd, &structHnd);
16503                 break;
16504             case GT_ASG:
16505                 structHnd = gtGetStructHandleIfPresent(tree->gtGetOp1());
16506                 break;
16507             case GT_LCL_FLD:
16508 #ifdef FEATURE_SIMD
16509                 if (varTypeIsSIMD(tree))
16510                 {
16511                     structHnd = gtGetStructHandleForSIMD(tree->gtType, TYP_FLOAT);
16512                 }
16513 #endif
16514                 break;
16515             case GT_LCL_VAR:
16516                 structHnd = lvaTable[tree->AsLclVarCommon()->gtLclNum].lvVerTypeInfo.GetClassHandle();
16517                 break;
16518             case GT_RETURN:
16519                 structHnd = gtGetStructHandleIfPresent(tree->gtOp.gtOp1);
16520                 break;
16521             case GT_IND:
16522 #ifdef FEATURE_SIMD
16523                 if (varTypeIsSIMD(tree))
16524                 {
16525                     structHnd = gtGetStructHandleForSIMD(tree->gtType, TYP_FLOAT);
16526                 }
16527                 else
16528 #endif
16529                 {
16530                     ArrayInfo arrInfo;
16531                     if (TryGetArrayInfo(tree->AsIndir(), &arrInfo))
16532                     {
16533                         structHnd = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType);
16534                     }
16535                 }
16536                 break;
16537 #ifdef FEATURE_SIMD
16538             case GT_SIMD:
16539                 structHnd = gtGetStructHandleForSIMD(tree->gtType, tree->AsSIMD()->gtSIMDBaseType);
16540                 break;
16541 #endif // FEATURE_SIMD
16542 #ifdef FEATURE_HW_INTRINSICS
16543             case GT_HWIntrinsic:
16544                 structHnd = gtGetStructHandleForHWSIMD(tree->gtType, tree->AsHWIntrinsic()->gtSIMDBaseType);
16545                 break;
16546 #endif
16547                 break;
16548         }
16549     }
16550     return structHnd;
16551 }
16552
16553 CORINFO_CLASS_HANDLE Compiler::gtGetStructHandle(GenTree* tree)
16554 {
16555     CORINFO_CLASS_HANDLE structHnd = gtGetStructHandleIfPresent(tree);
16556     assert(structHnd != NO_CLASS_HANDLE);
16557     return structHnd;
16558 }
16559
16560 //------------------------------------------------------------------------
16561 // gtGetClassHandle: find class handle for a ref type
16562 //
16563 // Arguments:
16564 //    tree -- tree to find handle for
16565 //    pIsExact   [out] -- whether handle is exact type
16566 //    pIsNonNull [out] -- whether tree value is known not to be null
16567 //
16568 // Return Value:
16569 //    nullptr if class handle is unknown,
16570 //        otherwise the class handle.
16571 //    *pIsExact set true if tree type is known to be exactly the handle type,
16572 //        otherwise actual type may be a subtype.
16573 //    *pIsNonNull set true if tree value is known not to be null,
16574 //        otherwise a null value is possible.
16575
16576 CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, bool* pIsNonNull)
16577 {
16578     // Set default values for our out params.
16579     *pIsNonNull                   = false;
16580     *pIsExact                     = false;
16581     CORINFO_CLASS_HANDLE objClass = nullptr;
16582
16583     // Bail out if we're just importing and not generating code, since
16584     // the jit uses TYP_REF for CORINFO_TYPE_VAR locals and args, but
16585     // these may not be ref types.
16586     if (compIsForImportOnly())
16587     {
16588         return objClass;
16589     }
16590
16591     // Bail out if the tree is not a ref type.
16592     var_types treeType = tree->TypeGet();
16593     if (treeType != TYP_REF)
16594     {
16595         return objClass;
16596     }
16597
16598     // Tunnel through commas.
16599     GenTree*         obj   = tree->gtEffectiveVal(false);
16600     const genTreeOps objOp = obj->OperGet();
16601
16602     switch (objOp)
16603     {
16604         case GT_COMMA:
16605         {
16606             // gtEffectiveVal above means we shouldn't see commas here.
16607             assert(!"unexpected GT_COMMA");
16608             break;
16609         }
16610
16611         case GT_LCL_VAR:
16612         {
16613             // For locals, pick up type info from the local table.
16614             const unsigned objLcl = obj->AsLclVar()->GetLclNum();
16615
16616             objClass  = lvaTable[objLcl].lvClassHnd;
16617             *pIsExact = lvaTable[objLcl].lvClassIsExact;
16618             break;
16619         }
16620
16621         case GT_FIELD:
16622         {
16623             // For fields, get the type from the field handle.
16624             CORINFO_FIELD_HANDLE fieldHnd = obj->gtField.gtFldHnd;
16625
16626             if (fieldHnd != nullptr)
16627             {
16628                 objClass = gtGetFieldClassHandle(fieldHnd, pIsExact, pIsNonNull);
16629             }
16630
16631             break;
16632         }
16633
16634         case GT_RET_EXPR:
16635         {
16636             // If we see a RET_EXPR, recurse through to examine the
16637             // return value expression.
16638             GenTree* retExpr = tree->gtRetExpr.gtInlineCandidate;
16639             objClass         = gtGetClassHandle(retExpr, pIsExact, pIsNonNull);
16640             break;
16641         }
16642
16643         case GT_CALL:
16644         {
16645             GenTreeCall* call = tree->AsCall();
16646             if (call->IsInlineCandidate())
16647             {
16648                 // For inline candidates, we've already cached the return
16649                 // type class handle in the inline info.
16650                 InlineCandidateInfo* inlInfo = call->gtInlineCandidateInfo;
16651                 assert(inlInfo != nullptr);
16652
16653                 // Grab it as our first cut at a return type.
16654                 assert(inlInfo->methInfo.args.retType == CORINFO_TYPE_CLASS);
16655                 objClass = inlInfo->methInfo.args.retTypeClass;
16656
16657                 // If the method is shared, the above may not capture
16658                 // the most precise return type information (that is,
16659                 // it may represent a shared return type and as such,
16660                 // have instances of __Canon). See if we can use the
16661                 // context to get at something more definite.
16662                 //
16663                 // For now, we do this here on demand rather than when
16664                 // processing the call, but we could/should apply
16665                 // similar sharpening to the argument and local types
16666                 // of the inlinee.
16667                 const unsigned retClassFlags = info.compCompHnd->getClassAttribs(objClass);
16668                 if (retClassFlags & CORINFO_FLG_SHAREDINST)
16669                 {
16670                     CORINFO_CONTEXT_HANDLE context = inlInfo->exactContextHnd;
16671
16672                     if (context != nullptr)
16673                     {
16674                         CORINFO_CLASS_HANDLE exactClass = nullptr;
16675
16676                         if (((size_t)context & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
16677                         {
16678                             exactClass = (CORINFO_CLASS_HANDLE)((size_t)context & ~CORINFO_CONTEXTFLAGS_MASK);
16679                         }
16680                         else
16681                         {
16682                             CORINFO_METHOD_HANDLE exactMethod =
16683                                 (CORINFO_METHOD_HANDLE)((size_t)context & ~CORINFO_CONTEXTFLAGS_MASK);
16684                             exactClass = info.compCompHnd->getMethodClass(exactMethod);
16685                         }
16686
16687                         // Grab the signature in this context.
16688                         CORINFO_SIG_INFO sig;
16689                         eeGetMethodSig(call->gtCallMethHnd, &sig, exactClass);
16690                         assert(sig.retType == CORINFO_TYPE_CLASS);
16691                         objClass = sig.retTypeClass;
16692                     }
16693                 }
16694             }
16695             else if (call->gtCallType == CT_USER_FUNC)
16696             {
16697                 // For user calls, we can fetch the approximate return
16698                 // type info from the method handle. Unfortunately
16699                 // we've lost the exact context, so this is the best
16700                 // we can do for now.
16701                 CORINFO_METHOD_HANDLE method     = call->gtCallMethHnd;
16702                 CORINFO_CLASS_HANDLE  exactClass = nullptr;
16703                 CORINFO_SIG_INFO      sig;
16704                 eeGetMethodSig(method, &sig, exactClass);
16705                 if (sig.retType == CORINFO_TYPE_VOID)
16706                 {
16707                     // This is a constructor call.
16708                     const unsigned methodFlags = info.compCompHnd->getMethodAttribs(method);
16709                     assert((methodFlags & CORINFO_FLG_CONSTRUCTOR) != 0);
16710                     objClass    = info.compCompHnd->getMethodClass(method);
16711                     *pIsExact   = true;
16712                     *pIsNonNull = true;
16713                 }
16714                 else
16715                 {
16716                     assert(sig.retType == CORINFO_TYPE_CLASS);
16717                     objClass = sig.retTypeClass;
16718                 }
16719             }
16720             else if (call->gtCallType == CT_HELPER)
16721             {
16722                 objClass = gtGetHelperCallClassHandle(call, pIsExact, pIsNonNull);
16723             }
16724
16725             break;
16726         }
16727
16728         case GT_INTRINSIC:
16729         {
16730             GenTreeIntrinsic* intrinsic = obj->AsIntrinsic();
16731
16732             if (intrinsic->gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType)
16733             {
16734                 CORINFO_CLASS_HANDLE runtimeType = info.compCompHnd->getBuiltinClass(CLASSID_RUNTIME_TYPE);
16735                 assert(runtimeType != NO_CLASS_HANDLE);
16736
16737                 objClass    = runtimeType;
16738                 *pIsExact   = false;
16739                 *pIsNonNull = true;
16740             }
16741
16742             break;
16743         }
16744
16745         case GT_CNS_STR:
16746         {
16747             // For literal strings, we know the class and that the
16748             // value is not null.
16749             objClass    = impGetStringClass();
16750             *pIsExact   = true;
16751             *pIsNonNull = true;
16752             break;
16753         }
16754
16755         case GT_IND:
16756         {
16757             GenTreeIndir* indir = obj->AsIndir();
16758
16759             if (indir->HasBase() && !indir->HasIndex())
16760             {
16761                 // indir(addr(lcl)) --> lcl
16762                 //
16763                 // This comes up during constrained callvirt on ref types.
16764
16765                 GenTree*             base = indir->Base();
16766                 GenTreeLclVarCommon* lcl  = base->IsLocalAddrExpr();
16767
16768                 if ((lcl != nullptr) && (base->OperGet() != GT_ADD))
16769                 {
16770                     const unsigned objLcl = lcl->GetLclNum();
16771                     objClass              = lvaTable[objLcl].lvClassHnd;
16772                     *pIsExact             = lvaTable[objLcl].lvClassIsExact;
16773                 }
16774                 else if (base->OperGet() == GT_ARR_ELEM)
16775                 {
16776                     // indir(arr_elem(...)) -> array element type
16777
16778                     GenTree* array = base->AsArrElem()->gtArrObj;
16779
16780                     objClass    = gtGetArrayElementClassHandle(array);
16781                     *pIsExact   = false;
16782                     *pIsNonNull = false;
16783                 }
16784                 else if (base->OperGet() == GT_ADD)
16785                 {
16786                     // This could be a static field access.
16787                     //
16788                     // See if op1 is a static field base helper call
16789                     // and if so, op2 will have the field info.
16790                     GenTree* op1 = base->gtOp.gtOp1;
16791                     GenTree* op2 = base->gtOp.gtOp2;
16792
16793                     const bool op1IsStaticFieldBase = gtIsStaticGCBaseHelperCall(op1);
16794
16795                     if (op1IsStaticFieldBase && (op2->OperGet() == GT_CNS_INT))
16796                     {
16797                         FieldSeqNode* fieldSeq = op2->AsIntCon()->gtFieldSeq;
16798
16799                         if (fieldSeq != nullptr)
16800                         {
16801                             while (fieldSeq->m_next != nullptr)
16802                             {
16803                                 fieldSeq = fieldSeq->m_next;
16804                             }
16805
16806                             assert(!fieldSeq->IsPseudoField());
16807
16808                             // No benefit to calling gtGetFieldClassHandle here, as
16809                             // the exact field being accessed can vary.
16810                             CORINFO_FIELD_HANDLE fieldHnd     = fieldSeq->m_fieldHnd;
16811                             CORINFO_CLASS_HANDLE fieldClass   = nullptr;
16812                             CorInfoType          fieldCorType = info.compCompHnd->getFieldType(fieldHnd, &fieldClass);
16813
16814                             assert(fieldCorType == CORINFO_TYPE_CLASS);
16815                             objClass = fieldClass;
16816                         }
16817                     }
16818                 }
16819             }
16820
16821             break;
16822         }
16823
16824         case GT_BOX:
16825         {
16826             // Box should just wrap a local var reference which has
16827             // the type we're looking for. Also box only represents a
16828             // non-nullable value type so result cannot be null.
16829             GenTreeBox* box     = obj->AsBox();
16830             GenTree*    boxTemp = box->BoxOp();
16831             assert(boxTemp->IsLocal());
16832             const unsigned boxTempLcl = boxTemp->AsLclVar()->GetLclNum();
16833             objClass                  = lvaTable[boxTempLcl].lvClassHnd;
16834             *pIsExact                 = lvaTable[boxTempLcl].lvClassIsExact;
16835             *pIsNonNull               = true;
16836             break;
16837         }
16838
16839         case GT_INDEX:
16840         {
16841             GenTree* array = obj->AsIndex()->Arr();
16842
16843             objClass    = gtGetArrayElementClassHandle(array);
16844             *pIsExact   = false;
16845             *pIsNonNull = false;
16846             break;
16847         }
16848
16849         default:
16850         {
16851             break;
16852         }
16853     }
16854
16855     return objClass;
16856 }
16857
16858 //------------------------------------------------------------------------
16859 // gtGetHelperCallClassHandle: find class handle for return value of a
16860 //   helper call
16861 //
16862 // Arguments:
16863 //    call - helper call to examine
16864 //    pIsExact - [OUT] true if type is known exactly
16865 //    pIsNonNull - [OUT] true if return value is not null
16866 //
16867 // Return Value:
16868 //    nullptr if helper call result is not a ref class, or the class handle
16869 //    is unknown, otherwise the class handle.
16870
16871 CORINFO_CLASS_HANDLE Compiler::gtGetHelperCallClassHandle(GenTreeCall* call, bool* pIsExact, bool* pIsNonNull)
16872 {
16873     assert(call->gtCallType == CT_HELPER);
16874
16875     *pIsNonNull                    = false;
16876     *pIsExact                      = false;
16877     CORINFO_CLASS_HANDLE  objClass = nullptr;
16878     const CorInfoHelpFunc helper   = eeGetHelperNum(call->gtCallMethHnd);
16879
16880     switch (helper)
16881     {
16882         case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE:
16883         case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL:
16884         {
16885             // Note for some runtimes these helpers return exact types.
16886             //
16887             // But in those cases the types are also sealed, so there's no
16888             // need to claim exactness here.
16889             const bool           helperResultNonNull = (helper == CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE);
16890             CORINFO_CLASS_HANDLE runtimeType         = info.compCompHnd->getBuiltinClass(CLASSID_RUNTIME_TYPE);
16891
16892             assert(runtimeType != NO_CLASS_HANDLE);
16893
16894             objClass    = runtimeType;
16895             *pIsNonNull = helperResultNonNull;
16896             break;
16897         }
16898
16899         case CORINFO_HELP_CHKCASTCLASS:
16900         case CORINFO_HELP_CHKCASTANY:
16901         case CORINFO_HELP_CHKCASTARRAY:
16902         case CORINFO_HELP_CHKCASTINTERFACE:
16903         case CORINFO_HELP_CHKCASTCLASS_SPECIAL:
16904         case CORINFO_HELP_ISINSTANCEOFINTERFACE:
16905         case CORINFO_HELP_ISINSTANCEOFARRAY:
16906         case CORINFO_HELP_ISINSTANCEOFCLASS:
16907         case CORINFO_HELP_ISINSTANCEOFANY:
16908         {
16909             // Fetch the class handle from the helper call arglist
16910             GenTreeArgList*      args    = call->gtCallArgs;
16911             GenTree*             typeArg = args->Current();
16912             CORINFO_CLASS_HANDLE castHnd = gtGetHelperArgClassHandle(typeArg);
16913
16914             // We generally assume the type being cast to is the best type
16915             // for the result, unless it is an interface type.
16916             //
16917             // TODO-CQ: when we have default interface methods then
16918             // this might not be the best assumption. We could also
16919             // explore calling something like mergeClasses to identify
16920             // the more specific class. A similar issue arises when
16921             // typing the temp in impCastClassOrIsInstToTree, when we
16922             // expand the cast inline.
16923             if (castHnd != nullptr)
16924             {
16925                 DWORD attrs = info.compCompHnd->getClassAttribs(castHnd);
16926
16927                 if ((attrs & CORINFO_FLG_INTERFACE) != 0)
16928                 {
16929                     castHnd = nullptr;
16930                 }
16931             }
16932
16933             // If we don't have a good estimate for the type we can use the
16934             // type from the value being cast instead.
16935             if (castHnd == nullptr)
16936             {
16937                 GenTree* valueArg = args->Rest()->Current();
16938                 castHnd           = gtGetClassHandle(valueArg, pIsExact, pIsNonNull);
16939             }
16940
16941             // We don't know at jit time if the cast will succeed or fail, but if it
16942             // fails at runtime then an exception is thrown for cast helpers, or the
16943             // result is set null for instance helpers.
16944             //
16945             // So it safe to claim the result has the cast type.
16946             // Note we don't know for sure that it is exactly this type.
16947             if (castHnd != nullptr)
16948             {
16949                 objClass = castHnd;
16950             }
16951
16952             break;
16953         }
16954
16955         default:
16956             break;
16957     }
16958
16959     return objClass;
16960 }
16961
16962 //------------------------------------------------------------------------
16963 // gtGetArrayElementClassHandle: find class handle for elements of an array
16964 // of ref types
16965 //
16966 // Arguments:
16967 //    array -- array to find handle for
16968 //
16969 // Return Value:
16970 //    nullptr if element class handle is unknown, otherwise the class handle.
16971
16972 CORINFO_CLASS_HANDLE Compiler::gtGetArrayElementClassHandle(GenTree* array)
16973 {
16974     bool                 isArrayExact   = false;
16975     bool                 isArrayNonNull = false;
16976     CORINFO_CLASS_HANDLE arrayClassHnd  = gtGetClassHandle(array, &isArrayExact, &isArrayNonNull);
16977
16978     if (arrayClassHnd != nullptr)
16979     {
16980         // We know the class of the reference
16981         DWORD attribs = info.compCompHnd->getClassAttribs(arrayClassHnd);
16982
16983         if ((attribs & CORINFO_FLG_ARRAY) != 0)
16984         {
16985             // We know for sure it is an array
16986             CORINFO_CLASS_HANDLE elemClassHnd  = nullptr;
16987             CorInfoType          arrayElemType = info.compCompHnd->getChildType(arrayClassHnd, &elemClassHnd);
16988
16989             if (arrayElemType == CORINFO_TYPE_CLASS)
16990             {
16991                 // We know it is an array of ref types
16992                 return elemClassHnd;
16993             }
16994         }
16995     }
16996
16997     return nullptr;
16998 }
16999
17000 //------------------------------------------------------------------------
17001 // gtGetFieldClassHandle: find class handle for a field
17002 //
17003 // Arguments:
17004 //    fieldHnd - field handle for field in question
17005 //    pIsExact - [OUT] true if type is known exactly
17006 //    pIsNonNull - [OUT] true if field value is not null
17007 //
17008 // Return Value:
17009 //    nullptr if helper call result is not a ref class, or the class handle
17010 //    is unknown, otherwise the class handle.
17011 //
17012 //    May examine runtime state of static field instances.
17013
17014 CORINFO_CLASS_HANDLE Compiler::gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsExact, bool* pIsNonNull)
17015 {
17016     CORINFO_CLASS_HANDLE fieldClass   = nullptr;
17017     CorInfoType          fieldCorType = info.compCompHnd->getFieldType(fieldHnd, &fieldClass);
17018
17019     if (fieldCorType == CORINFO_TYPE_CLASS)
17020     {
17021         // Optionally, look at the actual type of the field's value
17022         bool queryForCurrentClass = true;
17023         INDEBUG(queryForCurrentClass = (JitConfig.JitQueryCurrentStaticFieldClass() > 0););
17024
17025         if (queryForCurrentClass)
17026         {
17027
17028 #if DEBUG
17029             const char* fieldClassName = nullptr;
17030             const char* fieldName      = eeGetFieldName(fieldHnd, &fieldClassName);
17031             JITDUMP("Querying runtime about current class of field %s.%s (declared as %s)\n", fieldClassName, fieldName,
17032                     eeGetClassName(fieldClass));
17033 #endif // DEBUG
17034
17035             // Is this a fully initialized init-only static field?
17036             //
17037             // Note we're not asking for speculative results here, yet.
17038             CORINFO_CLASS_HANDLE currentClass = info.compCompHnd->getStaticFieldCurrentClass(fieldHnd);
17039
17040             if (currentClass != NO_CLASS_HANDLE)
17041             {
17042                 // Yes! We know the class exactly and can rely on this to always be true.
17043                 fieldClass  = currentClass;
17044                 *pIsExact   = true;
17045                 *pIsNonNull = true;
17046                 JITDUMP("Runtime reports field is init-only and initialized and has class %s\n",
17047                         eeGetClassName(fieldClass));
17048             }
17049             else
17050             {
17051                 JITDUMP("Field's current class not available\n");
17052             }
17053         }
17054     }
17055
17056     return fieldClass;
17057 }
17058
17059 //------------------------------------------------------------------------
17060 // gtIsGCStaticBaseHelperCall: true if tree is fetching the gc static base
17061 //    for a subsequent static field access
17062 //
17063 // Arguments:
17064 //    tree - tree to consider
17065 //
17066 // Return Value:
17067 //    true if the tree is a suitable helper call
17068 //
17069 // Notes:
17070 //    Excludes R2R helpers as they specify the target field in a way
17071 //    that is opaque to the jit.
17072
17073 bool Compiler::gtIsStaticGCBaseHelperCall(GenTree* tree)
17074 {
17075     if (tree->OperGet() != GT_CALL)
17076     {
17077         return false;
17078     }
17079
17080     GenTreeCall* call = tree->AsCall();
17081
17082     if (call->gtCallType != CT_HELPER)
17083     {
17084         return false;
17085     }
17086
17087     const CorInfoHelpFunc helper = eeGetHelperNum(call->gtCallMethHnd);
17088
17089     switch (helper)
17090     {
17091         // We are looking for a REF type so only need to check for the GC base helpers
17092         case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
17093         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
17094         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
17095         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
17096         case CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
17097         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
17098         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
17099         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
17100             return true;
17101         default:
17102             break;
17103     }
17104
17105     return false;
17106 }
17107
17108 void GenTree::ParseArrayAddress(
17109     Compiler* comp, ArrayInfo* arrayInfo, GenTree** pArr, ValueNum* pInxVN, FieldSeqNode** pFldSeq)
17110 {
17111     *pArr                 = nullptr;
17112     ValueNum       inxVN  = ValueNumStore::NoVN;
17113     target_ssize_t offset = 0;
17114     FieldSeqNode*  fldSeq = nullptr;
17115
17116     ParseArrayAddressWork(comp, 1, pArr, &inxVN, &offset, &fldSeq);
17117
17118     // If we didn't find an array reference (perhaps it is the constant null?) we will give up.
17119     if (*pArr == nullptr)
17120     {
17121         return;
17122     }
17123
17124     // OK, new we have to figure out if any part of the "offset" is a constant contribution to the index.
17125     // First, sum the offsets of any fields in fldSeq.
17126     unsigned      fieldOffsets = 0;
17127     FieldSeqNode* fldSeqIter   = fldSeq;
17128     // Also, find the first non-pseudo field...
17129     assert(*pFldSeq == nullptr);
17130     while (fldSeqIter != nullptr)
17131     {
17132         if (fldSeqIter == FieldSeqStore::NotAField())
17133         {
17134             // TODO-Review: A NotAField here indicates a failure to properly maintain the field sequence
17135             // See test case self_host_tests_x86\jit\regression\CLR-x86-JIT\v1-m12-beta2\ b70992\ b70992.exe
17136             // Safest thing to do here is to drop back to MinOpts
17137             CLANG_FORMAT_COMMENT_ANCHOR;
17138
17139 #ifdef DEBUG
17140             if (comp->opts.optRepeat)
17141             {
17142                 // We don't guarantee preserving these annotations through the entire optimizer, so
17143                 // just conservatively return null if under optRepeat.
17144                 *pArr = nullptr;
17145                 return;
17146             }
17147 #endif // DEBUG
17148             noway_assert(!"fldSeqIter is NotAField() in ParseArrayAddress");
17149         }
17150
17151         if (!FieldSeqStore::IsPseudoField(fldSeqIter->m_fieldHnd))
17152         {
17153             if (*pFldSeq == nullptr)
17154             {
17155                 *pFldSeq = fldSeqIter;
17156             }
17157             CORINFO_CLASS_HANDLE fldCls = nullptr;
17158             noway_assert(fldSeqIter->m_fieldHnd != nullptr);
17159             CorInfoType cit = comp->info.compCompHnd->getFieldType(fldSeqIter->m_fieldHnd, &fldCls);
17160             fieldOffsets += comp->compGetTypeSize(cit, fldCls);
17161         }
17162         fldSeqIter = fldSeqIter->m_next;
17163     }
17164
17165     // Is there some portion of the "offset" beyond the first-elem offset and the struct field suffix we just computed?
17166     if (!FitsIn<target_ssize_t>(fieldOffsets + arrayInfo->m_elemOffset) ||
17167         !FitsIn<target_ssize_t>(arrayInfo->m_elemSize))
17168     {
17169         // This seems unlikely, but no harm in being safe...
17170         *pInxVN = comp->GetValueNumStore()->VNForExpr(nullptr, TYP_INT);
17171         return;
17172     }
17173     // Otherwise...
17174     target_ssize_t offsetAccountedFor = static_cast<target_ssize_t>(fieldOffsets + arrayInfo->m_elemOffset);
17175     target_ssize_t elemSize           = static_cast<target_ssize_t>(arrayInfo->m_elemSize);
17176
17177     target_ssize_t constIndOffset = offset - offsetAccountedFor;
17178     // This should be divisible by the element size...
17179     assert((constIndOffset % elemSize) == 0);
17180     target_ssize_t constInd = constIndOffset / elemSize;
17181
17182     ValueNumStore* vnStore = comp->GetValueNumStore();
17183
17184     if (inxVN == ValueNumStore::NoVN)
17185     {
17186         // Must be a constant index.
17187         *pInxVN = vnStore->VNForPtrSizeIntCon(constInd);
17188     }
17189     else
17190     {
17191         //
17192         // Perform ((inxVN / elemSizeVN) + vnForConstInd)
17193         //
17194
17195         // The value associated with the index value number (inxVN) is the offset into the array,
17196         // which has been scaled by element size. We need to recover the array index from that offset
17197         if (vnStore->IsVNConstant(inxVN))
17198         {
17199             target_ssize_t index = vnStore->CoercedConstantValue<target_ssize_t>(inxVN);
17200             noway_assert(elemSize > 0 && ((index % elemSize) == 0));
17201             *pInxVN = vnStore->VNForPtrSizeIntCon((index / elemSize) + constInd);
17202         }
17203         else
17204         {
17205             bool canFoldDiv = false;
17206
17207             // If the index VN is a MUL by elemSize, see if we can eliminate it instead of adding
17208             // the division by elemSize.
17209             VNFuncApp funcApp;
17210             if (vnStore->GetVNFunc(inxVN, &funcApp) && funcApp.m_func == (VNFunc)GT_MUL)
17211             {
17212                 ValueNum vnForElemSize = vnStore->VNForLongCon(elemSize);
17213
17214                 // One of the multiply operand is elemSize, so the resulting
17215                 // index VN should simply be the other operand.
17216                 if (funcApp.m_args[1] == vnForElemSize)
17217                 {
17218                     *pInxVN    = funcApp.m_args[0];
17219                     canFoldDiv = true;
17220                 }
17221                 else if (funcApp.m_args[0] == vnForElemSize)
17222                 {
17223                     *pInxVN    = funcApp.m_args[1];
17224                     canFoldDiv = true;
17225                 }
17226             }
17227
17228             // Perform ((inxVN / elemSizeVN) + vnForConstInd)
17229             if (!canFoldDiv)
17230             {
17231                 ValueNum vnForElemSize = vnStore->VNForPtrSizeIntCon(elemSize);
17232                 ValueNum vnForScaledInx =
17233                     vnStore->VNForFunc(TYP_I_IMPL, GetVNFuncForOper(GT_DIV, VOK_Default), inxVN, vnForElemSize);
17234                 *pInxVN = vnForScaledInx;
17235             }
17236
17237             if (constInd != 0)
17238             {
17239                 ValueNum vnForConstInd = comp->GetValueNumStore()->VNForPtrSizeIntCon(constInd);
17240                 VNFunc   vnFunc        = GetVNFuncForOper(GT_ADD, VOK_Default);
17241
17242                 *pInxVN = comp->GetValueNumStore()->VNForFunc(TYP_I_IMPL, vnFunc, *pInxVN, vnForConstInd);
17243             }
17244         }
17245     }
17246 }
17247
17248 void GenTree::ParseArrayAddressWork(Compiler*       comp,
17249                                     target_ssize_t  inputMul,
17250                                     GenTree**       pArr,
17251                                     ValueNum*       pInxVN,
17252                                     target_ssize_t* pOffset,
17253                                     FieldSeqNode**  pFldSeq)
17254 {
17255     if (TypeGet() == TYP_REF)
17256     {
17257         // This must be the array pointer.
17258         *pArr = this;
17259         assert(inputMul == 1); // Can't multiply the array pointer by anything.
17260     }
17261     else
17262     {
17263         switch (OperGet())
17264         {
17265             case GT_CNS_INT:
17266                 *pFldSeq = comp->GetFieldSeqStore()->Append(*pFldSeq, gtIntCon.gtFieldSeq);
17267                 assert(!gtIntCon.ImmedValNeedsReloc(comp));
17268                 // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntCon::gtIconVal had target_ssize_t
17269                 // type.
17270                 *pOffset += (inputMul * (target_ssize_t)(gtIntCon.gtIconVal));
17271                 return;
17272
17273             case GT_ADD:
17274             case GT_SUB:
17275                 gtOp.gtOp1->ParseArrayAddressWork(comp, inputMul, pArr, pInxVN, pOffset, pFldSeq);
17276                 if (OperGet() == GT_SUB)
17277                 {
17278                     inputMul = -inputMul;
17279                 }
17280                 gtOp.gtOp2->ParseArrayAddressWork(comp, inputMul, pArr, pInxVN, pOffset, pFldSeq);
17281                 return;
17282
17283             case GT_MUL:
17284             {
17285                 // If one op is a constant, continue parsing down.
17286                 target_ssize_t subMul   = 0;
17287                 GenTree*       nonConst = nullptr;
17288                 if (gtOp.gtOp1->IsCnsIntOrI())
17289                 {
17290                     // If the other arg is an int constant, and is a "not-a-field", choose
17291                     // that as the multiplier, thus preserving constant index offsets...
17292                     if (gtOp.gtOp2->OperGet() == GT_CNS_INT &&
17293                         gtOp.gtOp2->gtIntCon.gtFieldSeq == FieldSeqStore::NotAField())
17294                     {
17295                         assert(!gtOp.gtOp2->gtIntCon.ImmedValNeedsReloc(comp));
17296                         // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntConCommon::gtIconVal had
17297                         // target_ssize_t type.
17298                         subMul   = (target_ssize_t)gtOp.gtOp2->gtIntConCommon.IconValue();
17299                         nonConst = gtOp.gtOp1;
17300                     }
17301                     else
17302                     {
17303                         assert(!gtOp.gtOp1->gtIntCon.ImmedValNeedsReloc(comp));
17304                         // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntConCommon::gtIconVal had
17305                         // target_ssize_t type.
17306                         subMul   = (target_ssize_t)gtOp.gtOp1->gtIntConCommon.IconValue();
17307                         nonConst = gtOp.gtOp2;
17308                     }
17309                 }
17310                 else if (gtOp.gtOp2->IsCnsIntOrI())
17311                 {
17312                     assert(!gtOp.gtOp2->gtIntCon.ImmedValNeedsReloc(comp));
17313                     // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntConCommon::gtIconVal had
17314                     // target_ssize_t type.
17315                     subMul   = (target_ssize_t)gtOp.gtOp2->gtIntConCommon.IconValue();
17316                     nonConst = gtOp.gtOp1;
17317                 }
17318                 if (nonConst != nullptr)
17319                 {
17320                     nonConst->ParseArrayAddressWork(comp, inputMul * subMul, pArr, pInxVN, pOffset, pFldSeq);
17321                     return;
17322                 }
17323                 // Otherwise, exit the switch, treat as a contribution to the index.
17324             }
17325             break;
17326
17327             case GT_LSH:
17328                 // If one op is a constant, continue parsing down.
17329                 if (gtOp.gtOp2->IsCnsIntOrI())
17330                 {
17331                     assert(!gtOp.gtOp2->gtIntCon.ImmedValNeedsReloc(comp));
17332                     // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntCon::gtIconVal had target_ssize_t
17333                     // type.
17334                     target_ssize_t subMul = target_ssize_t{1} << (target_ssize_t)gtOp.gtOp2->gtIntConCommon.IconValue();
17335                     gtOp.gtOp1->ParseArrayAddressWork(comp, inputMul * subMul, pArr, pInxVN, pOffset, pFldSeq);
17336                     return;
17337                 }
17338                 // Otherwise, exit the switch, treat as a contribution to the index.
17339                 break;
17340
17341             case GT_COMMA:
17342                 // We don't care about exceptions for this purpose.
17343                 if ((gtOp.gtOp1->OperGet() == GT_ARR_BOUNDS_CHECK) || gtOp.gtOp1->IsNothingNode())
17344                 {
17345                     gtOp.gtOp2->ParseArrayAddressWork(comp, inputMul, pArr, pInxVN, pOffset, pFldSeq);
17346                     return;
17347                 }
17348                 break;
17349
17350             default:
17351                 break;
17352         }
17353         // If we didn't return above, must be a contribution to the non-constant part of the index VN.
17354         ValueNum vn = comp->GetValueNumStore()->VNLiberalNormalValue(gtVNPair);
17355         if (inputMul != 1)
17356         {
17357             ValueNum mulVN = comp->GetValueNumStore()->VNForLongCon(inputMul);
17358             vn = comp->GetValueNumStore()->VNForFunc(TypeGet(), GetVNFuncForOper(GT_MUL, VOK_Default), mulVN, vn);
17359         }
17360         if (*pInxVN == ValueNumStore::NoVN)
17361         {
17362             *pInxVN = vn;
17363         }
17364         else
17365         {
17366             *pInxVN =
17367                 comp->GetValueNumStore()->VNForFunc(TypeGet(), GetVNFuncForOper(GT_ADD, VOK_Default), *pInxVN, vn);
17368         }
17369     }
17370 }
17371
17372 bool GenTree::ParseArrayElemForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq)
17373 {
17374     if (OperIsIndir())
17375     {
17376         if (gtFlags & GTF_IND_ARR_INDEX)
17377         {
17378             bool b = comp->GetArrayInfoMap()->Lookup(this, arrayInfo);
17379             assert(b);
17380             return true;
17381         }
17382
17383         // Otherwise...
17384         GenTree* addr = AsIndir()->Addr();
17385         return addr->ParseArrayElemAddrForm(comp, arrayInfo, pFldSeq);
17386     }
17387     else
17388     {
17389         return false;
17390     }
17391 }
17392
17393 bool GenTree::ParseArrayElemAddrForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq)
17394 {
17395     switch (OperGet())
17396     {
17397         case GT_ADD:
17398         {
17399             GenTree* arrAddr = nullptr;
17400             GenTree* offset  = nullptr;
17401             if (gtOp.gtOp1->TypeGet() == TYP_BYREF)
17402             {
17403                 arrAddr = gtOp.gtOp1;
17404                 offset  = gtOp.gtOp2;
17405             }
17406             else if (gtOp.gtOp2->TypeGet() == TYP_BYREF)
17407             {
17408                 arrAddr = gtOp.gtOp2;
17409                 offset  = gtOp.gtOp1;
17410             }
17411             else
17412             {
17413                 return false;
17414             }
17415             if (!offset->ParseOffsetForm(comp, pFldSeq))
17416             {
17417                 return false;
17418             }
17419             return arrAddr->ParseArrayElemAddrForm(comp, arrayInfo, pFldSeq);
17420         }
17421
17422         case GT_ADDR:
17423         {
17424             GenTree* addrArg = gtOp.gtOp1;
17425             if (addrArg->OperGet() != GT_IND)
17426             {
17427                 return false;
17428             }
17429             else
17430             {
17431                 // The "Addr" node might be annotated with a zero-offset field sequence.
17432                 FieldSeqNode* zeroOffsetFldSeq = nullptr;
17433                 if (comp->GetZeroOffsetFieldMap()->Lookup(this, &zeroOffsetFldSeq))
17434                 {
17435                     *pFldSeq = comp->GetFieldSeqStore()->Append(*pFldSeq, zeroOffsetFldSeq);
17436                 }
17437                 return addrArg->ParseArrayElemForm(comp, arrayInfo, pFldSeq);
17438             }
17439         }
17440
17441         default:
17442             return false;
17443     }
17444 }
17445
17446 bool GenTree::ParseOffsetForm(Compiler* comp, FieldSeqNode** pFldSeq)
17447 {
17448     switch (OperGet())
17449     {
17450         case GT_CNS_INT:
17451         {
17452             GenTreeIntCon* icon = AsIntCon();
17453             *pFldSeq            = comp->GetFieldSeqStore()->Append(*pFldSeq, icon->gtFieldSeq);
17454             return true;
17455         }
17456
17457         case GT_ADD:
17458             if (!gtOp.gtOp1->ParseOffsetForm(comp, pFldSeq))
17459             {
17460                 return false;
17461             }
17462             return gtOp.gtOp2->ParseOffsetForm(comp, pFldSeq);
17463
17464         default:
17465             return false;
17466     }
17467 }
17468
17469 void GenTree::LabelIndex(Compiler* comp, bool isConst)
17470 {
17471     switch (OperGet())
17472     {
17473         case GT_CNS_INT:
17474             // If we got here, this is a contribution to the constant part of the index.
17475             if (isConst)
17476             {
17477                 gtIntCon.gtFieldSeq =
17478                     comp->GetFieldSeqStore()->CreateSingleton(FieldSeqStore::ConstantIndexPseudoField);
17479             }
17480             return;
17481
17482         case GT_LCL_VAR:
17483             gtFlags |= GTF_VAR_ARR_INDEX;
17484             return;
17485
17486         case GT_ADD:
17487         case GT_SUB:
17488             gtOp.gtOp1->LabelIndex(comp, isConst);
17489             gtOp.gtOp2->LabelIndex(comp, isConst);
17490             break;
17491
17492         case GT_CAST:
17493             gtOp.gtOp1->LabelIndex(comp, isConst);
17494             break;
17495
17496         case GT_ARR_LENGTH:
17497             gtFlags |= GTF_ARRLEN_ARR_IDX;
17498             return;
17499
17500         default:
17501             // For all other operators, peel off one constant; and then label the other if it's also a constant.
17502             if (OperIsArithmetic() || OperIsCompare())
17503             {
17504                 if (gtOp.gtOp2->OperGet() == GT_CNS_INT)
17505                 {
17506                     gtOp.gtOp1->LabelIndex(comp, isConst);
17507                     break;
17508                 }
17509                 else if (gtOp.gtOp1->OperGet() == GT_CNS_INT)
17510                 {
17511                     gtOp.gtOp2->LabelIndex(comp, isConst);
17512                     break;
17513                 }
17514                 // Otherwise continue downward on both, labeling vars.
17515                 gtOp.gtOp1->LabelIndex(comp, false);
17516                 gtOp.gtOp2->LabelIndex(comp, false);
17517             }
17518             break;
17519     }
17520 }
17521
17522 // Note that the value of the below field doesn't matter; it exists only to provide a distinguished address.
17523 //
17524 // static
17525 FieldSeqNode FieldSeqStore::s_notAField(nullptr, nullptr);
17526
17527 // FieldSeqStore methods.
17528 FieldSeqStore::FieldSeqStore(CompAllocator alloc) : m_alloc(alloc), m_canonMap(new (alloc) FieldSeqNodeCanonMap(alloc))
17529 {
17530 }
17531
17532 FieldSeqNode* FieldSeqStore::CreateSingleton(CORINFO_FIELD_HANDLE fieldHnd)
17533 {
17534     FieldSeqNode  fsn(fieldHnd, nullptr);
17535     FieldSeqNode* res = nullptr;
17536     if (m_canonMap->Lookup(fsn, &res))
17537     {
17538         return res;
17539     }
17540     else
17541     {
17542         res  = m_alloc.allocate<FieldSeqNode>(1);
17543         *res = fsn;
17544         m_canonMap->Set(fsn, res);
17545         return res;
17546     }
17547 }
17548
17549 FieldSeqNode* FieldSeqStore::Append(FieldSeqNode* a, FieldSeqNode* b)
17550 {
17551     if (a == nullptr)
17552     {
17553         return b;
17554     }
17555     else if (a == NotAField())
17556     {
17557         return NotAField();
17558     }
17559     else if (b == nullptr)
17560     {
17561         return a;
17562     }
17563     else if (b == NotAField())
17564     {
17565         return NotAField();
17566         // Extremely special case for ConstantIndex pseudo-fields -- appending consecutive such
17567         // together collapse to one.
17568     }
17569     else if (a->m_next == nullptr && a->m_fieldHnd == ConstantIndexPseudoField &&
17570              b->m_fieldHnd == ConstantIndexPseudoField)
17571     {
17572         return b;
17573     }
17574     else
17575     {
17576         FieldSeqNode* tmp = Append(a->m_next, b);
17577         FieldSeqNode  fsn(a->m_fieldHnd, tmp);
17578         FieldSeqNode* res = nullptr;
17579         if (m_canonMap->Lookup(fsn, &res))
17580         {
17581             return res;
17582         }
17583         else
17584         {
17585             res  = m_alloc.allocate<FieldSeqNode>(1);
17586             *res = fsn;
17587             m_canonMap->Set(fsn, res);
17588             return res;
17589         }
17590     }
17591 }
17592
17593 // Static vars.
17594 int FieldSeqStore::FirstElemPseudoFieldStruct;
17595 int FieldSeqStore::ConstantIndexPseudoFieldStruct;
17596
17597 CORINFO_FIELD_HANDLE FieldSeqStore::FirstElemPseudoField =
17598     (CORINFO_FIELD_HANDLE)&FieldSeqStore::FirstElemPseudoFieldStruct;
17599 CORINFO_FIELD_HANDLE FieldSeqStore::ConstantIndexPseudoField =
17600     (CORINFO_FIELD_HANDLE)&FieldSeqStore::ConstantIndexPseudoFieldStruct;
17601
17602 bool FieldSeqNode::IsFirstElemFieldSeq()
17603 {
17604     // this must be non-null per ISO C++
17605     return m_fieldHnd == FieldSeqStore::FirstElemPseudoField;
17606 }
17607
17608 bool FieldSeqNode::IsConstantIndexFieldSeq()
17609 {
17610     // this must be non-null per ISO C++
17611     return m_fieldHnd == FieldSeqStore::ConstantIndexPseudoField;
17612 }
17613
17614 bool FieldSeqNode::IsPseudoField()
17615 {
17616     if (this == nullptr)
17617     {
17618         return false;
17619     }
17620     return m_fieldHnd == FieldSeqStore::FirstElemPseudoField || m_fieldHnd == FieldSeqStore::ConstantIndexPseudoField;
17621 }
17622
17623 #ifdef FEATURE_SIMD
17624 GenTreeSIMD* Compiler::gtNewSIMDNode(
17625     var_types type, GenTree* op1, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size)
17626 {
17627     assert(op1 != nullptr);
17628     SetOpLclRelatedToSIMDIntrinsic(op1);
17629
17630     return new (this, GT_SIMD) GenTreeSIMD(type, op1, simdIntrinsicID, baseType, size);
17631 }
17632
17633 GenTreeSIMD* Compiler::gtNewSIMDNode(
17634     var_types type, GenTree* op1, GenTree* op2, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size)
17635 {
17636     assert(op1 != nullptr);
17637     SetOpLclRelatedToSIMDIntrinsic(op1);
17638     SetOpLclRelatedToSIMDIntrinsic(op2);
17639
17640     return new (this, GT_SIMD) GenTreeSIMD(type, op1, op2, simdIntrinsicID, baseType, size);
17641 }
17642
17643 //-------------------------------------------------------------------
17644 // SetOpLclRelatedToSIMDIntrinsic: Determine if the tree has a local var that needs to be set
17645 // as used by a SIMD intrinsic, and if so, set that local var appropriately.
17646 //
17647 // Arguments:
17648 //     op - The tree, to be an operand of a new GT_SIMD node, to check.
17649 //
17650 void Compiler::SetOpLclRelatedToSIMDIntrinsic(GenTree* op)
17651 {
17652     if (op != nullptr)
17653     {
17654         if (op->OperIsLocal())
17655         {
17656             setLclRelatedToSIMDIntrinsic(op);
17657         }
17658         else if ((op->OperGet() == GT_OBJ) && (op->gtOp.gtOp1->OperGet() == GT_ADDR) &&
17659                  op->gtOp.gtOp1->gtOp.gtOp1->OperIsLocal())
17660         {
17661             setLclRelatedToSIMDIntrinsic(op->gtOp.gtOp1->gtOp.gtOp1);
17662         }
17663     }
17664 }
17665
17666 bool GenTree::isCommutativeSIMDIntrinsic()
17667 {
17668     assert(gtOper == GT_SIMD);
17669     switch (AsSIMD()->gtSIMDIntrinsicID)
17670     {
17671         case SIMDIntrinsicAdd:
17672         case SIMDIntrinsicBitwiseAnd:
17673         case SIMDIntrinsicBitwiseOr:
17674         case SIMDIntrinsicBitwiseXor:
17675         case SIMDIntrinsicEqual:
17676         case SIMDIntrinsicMax:
17677         case SIMDIntrinsicMin:
17678         case SIMDIntrinsicMul:
17679         case SIMDIntrinsicOpEquality:
17680         case SIMDIntrinsicOpInEquality:
17681             return true;
17682         default:
17683             return false;
17684     }
17685 }
17686 #endif // FEATURE_SIMD
17687
17688 #ifdef FEATURE_HW_INTRINSICS
17689 bool GenTree::isCommutativeHWIntrinsic() const
17690 {
17691     assert(gtOper == GT_HWIntrinsic);
17692
17693 #ifdef _TARGET_XARCH_
17694     return HWIntrinsicInfo::IsCommutative(AsHWIntrinsic()->gtHWIntrinsicId);
17695 #else
17696     return false;
17697 #endif // _TARGET_XARCH_
17698 }
17699
17700 bool GenTree::isContainableHWIntrinsic() const
17701 {
17702     assert(gtOper == GT_HWIntrinsic);
17703
17704 #ifdef _TARGET_XARCH_
17705     switch (AsHWIntrinsic()->gtHWIntrinsicId)
17706     {
17707         case NI_SSE_LoadAlignedVector128:
17708         case NI_SSE_LoadScalarVector128:
17709         case NI_SSE_LoadVector128:
17710         case NI_SSE2_LoadAlignedVector128:
17711         case NI_SSE2_LoadScalarVector128:
17712         case NI_SSE2_LoadVector128:
17713         case NI_AVX_LoadAlignedVector256:
17714         case NI_AVX_LoadVector256:
17715         {
17716             return true;
17717         }
17718
17719         default:
17720         {
17721             return false;
17722         }
17723     }
17724 #else
17725     return false;
17726 #endif // _TARGET_XARCH_
17727 }
17728
17729 bool GenTree::isRMWHWIntrinsic(Compiler* comp)
17730 {
17731     assert(gtOper == GT_HWIntrinsic);
17732     assert(comp != nullptr);
17733
17734 #ifdef _TARGET_XARCH_
17735     if (!comp->canUseVexEncoding())
17736     {
17737         return HWIntrinsicInfo::HasRMWSemantics(AsHWIntrinsic()->gtHWIntrinsicId);
17738     }
17739
17740     switch (AsHWIntrinsic()->gtHWIntrinsicId)
17741     {
17742         // TODO-XArch-Cleanup: Move this switch block to be table driven.
17743
17744         case NI_SSE42_Crc32:
17745         case NI_SSE42_X64_Crc32:
17746         case NI_FMA_MultiplyAdd:
17747         case NI_FMA_MultiplyAddNegated:
17748         case NI_FMA_MultiplyAddNegatedScalar:
17749         case NI_FMA_MultiplyAddScalar:
17750         case NI_FMA_MultiplyAddSubtract:
17751         case NI_FMA_MultiplySubtract:
17752         case NI_FMA_MultiplySubtractAdd:
17753         case NI_FMA_MultiplySubtractNegated:
17754         case NI_FMA_MultiplySubtractNegatedScalar:
17755         case NI_FMA_MultiplySubtractScalar:
17756         {
17757             return true;
17758         }
17759
17760         default:
17761         {
17762             return false;
17763         }
17764     }
17765 #else
17766     return false;
17767 #endif // _TARGET_XARCH_
17768 }
17769
17770 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(var_types      type,
17771                                                        NamedIntrinsic hwIntrinsicID,
17772                                                        var_types      baseType,
17773                                                        unsigned       size)
17774 {
17775     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, hwIntrinsicID, baseType, size);
17776 }
17777
17778 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(
17779     var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned simdSize)
17780 {
17781     SetOpLclRelatedToSIMDIntrinsic(op1);
17782
17783     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, op1, hwIntrinsicID, baseType, simdSize);
17784 }
17785
17786 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(
17787     var_types type, GenTree* op1, GenTree* op2, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned simdSize)
17788 {
17789     SetOpLclRelatedToSIMDIntrinsic(op1);
17790     SetOpLclRelatedToSIMDIntrinsic(op2);
17791
17792     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, op1, op2, hwIntrinsicID, baseType, simdSize);
17793 }
17794
17795 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(var_types      type,
17796                                                        GenTree*       op1,
17797                                                        GenTree*       op2,
17798                                                        GenTree*       op3,
17799                                                        NamedIntrinsic hwIntrinsicID,
17800                                                        var_types      baseType,
17801                                                        unsigned       size)
17802 {
17803     SetOpLclRelatedToSIMDIntrinsic(op1);
17804     SetOpLclRelatedToSIMDIntrinsic(op2);
17805     SetOpLclRelatedToSIMDIntrinsic(op3);
17806
17807     return new (this, GT_HWIntrinsic)
17808         GenTreeHWIntrinsic(type, gtNewArgList(op1, op2, op3), hwIntrinsicID, baseType, size);
17809 }
17810
17811 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(var_types      type,
17812                                                        GenTree*       op1,
17813                                                        GenTree*       op2,
17814                                                        GenTree*       op3,
17815                                                        GenTree*       op4,
17816                                                        NamedIntrinsic hwIntrinsicID,
17817                                                        var_types      baseType,
17818                                                        unsigned       size)
17819 {
17820     SetOpLclRelatedToSIMDIntrinsic(op1);
17821     SetOpLclRelatedToSIMDIntrinsic(op2);
17822     SetOpLclRelatedToSIMDIntrinsic(op3);
17823     SetOpLclRelatedToSIMDIntrinsic(op4);
17824
17825     return new (this, GT_HWIntrinsic)
17826         GenTreeHWIntrinsic(type, gtNewArgList(op1, op2, op3, op4), hwIntrinsicID, baseType, size);
17827 }
17828
17829 GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID)
17830 {
17831     SetOpLclRelatedToSIMDIntrinsic(op1);
17832
17833     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, op1, hwIntrinsicID, TYP_UNKNOWN, 0);
17834 }
17835
17836 GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(var_types      type,
17837                                                          GenTree*       op1,
17838                                                          GenTree*       op2,
17839                                                          NamedIntrinsic hwIntrinsicID)
17840 {
17841     SetOpLclRelatedToSIMDIntrinsic(op1);
17842     SetOpLclRelatedToSIMDIntrinsic(op2);
17843
17844     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, op1, op2, hwIntrinsicID, TYP_UNKNOWN, 0);
17845 }
17846
17847 GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(
17848     var_types type, GenTree* op1, GenTree* op2, GenTree* op3, NamedIntrinsic hwIntrinsicID)
17849 {
17850     SetOpLclRelatedToSIMDIntrinsic(op1);
17851     SetOpLclRelatedToSIMDIntrinsic(op2);
17852     SetOpLclRelatedToSIMDIntrinsic(op3);
17853
17854     return new (this, GT_HWIntrinsic)
17855         GenTreeHWIntrinsic(type, gtNewArgList(op1, op2, op3), hwIntrinsicID, TYP_UNKNOWN, 0);
17856 }
17857
17858 //---------------------------------------------------------------------------------------
17859 // gtNewMustThrowException:
17860 //    create a throw node (calling into JIT helper) that must be thrown.
17861 //    The result would be a comma node: COMMA(jithelperthrow(void), x) where x's type should be specified.
17862 //
17863 // Arguments
17864 //    helper      -  JIT helper ID
17865 //    type        -  return type of the node
17866 //
17867 // Return Value
17868 //    pointer to the throw node
17869 //
17870 GenTree* Compiler::gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd)
17871 {
17872     GenTreeCall* node = gtNewHelperCallNode(helper, TYP_VOID);
17873     node->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN;
17874     if (type != TYP_VOID)
17875     {
17876         unsigned dummyTemp = lvaGrabTemp(true DEBUGARG("dummy temp of must thrown exception"));
17877         if (type == TYP_STRUCT)
17878         {
17879             lvaSetStruct(dummyTemp, clsHnd, false);
17880             type = lvaTable[dummyTemp].lvType; // struct type is normalized
17881         }
17882         else
17883         {
17884             lvaTable[dummyTemp].lvType = type;
17885         }
17886         GenTree* dummyNode = gtNewLclvNode(dummyTemp, type);
17887         return gtNewOperNode(GT_COMMA, type, node, dummyNode);
17888     }
17889     return node;
17890 }
17891
17892 // Returns true for the HW Instrinsic instructions that have MemoryLoad semantics, false otherwise
17893 bool GenTreeHWIntrinsic::OperIsMemoryLoad()
17894 {
17895 #ifdef _TARGET_XARCH_
17896     // Some xarch instructions have MemoryLoad sematics
17897     HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(gtHWIntrinsicId);
17898     if (category == HW_Category_MemoryLoad)
17899     {
17900         return true;
17901     }
17902     else if (HWIntrinsicInfo::MaybeMemoryLoad(gtHWIntrinsicId))
17903     {
17904         // Some AVX intrinsic (without HW_Category_MemoryLoad) also have MemoryLoad semantics
17905         if (category == HW_Category_SIMDScalar)
17906         {
17907             // Avx2.BroadcastScalarToVector128/256 have vector and pointer overloads both, e.g.,
17908             // Vector128<byte> BroadcastScalarToVector128(Vector128<byte> value)
17909             // Vector128<byte> BroadcastScalarToVector128(byte* source)
17910             // So, we need to check the argument's type is memory-reference (TYP_I_IMPL) or not
17911             assert(HWIntrinsicInfo::lookupNumArgs(this) == 1);
17912             return (gtHWIntrinsicId == NI_AVX2_BroadcastScalarToVector128 ||
17913                     gtHWIntrinsicId == NI_AVX2_BroadcastScalarToVector256) &&
17914                    gtOp.gtOp1->TypeGet() == TYP_I_IMPL;
17915         }
17916         else if (category == HW_Category_IMM)
17917         {
17918             // Do we have less than 3 operands?
17919             if (HWIntrinsicInfo::lookupNumArgs(this) < 3)
17920             {
17921                 return false;
17922             }
17923             else // We have 3 or more operands/args
17924             {
17925                 // All the Avx2.Gather* are "load" instructions
17926                 if (HWIntrinsicInfo::isAVX2GatherIntrinsic(gtHWIntrinsicId))
17927                 {
17928                     return true;
17929                 }
17930
17931                 GenTreeArgList* argList = gtOp.gtOp1->AsArgList();
17932
17933                 // Avx/Avx2.InsertVector128 have vector and pointer overloads both, e.g.,
17934                 // Vector256<sbyte> InsertVector128(Vector256<sbyte> value, Vector128<sbyte> data, byte index)
17935                 // Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index)
17936                 // So, we need to check the second argument's type is memory-reference (TYP_I_IMPL) or not
17937                 if ((gtHWIntrinsicId == NI_AVX_InsertVector128 || gtHWIntrinsicId == NI_AVX2_InsertVector128) &&
17938                     (argList->Rest()->Current()->TypeGet() == TYP_I_IMPL)) // Is the type of the second arg TYP_I_IMPL?
17939                 {
17940                     // This is Avx/Avx2.InsertVector128
17941                     return true;
17942                 }
17943             }
17944         }
17945     }
17946 #endif // _TARGET_XARCH_
17947     return false;
17948 }
17949
17950 // Returns true for the HW Instrinsic instructions that have MemoryStore semantics, false otherwise
17951 bool GenTreeHWIntrinsic::OperIsMemoryStore()
17952 {
17953 #ifdef _TARGET_XARCH_
17954     // Some xarch instructions have MemoryStore sematics
17955     HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(gtHWIntrinsicId);
17956     if (category == HW_Category_MemoryStore)
17957     {
17958         return true;
17959     }
17960     else if (HWIntrinsicInfo::MaybeMemoryStore(gtHWIntrinsicId) && category == HW_Category_IMM)
17961     {
17962         // Some AVX intrinsic (without HW_Category_MemoryStore) also have MemoryStore semantics
17963
17964         // Avx/Avx2.InsertVector128 have vector and pointer overloads both, e.g.,
17965         // Vector128<sbyte> ExtractVector128(Vector256<sbyte> value, byte index)
17966         // void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index)
17967         // So, the 3-argument form is MemoryStore
17968         if ((HWIntrinsicInfo::lookupNumArgs(this) == 3) &&
17969             (gtHWIntrinsicId == NI_AVX_ExtractVector128 || gtHWIntrinsicId == NI_AVX2_ExtractVector128))
17970         {
17971             return true;
17972         }
17973     }
17974 #endif // _TARGET_XARCH_
17975     return false;
17976 }
17977
17978 // Returns true for the HW Instrinsic instructions that have MemoryLoad semantics, false otherwise
17979 bool GenTreeHWIntrinsic::OperIsMemoryLoadOrStore()
17980 {
17981 #ifdef _TARGET_XARCH_
17982     return OperIsMemoryLoad() || OperIsMemoryStore();
17983 #endif // _TARGET_XARCH_
17984     return false;
17985 }
17986
17987 #endif // FEATURE_HW_INTRINSICS
17988
17989 //---------------------------------------------------------------------------------------
17990 // InitializeStructReturnType:
17991 //    Initialize the Return Type Descriptor for a method that returns a struct type
17992 //
17993 // Arguments
17994 //    comp        -  Compiler Instance
17995 //    retClsHnd   -  VM handle to the struct type returned by the method
17996 //
17997 // Return Value
17998 //    None
17999 //
18000 void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd)
18001 {
18002     assert(!m_inited);
18003
18004 #if FEATURE_MULTIREG_RET
18005
18006     assert(retClsHnd != NO_CLASS_HANDLE);
18007     unsigned structSize = comp->info.compCompHnd->getClassSize(retClsHnd);
18008
18009     Compiler::structPassingKind howToReturnStruct;
18010     var_types                   returnType = comp->getReturnTypeForStruct(retClsHnd, &howToReturnStruct, structSize);
18011
18012     switch (howToReturnStruct)
18013     {
18014         case Compiler::SPK_EnclosingType:
18015             m_isEnclosingType = true;
18016             __fallthrough;
18017
18018         case Compiler::SPK_PrimitiveType:
18019         {
18020             assert(returnType != TYP_UNKNOWN);
18021             assert(!varTypeIsStruct(returnType));
18022             m_regType[0] = returnType;
18023             break;
18024         }
18025
18026         case Compiler::SPK_ByValueAsHfa:
18027         {
18028             assert(varTypeIsStruct(returnType));
18029             var_types hfaType = comp->GetHfaType(retClsHnd);
18030
18031             // We should have an hfa struct type
18032             assert(varTypeIsFloating(hfaType));
18033
18034             // Note that the retail build issues a warning about a potential divsion by zero without this Max function
18035             unsigned elemSize = Max((unsigned)1, EA_SIZE_IN_BYTES(emitActualTypeSize(hfaType)));
18036
18037             // The size of this struct should be evenly divisible by elemSize
18038             assert((structSize % elemSize) == 0);
18039
18040             unsigned hfaCount = (structSize / elemSize);
18041             for (unsigned i = 0; i < hfaCount; ++i)
18042             {
18043                 m_regType[i] = hfaType;
18044             }
18045
18046             if (comp->compFloatingPointUsed == false)
18047             {
18048                 comp->compFloatingPointUsed = true;
18049             }
18050             break;
18051         }
18052
18053         case Compiler::SPK_ByValue:
18054         {
18055             assert(varTypeIsStruct(returnType));
18056
18057 #ifdef UNIX_AMD64_ABI
18058
18059             SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
18060             comp->eeGetSystemVAmd64PassStructInRegisterDescriptor(retClsHnd, &structDesc);
18061
18062             assert(structDesc.passedInRegisters);
18063             for (int i = 0; i < structDesc.eightByteCount; i++)
18064             {
18065                 assert(i < MAX_RET_REG_COUNT);
18066                 m_regType[i] = comp->GetEightByteType(structDesc, i);
18067             }
18068
18069 #elif defined(_TARGET_ARM64_)
18070
18071             // a non-HFA struct returned using two registers
18072             //
18073             assert((structSize > TARGET_POINTER_SIZE) && (structSize <= (2 * TARGET_POINTER_SIZE)));
18074
18075             BYTE gcPtrs[2] = {TYPE_GC_NONE, TYPE_GC_NONE};
18076             comp->info.compCompHnd->getClassGClayout(retClsHnd, &gcPtrs[0]);
18077             for (unsigned i = 0; i < 2; ++i)
18078             {
18079                 m_regType[i] = comp->getJitGCType(gcPtrs[i]);
18080             }
18081
18082 #else //  _TARGET_XXX_
18083
18084             // This target needs support here!
18085             //
18086             NYI("Unsupported TARGET returning a TYP_STRUCT in InitializeStructReturnType");
18087
18088 #endif // UNIX_AMD64_ABI
18089
18090             break; // for case SPK_ByValue
18091         }
18092
18093         case Compiler::SPK_ByReference:
18094
18095             // We are returning using the return buffer argument
18096             // There are no return registers
18097             break;
18098
18099         default:
18100
18101             unreached(); // By the contract of getReturnTypeForStruct we should never get here.
18102
18103     } // end of switch (howToReturnStruct)
18104
18105 #endif //  FEATURE_MULTIREG_RET
18106
18107 #ifdef DEBUG
18108     m_inited = true;
18109 #endif
18110 }
18111
18112 //---------------------------------------------------------------------------------------
18113 // InitializeLongReturnType:
18114 //    Initialize the Return Type Descriptor for a method that returns a TYP_LONG
18115 //
18116 // Arguments
18117 //    comp        -  Compiler Instance
18118 //
18119 // Return Value
18120 //    None
18121 //
18122 void ReturnTypeDesc::InitializeLongReturnType(Compiler* comp)
18123 {
18124 #if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
18125
18126     // Setups up a ReturnTypeDesc for returning a long using two registers
18127     //
18128     assert(MAX_RET_REG_COUNT >= 2);
18129     m_regType[0] = TYP_INT;
18130     m_regType[1] = TYP_INT;
18131
18132 #else // not (_TARGET_X86_ or _TARGET_ARM_)
18133
18134     m_regType[0] = TYP_LONG;
18135
18136 #endif // _TARGET_X86_ or _TARGET_ARM_
18137
18138 #ifdef DEBUG
18139     m_inited = true;
18140 #endif
18141 }
18142
18143 //-------------------------------------------------------------------
18144 // GetABIReturnReg:  Return ith return register as per target ABI
18145 //
18146 // Arguments:
18147 //     idx   -   Index of the return register.
18148 //               The first return register has an index of 0 and so on.
18149 //
18150 // Return Value:
18151 //     Returns ith return register as per target ABI.
18152 //
18153 // Notes:
18154 //     x86 and ARM return long in multiple registers.
18155 //     ARM and ARM64 return HFA struct in multiple registers.
18156 //
18157 regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx)
18158 {
18159     unsigned count = GetReturnRegCount();
18160     assert(idx < count);
18161
18162     regNumber resultReg = REG_NA;
18163
18164 #ifdef UNIX_AMD64_ABI
18165     var_types regType0 = GetReturnRegType(0);
18166
18167     if (idx == 0)
18168     {
18169         if (varTypeIsIntegralOrI(regType0))
18170         {
18171             resultReg = REG_INTRET;
18172         }
18173         else
18174         {
18175             noway_assert(varTypeIsFloating(regType0));
18176             resultReg = REG_FLOATRET;
18177         }
18178     }
18179     else if (idx == 1)
18180     {
18181         var_types regType1 = GetReturnRegType(1);
18182
18183         if (varTypeIsIntegralOrI(regType1))
18184         {
18185             if (varTypeIsIntegralOrI(regType0))
18186             {
18187                 resultReg = REG_INTRET_1;
18188             }
18189             else
18190             {
18191                 resultReg = REG_INTRET;
18192             }
18193         }
18194         else
18195         {
18196             noway_assert(varTypeIsFloating(regType1));
18197
18198             if (varTypeIsFloating(regType0))
18199             {
18200                 resultReg = REG_FLOATRET_1;
18201             }
18202             else
18203             {
18204                 resultReg = REG_FLOATRET;
18205             }
18206         }
18207     }
18208
18209 #elif defined(_TARGET_X86_)
18210
18211     if (idx == 0)
18212     {
18213         resultReg = REG_LNGRET_LO;
18214     }
18215     else if (idx == 1)
18216     {
18217         resultReg = REG_LNGRET_HI;
18218     }
18219
18220 #elif defined(_TARGET_ARM_)
18221
18222     var_types regType = GetReturnRegType(idx);
18223     if (varTypeIsIntegralOrI(regType))
18224     {
18225         // Ints are returned in one return register.
18226         // Longs are returned in two return registers.
18227         if (idx == 0)
18228         {
18229             resultReg = REG_LNGRET_LO;
18230         }
18231         else if (idx == 1)
18232         {
18233             resultReg = REG_LNGRET_HI;
18234         }
18235     }
18236     else
18237     {
18238         // Floats are returned in one return register (f0).
18239         // Doubles are returned in one return register (d0).
18240         // Structs are returned in four registers with HFAs.
18241         assert(idx < MAX_RET_REG_COUNT); // Up to 4 return registers for HFA's
18242         if (regType == TYP_DOUBLE)
18243         {
18244             resultReg = (regNumber)((unsigned)(REG_FLOATRET) + idx * 2); // d0, d1, d2 or d3
18245         }
18246         else
18247         {
18248             resultReg = (regNumber)((unsigned)(REG_FLOATRET) + idx); // f0, f1, f2 or f3
18249         }
18250     }
18251
18252 #elif defined(_TARGET_ARM64_)
18253
18254     var_types regType = GetReturnRegType(idx);
18255     if (varTypeIsIntegralOrI(regType))
18256     {
18257         noway_assert(idx < 2);                              // Up to 2 return registers for 16-byte structs
18258         resultReg = (idx == 0) ? REG_INTRET : REG_INTRET_1; // X0 or X1
18259     }
18260     else
18261     {
18262         noway_assert(idx < 4);                                   // Up to 4 return registers for HFA's
18263         resultReg = (regNumber)((unsigned)(REG_FLOATRET) + idx); // V0, V1, V2 or V3
18264     }
18265
18266 #endif // TARGET_XXX
18267
18268     assert(resultReg != REG_NA);
18269     return resultReg;
18270 }
18271
18272 //--------------------------------------------------------------------------------
18273 // GetABIReturnRegs: get the mask of return registers as per target arch ABI.
18274 //
18275 // Arguments:
18276 //    None
18277 //
18278 // Return Value:
18279 //    reg mask of return registers in which the return type is returned.
18280 //
18281 // Note:
18282 //    This routine can be used when the caller is not particular about the order
18283 //    of return registers and wants to know the set of return registers.
18284 //
18285 // static
18286 regMaskTP ReturnTypeDesc::GetABIReturnRegs()
18287 {
18288     regMaskTP resultMask = RBM_NONE;
18289
18290     unsigned count = GetReturnRegCount();
18291     for (unsigned i = 0; i < count; ++i)
18292     {
18293         resultMask |= genRegMask(GetABIReturnReg(i));
18294     }
18295
18296     return resultMask;
18297 }
18298
18299 //------------------------------------------------------------------------
18300 // The following functions manage the gtRsvdRegs set of temporary registers
18301 // created by LSRA during code generation.
18302
18303 //------------------------------------------------------------------------
18304 // AvailableTempRegCount: return the number of available temporary registers in the (optional) given set
18305 // (typically, RBM_ALLINT or RBM_ALLFLOAT).
18306 //
18307 // Arguments:
18308 //    mask - (optional) Check for available temporary registers only in this set.
18309 //
18310 // Return Value:
18311 //    Count of available temporary registers in given set.
18312 //
18313 unsigned GenTree::AvailableTempRegCount(regMaskTP mask /* = (regMaskTP)-1 */) const
18314 {
18315     return genCountBits(gtRsvdRegs & mask);
18316 }
18317
18318 //------------------------------------------------------------------------
18319 // GetSingleTempReg: There is expected to be exactly one available temporary register
18320 // in the given mask in the gtRsvdRegs set. Get that register. No future calls to get
18321 // a temporary register are expected. Removes the register from the set, but only in
18322 // DEBUG to avoid doing unnecessary work in non-DEBUG builds.
18323 //
18324 // Arguments:
18325 //    mask - (optional) Get an available temporary register only in this set.
18326 //
18327 // Return Value:
18328 //    Available temporary register in given mask.
18329 //
18330 regNumber GenTree::GetSingleTempReg(regMaskTP mask /* = (regMaskTP)-1 */)
18331 {
18332     regMaskTP availableSet = gtRsvdRegs & mask;
18333     assert(genCountBits(availableSet) == 1);
18334     regNumber tempReg = genRegNumFromMask(availableSet);
18335     INDEBUG(gtRsvdRegs &= ~availableSet;) // Remove the register from the set, so it can't be used again.
18336     return tempReg;
18337 }
18338
18339 //------------------------------------------------------------------------
18340 // ExtractTempReg: Find the lowest number temporary register from the gtRsvdRegs set
18341 // that is also in the optional given mask (typically, RBM_ALLINT or RBM_ALLFLOAT),
18342 // and return it. Remove this register from the temporary register set, so it won't
18343 // be returned again.
18344 //
18345 // Arguments:
18346 //    mask - (optional) Extract an available temporary register only in this set.
18347 //
18348 // Return Value:
18349 //    Available temporary register in given mask.
18350 //
18351 regNumber GenTree::ExtractTempReg(regMaskTP mask /* = (regMaskTP)-1 */)
18352 {
18353     regMaskTP availableSet = gtRsvdRegs & mask;
18354     assert(genCountBits(availableSet) >= 1);
18355     regMaskTP tempRegMask = genFindLowestBit(availableSet);
18356     gtRsvdRegs &= ~tempRegMask;
18357     return genRegNumFromMask(tempRegMask);
18358 }